xref: /reactos/dll/win32/kernel32/client/file/npipe.c (revision d6d30f9e)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:         ReactOS Win32 Kernel Library
4c2c66affSColin Finck  * FILE:            dll/win32/kernel32/client/file/npipe.c
5c2c66affSColin Finck  * PURPOSE:         Named Pipe Functions
6c2c66affSColin Finck  * PROGRAMMER:      Alex Ionescu (alex@relsoft.net)
7c2c66affSColin Finck  *                  Ariadne ( ariadne@xs4all.nl)
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10c2c66affSColin Finck /* INCLUDES *******************************************************************/
11c2c66affSColin Finck 
12c2c66affSColin Finck #include <k32.h>
13c2c66affSColin Finck #define NDEBUG
14c2c66affSColin Finck #include <debug.h>
15c2c66affSColin Finck DEBUG_CHANNEL(kernel32file);
16c2c66affSColin Finck 
17c2c66affSColin Finck /* GLOBALS ********************************************************************/
18c2c66affSColin Finck 
19c2c66affSColin Finck LONG ProcessPipeId;
20c2c66affSColin Finck 
21c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
22c2c66affSColin Finck 
2334c39a13SPierre Schweitzer /*
2434c39a13SPierre Schweitzer  * @implemented
2534c39a13SPierre Schweitzer  */
2619cef780SPierre Schweitzer static
2719cef780SPierre Schweitzer BOOL
NpGetUserNamep(HANDLE hNamedPipe,LPWSTR lpUserName,DWORD nMaxUserNameSize)2819cef780SPierre Schweitzer NpGetUserNamep(HANDLE hNamedPipe,
2919cef780SPierre Schweitzer                LPWSTR lpUserName,
3019cef780SPierre Schweitzer                DWORD nMaxUserNameSize)
3119cef780SPierre Schweitzer {
3234c39a13SPierre Schweitzer     BOOL Ret;
3334c39a13SPierre Schweitzer     HANDLE hToken;
3434c39a13SPierre Schweitzer     HMODULE hAdvapi;
3534c39a13SPierre Schweitzer     NTSTATUS Status;
3634c39a13SPierre Schweitzer     BOOL (WINAPI *pRevertToSelf)(void);
3734c39a13SPierre Schweitzer     BOOL (WINAPI *pGetUserNameW)(LPWSTR lpBuffer, LPDWORD lpnSize);
3834c39a13SPierre Schweitzer     BOOL (WINAPI *pImpersonateNamedPipeClient)(HANDLE hNamedPipe);
3934c39a13SPierre Schweitzer 
4034c39a13SPierre Schweitzer     /* Open advapi, we'll funcs from it */
4134c39a13SPierre Schweitzer     hAdvapi = LoadLibraryW(L"advapi32.dll");
4234c39a13SPierre Schweitzer     if (hAdvapi == NULL)
4334c39a13SPierre Schweitzer     {
4434c39a13SPierre Schweitzer         return FALSE;
4534c39a13SPierre Schweitzer     }
4634c39a13SPierre Schweitzer 
4734c39a13SPierre Schweitzer     /* Import the three required functions */
480add5d0aSPierre Schweitzer     pRevertToSelf = (BOOL (WINAPI *)(void))GetProcAddress(hAdvapi, "RevertToSelf");
490add5d0aSPierre Schweitzer     pGetUserNameW = (BOOL (WINAPI *)(LPWSTR, LPDWORD))GetProcAddress(hAdvapi, "GetUserNameW");
500add5d0aSPierre Schweitzer     pImpersonateNamedPipeClient = (BOOL (WINAPI *)(HANDLE))GetProcAddress(hAdvapi, "ImpersonateNamedPipeClient");
5134c39a13SPierre Schweitzer     /* If any couldn't be found, fail */
5234c39a13SPierre Schweitzer     if (pRevertToSelf == NULL || pGetUserNameW == NULL || pImpersonateNamedPipeClient == NULL)
5334c39a13SPierre Schweitzer     {
5434c39a13SPierre Schweitzer         FreeLibrary(hAdvapi);
5534c39a13SPierre Schweitzer         return FALSE;
5634c39a13SPierre Schweitzer     }
5734c39a13SPierre Schweitzer 
5834c39a13SPierre Schweitzer     /* Now, open the thread token for impersonation */
5934c39a13SPierre Schweitzer     Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_IMPERSONATE, TRUE, &hToken);
6034c39a13SPierre Schweitzer     /* Try to impersonate the pipe client */
6134c39a13SPierre Schweitzer     if (pImpersonateNamedPipeClient(hNamedPipe))
6234c39a13SPierre Schweitzer     {
6334c39a13SPierre Schweitzer         DWORD lpnSize;
6434c39a13SPierre Schweitzer 
6534c39a13SPierre Schweitzer         /* It worked, get the user name */
6634c39a13SPierre Schweitzer         lpnSize = nMaxUserNameSize;
6734c39a13SPierre Schweitzer         Ret = pGetUserNameW(lpUserName, &lpnSize);
6834c39a13SPierre Schweitzer         /* Failed to get the thread token? Revert to self */
6934c39a13SPierre Schweitzer         if (!NT_SUCCESS(Status))
7034c39a13SPierre Schweitzer         {
7134c39a13SPierre Schweitzer             pRevertToSelf();
7234c39a13SPierre Schweitzer 
7334c39a13SPierre Schweitzer             FreeLibrary(hAdvapi);
7434c39a13SPierre Schweitzer             return Ret;
7534c39a13SPierre Schweitzer         }
7634c39a13SPierre Schweitzer 
7734c39a13SPierre Schweitzer         /* Restore the thread token */
7834c39a13SPierre Schweitzer         Status = NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken,
79*d6d30f9eSHermès Bélusca-Maïto                                         &hToken, sizeof(hToken));
8034c39a13SPierre Schweitzer         /* We cannot fail closing the thread token! */
8134c39a13SPierre Schweitzer         if (!CloseHandle(hToken))
8234c39a13SPierre Schweitzer         {
8334c39a13SPierre Schweitzer             ASSERT(FALSE);
8434c39a13SPierre Schweitzer         }
8534c39a13SPierre Schweitzer 
8634c39a13SPierre Schweitzer         /* Set last error if it failed */
8734c39a13SPierre Schweitzer         if (!NT_SUCCESS(Status))
8834c39a13SPierre Schweitzer         {
8934c39a13SPierre Schweitzer             BaseSetLastNTError(Status);
9034c39a13SPierre Schweitzer         }
9134c39a13SPierre Schweitzer     }
9234c39a13SPierre Schweitzer     else
9334c39a13SPierre Schweitzer     {
9434c39a13SPierre Schweitzer         /* If opening the thread token succeed, close it */
9534c39a13SPierre Schweitzer         if (NT_SUCCESS(Status))
9634c39a13SPierre Schweitzer         {
9734c39a13SPierre Schweitzer             /* We cannot fail closing it! */
9834c39a13SPierre Schweitzer             if (!CloseHandle(hToken))
9934c39a13SPierre Schweitzer             {
10034c39a13SPierre Schweitzer                 ASSERT(FALSE);
10134c39a13SPierre Schweitzer             }
10234c39a13SPierre Schweitzer         }
10334c39a13SPierre Schweitzer 
10434c39a13SPierre Schweitzer         Ret = FALSE;
10534c39a13SPierre Schweitzer     }
10634c39a13SPierre Schweitzer 
10734c39a13SPierre Schweitzer     FreeLibrary(hAdvapi);
10834c39a13SPierre Schweitzer     return Ret;
10919cef780SPierre Schweitzer }
11019cef780SPierre Schweitzer 
11119cef780SPierre Schweitzer 
112c2c66affSColin Finck /*
113c2c66affSColin Finck  * @implemented
114c2c66affSColin Finck  */
115c2c66affSColin Finck BOOL
116c2c66affSColin Finck WINAPI
CreatePipe(PHANDLE hReadPipe,PHANDLE hWritePipe,LPSECURITY_ATTRIBUTES lpPipeAttributes,DWORD nSize)117c2c66affSColin Finck CreatePipe(PHANDLE hReadPipe,
118c2c66affSColin Finck            PHANDLE hWritePipe,
119c2c66affSColin Finck            LPSECURITY_ATTRIBUTES lpPipeAttributes,
120c2c66affSColin Finck            DWORD nSize)
121c2c66affSColin Finck {
122c2c66affSColin Finck     WCHAR Buffer[64];
123c2c66affSColin Finck     UNICODE_STRING PipeName;
124c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
125c2c66affSColin Finck     IO_STATUS_BLOCK StatusBlock;
126c2c66affSColin Finck     LARGE_INTEGER DefaultTimeout;
127c2c66affSColin Finck     NTSTATUS Status;
128c2c66affSColin Finck     HANDLE ReadPipeHandle;
129c2c66affSColin Finck     HANDLE WritePipeHandle;
130c2c66affSColin Finck     LONG PipeId;
131c2c66affSColin Finck     ULONG Attributes;
132c2c66affSColin Finck     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
133c2c66affSColin Finck 
134c2c66affSColin Finck     /* Set the timeout to 120 seconds */
135c2c66affSColin Finck     DefaultTimeout.QuadPart = -1200000000;
136c2c66affSColin Finck 
137c2c66affSColin Finck     /* Use default buffer size if desired */
138c2c66affSColin Finck     if (!nSize) nSize = 0x1000;
139c2c66affSColin Finck 
140c2c66affSColin Finck     /* Increase the Pipe ID */
141c2c66affSColin Finck     PipeId = InterlockedIncrement(&ProcessPipeId);
142c2c66affSColin Finck 
143c2c66affSColin Finck     /* Create the pipe name */
144c2c66affSColin Finck     swprintf(Buffer,
1454f0a158aSTimo Kreuzer              L"\\Device\\NamedPipe\\Win32Pipes.%p.%08x",
146c2c66affSColin Finck              NtCurrentTeb()->ClientId.UniqueProcess,
147c2c66affSColin Finck              PipeId);
148c2c66affSColin Finck     RtlInitUnicodeString(&PipeName, Buffer);
149c2c66affSColin Finck 
150c2c66affSColin Finck     /* Always use case insensitive */
151c2c66affSColin Finck     Attributes = OBJ_CASE_INSENSITIVE;
152c2c66affSColin Finck 
153c2c66affSColin Finck     /* Check if we got attributes */
154c2c66affSColin Finck     if (lpPipeAttributes)
155c2c66affSColin Finck     {
156c2c66affSColin Finck         /* Use the attributes' SD instead */
157c2c66affSColin Finck         SecurityDescriptor = lpPipeAttributes->lpSecurityDescriptor;
158c2c66affSColin Finck 
159c2c66affSColin Finck         /* Set OBJ_INHERIT if requested */
160c2c66affSColin Finck         if (lpPipeAttributes->bInheritHandle) Attributes |= OBJ_INHERIT;
161c2c66affSColin Finck     }
162c2c66affSColin Finck 
163c2c66affSColin Finck     /* Initialize the attributes */
164c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
165c2c66affSColin Finck                                &PipeName,
166c2c66affSColin Finck                                Attributes,
167c2c66affSColin Finck                                NULL,
168c2c66affSColin Finck                                SecurityDescriptor);
169c2c66affSColin Finck 
170c2c66affSColin Finck     /* Create the named pipe */
171c2c66affSColin Finck     Status = NtCreateNamedPipeFile(&ReadPipeHandle,
172c2c66affSColin Finck                                    GENERIC_READ | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
173c2c66affSColin Finck                                    &ObjectAttributes,
174c2c66affSColin Finck                                    &StatusBlock,
175c2c66affSColin Finck                                    FILE_SHARE_READ | FILE_SHARE_WRITE,
176c2c66affSColin Finck                                    FILE_CREATE,
177c2c66affSColin Finck                                    FILE_SYNCHRONOUS_IO_NONALERT,
178c2c66affSColin Finck                                    FILE_PIPE_BYTE_STREAM_TYPE,
179c2c66affSColin Finck                                    FILE_PIPE_BYTE_STREAM_MODE,
180c2c66affSColin Finck                                    FILE_PIPE_QUEUE_OPERATION,
181c2c66affSColin Finck                                    1,
182c2c66affSColin Finck                                    nSize,
183c2c66affSColin Finck                                    nSize,
184c2c66affSColin Finck                                    &DefaultTimeout);
185c2c66affSColin Finck     if (!NT_SUCCESS(Status))
186c2c66affSColin Finck     {
187c2c66affSColin Finck         /* Convert error and fail */
188c2c66affSColin Finck         WARN("Status: %lx\n", Status);
189c2c66affSColin Finck         BaseSetLastNTError(Status);
190c2c66affSColin Finck         return FALSE;
191c2c66affSColin Finck     }
192c2c66affSColin Finck 
193c2c66affSColin Finck     /* Now try opening it for write access */
194c2c66affSColin Finck     Status = NtOpenFile(&WritePipeHandle,
195c2c66affSColin Finck                         FILE_GENERIC_WRITE,
196c2c66affSColin Finck                         &ObjectAttributes,
197c2c66affSColin Finck                         &StatusBlock,
198c2c66affSColin Finck                         FILE_SHARE_READ,
199c2c66affSColin Finck                         FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
200c2c66affSColin Finck     if (!NT_SUCCESS(Status))
201c2c66affSColin Finck     {
202c2c66affSColin Finck         /* Convert error and fail */
203c2c66affSColin Finck         WARN("Status: %lx\n", Status);
204c2c66affSColin Finck         NtClose(ReadPipeHandle);
205c2c66affSColin Finck         BaseSetLastNTError(Status);
206c2c66affSColin Finck         return FALSE;
207c2c66affSColin Finck     }
208c2c66affSColin Finck 
209c2c66affSColin Finck     /* Return both handles */
210c2c66affSColin Finck     *hReadPipe = ReadPipeHandle;
211c2c66affSColin Finck     *hWritePipe = WritePipeHandle;
212c2c66affSColin Finck     return TRUE;
213c2c66affSColin Finck }
214c2c66affSColin Finck 
215c2c66affSColin Finck /*
216c2c66affSColin Finck  * @implemented
217c2c66affSColin Finck  */
218c2c66affSColin Finck HANDLE
219c2c66affSColin Finck WINAPI
CreateNamedPipeA(LPCSTR lpName,DWORD dwOpenMode,DWORD dwPipeMode,DWORD nMaxInstances,DWORD nOutBufferSize,DWORD nInBufferSize,DWORD nDefaultTimeOut,LPSECURITY_ATTRIBUTES lpSecurityAttributes)220c2c66affSColin Finck CreateNamedPipeA(LPCSTR lpName,
221c2c66affSColin Finck                  DWORD dwOpenMode,
222c2c66affSColin Finck                  DWORD dwPipeMode,
223c2c66affSColin Finck                  DWORD nMaxInstances,
224c2c66affSColin Finck                  DWORD nOutBufferSize,
225c2c66affSColin Finck                  DWORD nInBufferSize,
226c2c66affSColin Finck                  DWORD nDefaultTimeOut,
227c2c66affSColin Finck                  LPSECURITY_ATTRIBUTES lpSecurityAttributes)
228c2c66affSColin Finck {
229c2c66affSColin Finck     /* Call the W(ide) function */
230c2c66affSColin Finck     ConvertWin32AnsiChangeApiToUnicodeApi(CreateNamedPipe,
231c2c66affSColin Finck                                           lpName,
232c2c66affSColin Finck                                           dwOpenMode,
233c2c66affSColin Finck                                           dwPipeMode,
234c2c66affSColin Finck                                           nMaxInstances,
235c2c66affSColin Finck                                           nOutBufferSize,
236c2c66affSColin Finck                                           nInBufferSize,
237c2c66affSColin Finck                                           nDefaultTimeOut,
238c2c66affSColin Finck                                           lpSecurityAttributes);
239c2c66affSColin Finck }
240c2c66affSColin Finck 
241c2c66affSColin Finck /*
242c2c66affSColin Finck  * @implemented
243c2c66affSColin Finck  */
244c2c66affSColin Finck HANDLE
245c2c66affSColin Finck WINAPI
CreateNamedPipeW(LPCWSTR lpName,DWORD dwOpenMode,DWORD dwPipeMode,DWORD nMaxInstances,DWORD nOutBufferSize,DWORD nInBufferSize,DWORD nDefaultTimeOut,LPSECURITY_ATTRIBUTES lpSecurityAttributes)246c2c66affSColin Finck CreateNamedPipeW(LPCWSTR lpName,
247c2c66affSColin Finck                  DWORD dwOpenMode,
248c2c66affSColin Finck                  DWORD dwPipeMode,
249c2c66affSColin Finck                  DWORD nMaxInstances,
250c2c66affSColin Finck                  DWORD nOutBufferSize,
251c2c66affSColin Finck                  DWORD nInBufferSize,
252c2c66affSColin Finck                  DWORD nDefaultTimeOut,
253c2c66affSColin Finck                  LPSECURITY_ATTRIBUTES lpSecurityAttributes)
254c2c66affSColin Finck {
255c2c66affSColin Finck     UNICODE_STRING NamedPipeName;
256c2c66affSColin Finck     BOOL Result;
257c2c66affSColin Finck     NTSTATUS Status;
258c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
259c2c66affSColin Finck     HANDLE PipeHandle;
260c2c66affSColin Finck     ACCESS_MASK DesiredAccess;
261c2c66affSColin Finck     ULONG CreateOptions = 0;
262c2c66affSColin Finck     ULONG WriteModeMessage;
263c2c66affSColin Finck     ULONG ReadModeMessage;
264c2c66affSColin Finck     ULONG NonBlocking;
265c2c66affSColin Finck     IO_STATUS_BLOCK Iosb;
266c2c66affSColin Finck     ULONG ShareAccess = 0, Attributes;
267c2c66affSColin Finck     LARGE_INTEGER DefaultTimeOut;
268c2c66affSColin Finck     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
269c2c66affSColin Finck 
270c2c66affSColin Finck     /* Check for valid instances */
271c2c66affSColin Finck     if (nMaxInstances == 0 || nMaxInstances > PIPE_UNLIMITED_INSTANCES)
272c2c66affSColin Finck     {
273c2c66affSColin Finck         /* Fail */
274c2c66affSColin Finck         SetLastError(ERROR_INVALID_PARAMETER);
275c2c66affSColin Finck         return INVALID_HANDLE_VALUE;
276c2c66affSColin Finck     }
277c2c66affSColin Finck 
278c2c66affSColin Finck     /* Convert to NT syntax */
279c2c66affSColin Finck     if (nMaxInstances == PIPE_UNLIMITED_INSTANCES)
280c2c66affSColin Finck         nMaxInstances = -1;
281c2c66affSColin Finck 
282c2c66affSColin Finck     /* Convert the name */
283c2c66affSColin Finck     Result = RtlDosPathNameToNtPathName_U(lpName,
284c2c66affSColin Finck                                            &NamedPipeName,
285c2c66affSColin Finck                                            NULL,
286c2c66affSColin Finck                                            NULL);
287c2c66affSColin Finck     if (!Result)
288c2c66affSColin Finck     {
289c2c66affSColin Finck         /* Conversion failed */
290c2c66affSColin Finck         SetLastError(ERROR_PATH_NOT_FOUND);
291c2c66affSColin Finck         return INVALID_HANDLE_VALUE;
292c2c66affSColin Finck     }
293c2c66affSColin Finck 
294c2c66affSColin Finck     TRACE("Pipe name: %wZ\n", &NamedPipeName);
295c2c66affSColin Finck     TRACE("Pipe name: %S\n", NamedPipeName.Buffer);
296c2c66affSColin Finck 
297c2c66affSColin Finck     /* Always case insensitive, check if we got extra attributes */
298c2c66affSColin Finck     Attributes = OBJ_CASE_INSENSITIVE;
299c2c66affSColin Finck     if (lpSecurityAttributes)
300c2c66affSColin Finck     {
301c2c66affSColin Finck         /* We did; get the security descriptor */
302c2c66affSColin Finck         SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
303c2c66affSColin Finck 
304c2c66affSColin Finck         /* And check if this is pipe's handle will beinheritable */
305c2c66affSColin Finck         if (lpSecurityAttributes->bInheritHandle)
306c2c66affSColin Finck             Attributes |= OBJ_INHERIT;
307c2c66affSColin Finck     }
308c2c66affSColin Finck 
309c2c66affSColin Finck     /* Now we can initialize the object attributes */
310c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
311c2c66affSColin Finck                                &NamedPipeName,
312c2c66affSColin Finck                                Attributes,
313c2c66affSColin Finck                                NULL,
314c2c66affSColin Finck                                SecurityDescriptor);
315c2c66affSColin Finck 
316c2c66affSColin Finck     /* Setup the default Desired Access */
317c2c66affSColin Finck     DesiredAccess = SYNCHRONIZE | (dwOpenMode & (WRITE_DAC |
318c2c66affSColin Finck                                                  WRITE_OWNER |
319c2c66affSColin Finck                                                  ACCESS_SYSTEM_SECURITY));
320c2c66affSColin Finck 
321c2c66affSColin Finck     /* Convert to NT Create Flags */
322c2c66affSColin Finck     if (dwOpenMode & FILE_FLAG_WRITE_THROUGH)
323c2c66affSColin Finck     {
324c2c66affSColin Finck         CreateOptions |= FILE_WRITE_THROUGH;
325c2c66affSColin Finck     }
326c2c66affSColin Finck 
327c2c66affSColin Finck     if (!(dwOpenMode & FILE_FLAG_OVERLAPPED))
328c2c66affSColin Finck     {
329c2c66affSColin Finck         CreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT;
330c2c66affSColin Finck     }
331c2c66affSColin Finck 
332c2c66affSColin Finck     /* Handle all open modes */
333c2c66affSColin Finck     if (dwOpenMode & PIPE_ACCESS_OUTBOUND)
334c2c66affSColin Finck     {
335c2c66affSColin Finck         ShareAccess |= FILE_SHARE_READ;
336c2c66affSColin Finck         DesiredAccess |= GENERIC_WRITE;
337c2c66affSColin Finck     }
338c2c66affSColin Finck 
339c2c66affSColin Finck     if (dwOpenMode & PIPE_ACCESS_INBOUND)
340c2c66affSColin Finck     {
341c2c66affSColin Finck         ShareAccess |= FILE_SHARE_WRITE;
342c2c66affSColin Finck         DesiredAccess |= GENERIC_READ;
343c2c66affSColin Finck     }
344c2c66affSColin Finck 
345c2c66affSColin Finck     /* Handle the type flags */
346c2c66affSColin Finck     if (dwPipeMode & PIPE_TYPE_MESSAGE)
347c2c66affSColin Finck     {
348c2c66affSColin Finck         WriteModeMessage = FILE_PIPE_MESSAGE_TYPE;
349c2c66affSColin Finck     }
350c2c66affSColin Finck     else
351c2c66affSColin Finck     {
352c2c66affSColin Finck         WriteModeMessage = FILE_PIPE_BYTE_STREAM_TYPE;
353c2c66affSColin Finck     }
354c2c66affSColin Finck 
355c2c66affSColin Finck     /* Handle the mode flags */
356c2c66affSColin Finck     if (dwPipeMode & PIPE_READMODE_MESSAGE)
357c2c66affSColin Finck     {
358c2c66affSColin Finck         ReadModeMessage = FILE_PIPE_MESSAGE_MODE;
359c2c66affSColin Finck     }
360c2c66affSColin Finck     else
361c2c66affSColin Finck     {
362c2c66affSColin Finck         ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
363c2c66affSColin Finck     }
364c2c66affSColin Finck 
365c2c66affSColin Finck     /* Handle the blocking mode */
366c2c66affSColin Finck     if (dwPipeMode & PIPE_NOWAIT)
367c2c66affSColin Finck     {
368c2c66affSColin Finck         NonBlocking = FILE_PIPE_COMPLETE_OPERATION;
369c2c66affSColin Finck     }
370c2c66affSColin Finck     else
371c2c66affSColin Finck     {
372c2c66affSColin Finck         NonBlocking = FILE_PIPE_QUEUE_OPERATION;
373c2c66affSColin Finck     }
374c2c66affSColin Finck 
375c2c66affSColin Finck     /* Check if we have a timeout */
376c2c66affSColin Finck     if (nDefaultTimeOut)
377c2c66affSColin Finck     {
378c2c66affSColin Finck         /* Convert the time to NT format */
379c2c66affSColin Finck         DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000LL;
380c2c66affSColin Finck     }
381c2c66affSColin Finck     else
382c2c66affSColin Finck     {
383c2c66affSColin Finck         /* Use default timeout of 50 ms */
384c2c66affSColin Finck         DefaultTimeOut.QuadPart = -500000;
385c2c66affSColin Finck     }
386c2c66affSColin Finck 
387c2c66affSColin Finck     /* Now create the pipe */
388c2c66affSColin Finck     Status = NtCreateNamedPipeFile(&PipeHandle,
389c2c66affSColin Finck                                    DesiredAccess,
390c2c66affSColin Finck                                    &ObjectAttributes,
391c2c66affSColin Finck                                    &Iosb,
392c2c66affSColin Finck                                    ShareAccess,
393c2c66affSColin Finck                                    FILE_OPEN_IF,
394c2c66affSColin Finck                                    CreateOptions,
395c2c66affSColin Finck                                    WriteModeMessage,
396c2c66affSColin Finck                                    ReadModeMessage,
397c2c66affSColin Finck                                    NonBlocking,
398c2c66affSColin Finck                                    nMaxInstances,
399c2c66affSColin Finck                                    nInBufferSize,
400c2c66affSColin Finck                                    nOutBufferSize,
401c2c66affSColin Finck                                    &DefaultTimeOut);
402c2c66affSColin Finck 
403c2c66affSColin Finck     /* Normalize special error codes */
404c2c66affSColin Finck     if ((Status == STATUS_INVALID_DEVICE_REQUEST) ||
405c2c66affSColin Finck         (Status == STATUS_NOT_SUPPORTED))
406c2c66affSColin Finck     {
407c2c66affSColin Finck         Status = STATUS_OBJECT_NAME_INVALID;
408c2c66affSColin Finck     }
409c2c66affSColin Finck 
410c2c66affSColin Finck     /* Free the name */
411c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(),
412c2c66affSColin Finck                 0,
413c2c66affSColin Finck                 NamedPipeName.Buffer);
414c2c66affSColin Finck 
415c2c66affSColin Finck     /* Check status */
416c2c66affSColin Finck     if (!NT_SUCCESS(Status))
417c2c66affSColin Finck     {
418c2c66affSColin Finck         /* Failed to create it */
419c2c66affSColin Finck         WARN("NtCreateNamedPipe failed (Status %x)!\n", Status);
420c2c66affSColin Finck         BaseSetLastNTError (Status);
421c2c66affSColin Finck         return INVALID_HANDLE_VALUE;
422c2c66affSColin Finck     }
423c2c66affSColin Finck 
424c2c66affSColin Finck     /* Return the handle */
425c2c66affSColin Finck     return PipeHandle;
426c2c66affSColin Finck }
427c2c66affSColin Finck 
428c2c66affSColin Finck /*
429c2c66affSColin Finck  * @implemented
430c2c66affSColin Finck  */
431c2c66affSColin Finck BOOL
432c2c66affSColin Finck WINAPI
WaitNamedPipeA(LPCSTR lpNamedPipeName,DWORD nTimeOut)433c2c66affSColin Finck WaitNamedPipeA(LPCSTR lpNamedPipeName,
434c2c66affSColin Finck                DWORD nTimeOut)
435c2c66affSColin Finck {
4363832f83aSPierre Schweitzer     BOOL r = FALSE;
437c2c66affSColin Finck     UNICODE_STRING NameU;
438c2c66affSColin Finck 
439c2c66affSColin Finck     /* Convert the name to Unicode */
4403832f83aSPierre Schweitzer     if (Basep8BitStringToDynamicUnicodeString(&NameU, lpNamedPipeName))
4413832f83aSPierre Schweitzer     {
442c2c66affSColin Finck         /* Call the Unicode API */
443c2c66affSColin Finck         r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
444c2c66affSColin Finck 
445c2c66affSColin Finck         /* Free the Unicode string */
446c2c66affSColin Finck         RtlFreeUnicodeString(&NameU);
4473832f83aSPierre Schweitzer     }
448c2c66affSColin Finck 
449c2c66affSColin Finck     /* Return result */
450c2c66affSColin Finck     return r;
451c2c66affSColin Finck }
452c2c66affSColin Finck 
453c2c66affSColin Finck /*
454c2c66affSColin Finck  * @implemented
455c2c66affSColin Finck  */
456c2c66affSColin Finck BOOL
457c2c66affSColin Finck WINAPI
WaitNamedPipeW(LPCWSTR lpNamedPipeName,DWORD nTimeOut)458c2c66affSColin Finck WaitNamedPipeW(LPCWSTR lpNamedPipeName,
459c2c66affSColin Finck                DWORD nTimeOut)
460c2c66affSColin Finck {
461c2c66affSColin Finck     UNICODE_STRING NamedPipeName, NewName, DevicePath, PipePrefix;
462c2c66affSColin Finck     ULONG NameLength;
463c2c66affSColin Finck     ULONG i;
464c2c66affSColin Finck     PWCHAR p;
465c2c66affSColin Finck     ULONG Type;
466c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
467c2c66affSColin Finck     NTSTATUS Status;
468c2c66affSColin Finck     HANDLE FileHandle;
469c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
470c2c66affSColin Finck     ULONG WaitPipeInfoSize;
471ebe97358SPierre Schweitzer     PVOID DevicePathBuffer;
472c2c66affSColin Finck     PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo;
473c2c66affSColin Finck 
474c2c66affSColin Finck     /* Start by making a unicode string of the name */
475c2c66affSColin Finck     TRACE("Sent path: %S\n", lpNamedPipeName);
476c2c66affSColin Finck     if (!RtlCreateUnicodeString(&NamedPipeName, lpNamedPipeName))
477c2c66affSColin Finck     {
478c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
479c2c66affSColin Finck         return FALSE;
480c2c66affSColin Finck     }
481c2c66affSColin Finck     NameLength = NamedPipeName.Length / sizeof(WCHAR);
482c2c66affSColin Finck 
483c2c66affSColin Finck     /* All slashes must become backslashes */
484c2c66affSColin Finck     for (i = 0; i < NameLength; i++)
485c2c66affSColin Finck     {
486c2c66affSColin Finck         /* Check and convert */
487c2c66affSColin Finck         if (NamedPipeName.Buffer[i] == L'/') NamedPipeName.Buffer[i] = L'\\';
488c2c66affSColin Finck     }
489c2c66affSColin Finck 
490ebe97358SPierre Schweitzer     DevicePathBuffer = NULL;
491ebe97358SPierre Schweitzer 
492c2c66affSColin Finck     /* Find the path type of the name we were given */
493c2c66affSColin Finck     NewName = NamedPipeName;
494c2c66affSColin Finck     Type = RtlDetermineDosPathNameType_U(lpNamedPipeName);
495c2c66affSColin Finck 
496c2c66affSColin Finck     /* Check if this was a device path, ie : "\\.\pipe\name" */
497c2c66affSColin Finck     if (Type == RtlPathTypeLocalDevice)
498c2c66affSColin Finck     {
499c2c66affSColin Finck         /* Make sure it's a valid prefix */
500c2c66affSColin Finck         RtlInitUnicodeString(&PipePrefix, L"\\\\.\\pipe\\");
501c2c66affSColin Finck         if (!RtlPrefixUnicodeString(&PipePrefix, &NewName, TRUE))
502c2c66affSColin Finck         {
503c2c66affSColin Finck             /* The name is invalid */
504c2c66affSColin Finck             WARN("Invalid name!\n");
505c2c66affSColin Finck             RtlFreeUnicodeString(&NamedPipeName);
506c2c66affSColin Finck             BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
507c2c66affSColin Finck             return FALSE;
508c2c66affSColin Finck         }
509c2c66affSColin Finck 
510c2c66affSColin Finck         /* Move past it */
511c2c66affSColin Finck         NewName.Buffer += PipePrefix.Length / sizeof(WCHAR);
512c2c66affSColin Finck         NewName.Length -= PipePrefix.Length;
513c2c66affSColin Finck         NewName.MaximumLength -= PipePrefix.Length;
514c2c66affSColin Finck 
515c2c66affSColin Finck         /* Initialize the Dos Devices name */
516c2c66affSColin Finck         TRACE("NewName: %wZ\n", &NewName);
517c2c66affSColin Finck         RtlInitUnicodeString(&DevicePath, L"\\DosDevices\\pipe\\");
518c2c66affSColin Finck     }
519c2c66affSColin Finck     else if (Type == RtlPathTypeUncAbsolute)
520c2c66affSColin Finck     {
521ebe97358SPierre Schweitzer         PWSTR PipeName;
522ebe97358SPierre Schweitzer 
523c2c66affSColin Finck         /* The path is \\server\\pipe\name; find the pipename itself */
524c2c66affSColin Finck         p = &NewName.Buffer[2];
525c2c66affSColin Finck 
526c2c66affSColin Finck         /* First loop to get past the server name */
527c2c66affSColin Finck         do
528c2c66affSColin Finck         {
529c2c66affSColin Finck             /* Check if this is a backslash */
530c2c66affSColin Finck             if (*p == L'\\') break;
531c2c66affSColin Finck 
532c2c66affSColin Finck             /* Check next */
533c2c66affSColin Finck             p++;
534c2c66affSColin Finck         } while (*p);
535c2c66affSColin Finck 
536c2c66affSColin Finck         /* Now make sure the full name contains "pipe\" */
537c2c66affSColin Finck         if ((*p) && !(_wcsnicmp(p + 1, L"pipe\\", sizeof("pipe\\") - sizeof(ANSI_NULL))))
538c2c66affSColin Finck         {
539c2c66affSColin Finck             /* Get to the pipe name itself now */
540c2c66affSColin Finck             p += sizeof("pipe\\") - sizeof(ANSI_NULL);
541c2c66affSColin Finck         }
542c2c66affSColin Finck         else
543c2c66affSColin Finck         {
544c2c66affSColin Finck             /* The name is invalid */
545c2c66affSColin Finck             WARN("Invalid name!\n");
546c2c66affSColin Finck             RtlFreeUnicodeString(&NamedPipeName);
547c2c66affSColin Finck             BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
548c2c66affSColin Finck             return FALSE;
549c2c66affSColin Finck         }
550c2c66affSColin Finck 
551ebe97358SPierre Schweitzer         /* Skip first backslash */
552ebe97358SPierre Schweitzer         NewName.Buffer++;
553ebe97358SPierre Schweitzer         /* And skip pipe for copying name */
554ebe97358SPierre Schweitzer         PipeName = p + ((sizeof(L"pipe\\") - sizeof(UNICODE_NULL)) / sizeof(WCHAR));
555ebe97358SPierre Schweitzer         /* Update the string */
556ebe97358SPierre Schweitzer         NewName.Length = (USHORT)((ULONG_PTR)PipeName - (ULONG_PTR)NewName.Buffer);
557ebe97358SPierre Schweitzer         NewName.MaximumLength = (USHORT)((ULONG_PTR)PipeName - (ULONG_PTR)NewName.Buffer);
558ebe97358SPierre Schweitzer 
559ebe97358SPierre Schweitzer         /* DevicePath will contain the pipename + the DosDevice prefix */
560ebe97358SPierre Schweitzer         DevicePath.MaximumLength = (USHORT)((ULONG_PTR)PipeName - (ULONG_PTR)NewName.Buffer) + sizeof(L"\\DosDevices\\UNC\\");
561ebe97358SPierre Schweitzer 
562ebe97358SPierre Schweitzer         /* Allocate the buffer for DevicePath */
563ebe97358SPierre Schweitzer         DevicePathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DevicePath.MaximumLength);
564ebe97358SPierre Schweitzer         if (DevicePathBuffer == NULL)
565ebe97358SPierre Schweitzer         {
566ebe97358SPierre Schweitzer             RtlFreeUnicodeString(&NamedPipeName);
567ebe97358SPierre Schweitzer             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
568ebe97358SPierre Schweitzer             return FALSE;
569ebe97358SPierre Schweitzer         }
570ebe97358SPierre Schweitzer 
571ebe97358SPierre Schweitzer         /* Copy the prefix first */
572ebe97358SPierre Schweitzer         DevicePath.Buffer = DevicePathBuffer;
573ebe97358SPierre Schweitzer         RtlCopyMemory(DevicePathBuffer, L"\\DosDevices\\UNC\\", sizeof(L"\\DosDevices\\UNC\\") - sizeof(UNICODE_NULL));
574ebe97358SPierre Schweitzer         DevicePath.Length = sizeof(L"\\DosDevices\\UNC\\") - sizeof(UNICODE_NULL);
575ebe97358SPierre Schweitzer         /* And append the rest */
576ebe97358SPierre Schweitzer         RtlAppendUnicodeStringToString(&DevicePath, &NewName);
577ebe97358SPierre Schweitzer         /* And fix pipe name without its prefix */
578ebe97358SPierre Schweitzer         RtlInitUnicodeString(&NewName, PipeName + 1);
579c2c66affSColin Finck     }
580c2c66affSColin Finck     else
581c2c66affSColin Finck     {
582c2c66affSColin Finck         WARN("Invalid path type\n");
583c2c66affSColin Finck         RtlFreeUnicodeString(&NamedPipeName);
584c2c66affSColin Finck         BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
585c2c66affSColin Finck         return FALSE;
586c2c66affSColin Finck     }
587c2c66affSColin Finck 
588c2c66affSColin Finck     /* Now calculate the total length of the structure and allocate it */
589c2c66affSColin Finck     WaitPipeInfoSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) +
590c2c66affSColin Finck                        NewName.Length;
591c2c66affSColin Finck     WaitPipeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize);
592c2c66affSColin Finck     if (WaitPipeInfo == NULL)
593c2c66affSColin Finck     {
594ebe97358SPierre Schweitzer         if (DevicePathBuffer != NULL)
595ebe97358SPierre Schweitzer         {
596ebe97358SPierre Schweitzer             RtlFreeHeap(RtlGetProcessHeap(), 0, DevicePathBuffer);
597ebe97358SPierre Schweitzer         }
598ebe97358SPierre Schweitzer 
599c2c66affSColin Finck         RtlFreeUnicodeString(&NamedPipeName);
600c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
601c2c66affSColin Finck         return FALSE;
602c2c66affSColin Finck     }
603c2c66affSColin Finck 
604c2c66affSColin Finck     /* Initialize the object attributes */
605c2c66affSColin Finck     TRACE("Opening: %wZ\n", &DevicePath);
606c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
607c2c66affSColin Finck                                &DevicePath,
608c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
609c2c66affSColin Finck                                NULL,
610c2c66affSColin Finck                                NULL);
611c2c66affSColin Finck 
612c2c66affSColin Finck     /* Open the path */
613c2c66affSColin Finck     Status = NtOpenFile(&FileHandle,
614c2c66affSColin Finck                         FILE_READ_ATTRIBUTES | SYNCHRONIZE,
615c2c66affSColin Finck                         &ObjectAttributes,
616c2c66affSColin Finck                         &IoStatusBlock,
617c2c66affSColin Finck                         FILE_SHARE_READ | FILE_SHARE_WRITE,
618c2c66affSColin Finck                         FILE_SYNCHRONOUS_IO_NONALERT);
619ebe97358SPierre Schweitzer 
620ebe97358SPierre Schweitzer     if (DevicePathBuffer != NULL)
621ebe97358SPierre Schweitzer     {
622ebe97358SPierre Schweitzer         RtlFreeHeap(RtlGetProcessHeap(), 0, DevicePathBuffer);
623ebe97358SPierre Schweitzer     }
624ebe97358SPierre Schweitzer 
625c2c66affSColin Finck     if (!NT_SUCCESS(Status))
626c2c66affSColin Finck     {
627c2c66affSColin Finck         /* Fail; couldn't open */
628c2c66affSColin Finck         WARN("Status: %lx\n", Status);
629c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo);
630c2c66affSColin Finck         RtlFreeUnicodeString(&NamedPipeName);
631c2c66affSColin Finck         BaseSetLastNTError(Status);
632c2c66affSColin Finck         return FALSE;
633c2c66affSColin Finck     }
634c2c66affSColin Finck 
635c2c66affSColin Finck     /* Check what timeout we got */
636c2c66affSColin Finck     if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT)
637c2c66affSColin Finck     {
638c2c66affSColin Finck         /* Don't use a timeout */
639c2c66affSColin Finck         WaitPipeInfo->TimeoutSpecified = FALSE;
640c2c66affSColin Finck     }
641c2c66affSColin Finck     else
642c2c66affSColin Finck     {
643c2c66affSColin Finck         /* Check if we should wait forever */
644c2c66affSColin Finck         if (nTimeOut == NMPWAIT_WAIT_FOREVER)
645c2c66affSColin Finck         {
646c2c66affSColin Finck             /* Set the max */
647c2c66affSColin Finck             WaitPipeInfo->Timeout.LowPart = 0;
648c2c66affSColin Finck             WaitPipeInfo->Timeout.HighPart = 0x80000000;
649c2c66affSColin Finck         }
650c2c66affSColin Finck         else
651c2c66affSColin Finck         {
652c2c66affSColin Finck             /* Convert to NT format */
653c2c66affSColin Finck             WaitPipeInfo->Timeout.QuadPart = nTimeOut * -10000LL;
654c2c66affSColin Finck         }
655c2c66affSColin Finck 
656c2c66affSColin Finck         /* In both cases, we do have a timeout */
657c2c66affSColin Finck         WaitPipeInfo->TimeoutSpecified = TRUE;
658c2c66affSColin Finck     }
659c2c66affSColin Finck 
660c2c66affSColin Finck     /* Set the length and copy the name */
661c2c66affSColin Finck     WaitPipeInfo->NameLength = NewName.Length;
662c2c66affSColin Finck     RtlCopyMemory(WaitPipeInfo->Name, NewName.Buffer, NewName.Length);
663c2c66affSColin Finck 
664c2c66affSColin Finck     /* Get rid of the full name */
665c2c66affSColin Finck     RtlFreeUnicodeString(&NamedPipeName);
666c2c66affSColin Finck 
667c2c66affSColin Finck     /* Let NPFS know of our request */
668c2c66affSColin Finck     Status = NtFsControlFile(FileHandle,
669c2c66affSColin Finck                              NULL,
670c2c66affSColin Finck                              NULL,
671c2c66affSColin Finck                              NULL,
672c2c66affSColin Finck                              &IoStatusBlock,
673c2c66affSColin Finck                              FSCTL_PIPE_WAIT,
674c2c66affSColin Finck                              WaitPipeInfo,
675c2c66affSColin Finck                              WaitPipeInfoSize,
676c2c66affSColin Finck                              NULL,
677c2c66affSColin Finck                              0);
678c2c66affSColin Finck 
679c2c66affSColin Finck     /* Free our pipe info data and close the handle */
680c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo);
681c2c66affSColin Finck     NtClose(FileHandle);
682c2c66affSColin Finck 
683c2c66affSColin Finck     /* Check the status */
684c2c66affSColin Finck     if (!NT_SUCCESS(Status))
685c2c66affSColin Finck     {
686c2c66affSColin Finck         /* Failure to wait on the pipe */
687c2c66affSColin Finck         WARN("Status: %lx\n", Status);
688c2c66affSColin Finck         BaseSetLastNTError(Status);
689c2c66affSColin Finck         return FALSE;
690c2c66affSColin Finck      }
691c2c66affSColin Finck 
692c2c66affSColin Finck     /* Success */
693c2c66affSColin Finck     return TRUE;
694c2c66affSColin Finck }
695c2c66affSColin Finck 
696c2c66affSColin Finck /*
697c2c66affSColin Finck  * @implemented
698c2c66affSColin Finck  */
699c2c66affSColin Finck BOOL
700c2c66affSColin Finck WINAPI
ConnectNamedPipe(IN HANDLE hNamedPipe,IN LPOVERLAPPED lpOverlapped)701c2c66affSColin Finck ConnectNamedPipe(IN HANDLE hNamedPipe,
702c2c66affSColin Finck                  IN LPOVERLAPPED lpOverlapped)
703c2c66affSColin Finck {
704c2c66affSColin Finck     NTSTATUS Status;
705c2c66affSColin Finck 
706c2c66affSColin Finck     if (lpOverlapped != NULL)
707c2c66affSColin Finck     {
708c2c66affSColin Finck         PVOID ApcContext;
709c2c66affSColin Finck 
710c2c66affSColin Finck         lpOverlapped->Internal = STATUS_PENDING;
711c2c66affSColin Finck         ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
712c2c66affSColin Finck 
713c2c66affSColin Finck         Status = NtFsControlFile(hNamedPipe,
714c2c66affSColin Finck                                  lpOverlapped->hEvent,
715c2c66affSColin Finck                                  NULL,
716c2c66affSColin Finck                                  ApcContext,
717c2c66affSColin Finck                                  (PIO_STATUS_BLOCK)lpOverlapped,
718c2c66affSColin Finck                                  FSCTL_PIPE_LISTEN,
719c2c66affSColin Finck                                  NULL,
720c2c66affSColin Finck                                  0,
721c2c66affSColin Finck                                  NULL,
722c2c66affSColin Finck                                  0);
723c2c66affSColin Finck 
724c2c66affSColin Finck         /* return FALSE in case of failure and pending operations! */
725c2c66affSColin Finck         if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
726c2c66affSColin Finck         {
727c2c66affSColin Finck             BaseSetLastNTError(Status);
728c2c66affSColin Finck             return FALSE;
729c2c66affSColin Finck         }
730c2c66affSColin Finck     }
731c2c66affSColin Finck     else
732c2c66affSColin Finck     {
733c2c66affSColin Finck         IO_STATUS_BLOCK Iosb;
734c2c66affSColin Finck 
735c2c66affSColin Finck         Status = NtFsControlFile(hNamedPipe,
736c2c66affSColin Finck                                  NULL,
737c2c66affSColin Finck                                  NULL,
738c2c66affSColin Finck                                  NULL,
739c2c66affSColin Finck                                  &Iosb,
740c2c66affSColin Finck                                  FSCTL_PIPE_LISTEN,
741c2c66affSColin Finck                                  NULL,
742c2c66affSColin Finck                                  0,
743c2c66affSColin Finck                                  NULL,
744c2c66affSColin Finck                                  0);
745c2c66affSColin Finck 
746c2c66affSColin Finck         /* wait in case operation is pending */
747c2c66affSColin Finck         if (Status == STATUS_PENDING)
748c2c66affSColin Finck         {
749c2c66affSColin Finck              Status = NtWaitForSingleObject(hNamedPipe,
750c2c66affSColin Finck                                             FALSE,
751c2c66affSColin Finck                                             NULL);
752c2c66affSColin Finck              if (NT_SUCCESS(Status))
753c2c66affSColin Finck              {
754c2c66affSColin Finck                  Status = Iosb.Status;
755c2c66affSColin Finck              }
756c2c66affSColin Finck         }
757c2c66affSColin Finck 
758c2c66affSColin Finck         if (!NT_SUCCESS(Status))
759c2c66affSColin Finck         {
760c2c66affSColin Finck             BaseSetLastNTError(Status);
761c2c66affSColin Finck             return FALSE;
762c2c66affSColin Finck         }
763c2c66affSColin Finck     }
764c2c66affSColin Finck 
765c2c66affSColin Finck     return TRUE;
766c2c66affSColin Finck }
767c2c66affSColin Finck 
768c2c66affSColin Finck 
769c2c66affSColin Finck /*
770c2c66affSColin Finck  * @implemented
771c2c66affSColin Finck  */
772c2c66affSColin Finck BOOL
773c2c66affSColin Finck WINAPI
SetNamedPipeHandleState(HANDLE hNamedPipe,LPDWORD lpMode,LPDWORD lpMaxCollectionCount,LPDWORD lpCollectDataTimeout)774c2c66affSColin Finck SetNamedPipeHandleState(HANDLE hNamedPipe,
775c2c66affSColin Finck                         LPDWORD lpMode,
776c2c66affSColin Finck                         LPDWORD lpMaxCollectionCount,
777c2c66affSColin Finck                         LPDWORD lpCollectDataTimeout)
778c2c66affSColin Finck {
779c2c66affSColin Finck     IO_STATUS_BLOCK Iosb;
780c2c66affSColin Finck     NTSTATUS Status;
781c2c66affSColin Finck 
782c2c66affSColin Finck     /* Check if the Mode is being changed */
783c2c66affSColin Finck     if (lpMode)
784c2c66affSColin Finck     {
785c2c66affSColin Finck         FILE_PIPE_INFORMATION Settings;
786c2c66affSColin Finck 
787c2c66affSColin Finck         /* Set the Completion Mode */
788c2c66affSColin Finck         Settings.CompletionMode = (*lpMode & PIPE_NOWAIT) ?
789c2c66affSColin Finck                                   FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
790c2c66affSColin Finck 
791c2c66affSColin Finck         /* Set the Read Mode */
792c2c66affSColin Finck         Settings.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE) ?
793c2c66affSColin Finck                             FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE;
794c2c66affSColin Finck 
795c2c66affSColin Finck         /* Send the changes to the Driver */
796c2c66affSColin Finck         Status = NtSetInformationFile(hNamedPipe,
797c2c66affSColin Finck                                       &Iosb,
798c2c66affSColin Finck                                       &Settings,
799*d6d30f9eSHermès Bélusca-Maïto                                       sizeof(Settings),
800c2c66affSColin Finck                                       FilePipeInformation);
801c2c66affSColin Finck         if (!NT_SUCCESS(Status))
802c2c66affSColin Finck         {
803c2c66affSColin Finck             BaseSetLastNTError(Status);
804c2c66affSColin Finck             return FALSE;
805c2c66affSColin Finck         }
806c2c66affSColin Finck     }
807c2c66affSColin Finck 
808c2c66affSColin Finck     /* Check if the Collection count or Timeout are being changed */
809c2c66affSColin Finck     if (lpMaxCollectionCount || lpCollectDataTimeout)
810c2c66affSColin Finck     {
811c2c66affSColin Finck         FILE_PIPE_REMOTE_INFORMATION RemoteSettings;
812c2c66affSColin Finck 
813c2c66affSColin Finck         /* Setting one without the other would delete it, so we read old one */
814c2c66affSColin Finck         if (!lpMaxCollectionCount || !lpCollectDataTimeout)
815c2c66affSColin Finck         {
816c2c66affSColin Finck             Status = NtQueryInformationFile(hNamedPipe,
817c2c66affSColin Finck                                             &Iosb,
818c2c66affSColin Finck                                             &RemoteSettings,
819*d6d30f9eSHermès Bélusca-Maïto                                             sizeof(RemoteSettings),
820c2c66affSColin Finck                                             FilePipeRemoteInformation);
821c2c66affSColin Finck             if (!NT_SUCCESS(Status))
822c2c66affSColin Finck             {
823c2c66affSColin Finck                 BaseSetLastNTError(Status);
824c2c66affSColin Finck                 return FALSE;
825c2c66affSColin Finck             }
826c2c66affSColin Finck         }
827c2c66affSColin Finck 
828c2c66affSColin Finck         /* Now set the new settings */
829c2c66affSColin Finck         RemoteSettings.MaximumCollectionCount = (lpMaxCollectionCount) ?
830c2c66affSColin Finck                                                 *lpMaxCollectionCount :
831c2c66affSColin Finck                                                 RemoteSettings.MaximumCollectionCount;
832c2c66affSColin Finck         if (lpCollectDataTimeout)
833c2c66affSColin Finck         {
834c2c66affSColin Finck             /* Convert it to Quad */
835c2c66affSColin Finck             RemoteSettings.CollectDataTime.QuadPart = *lpCollectDataTimeout * -10000LL;
836c2c66affSColin Finck         }
837c2c66affSColin Finck 
838c2c66affSColin Finck         /* Tell the driver to change them */
839c2c66affSColin Finck         Status = NtSetInformationFile(hNamedPipe,
840c2c66affSColin Finck                                       &Iosb,
841c2c66affSColin Finck                                       &RemoteSettings,
842*d6d30f9eSHermès Bélusca-Maïto                                       sizeof(RemoteSettings),
843c2c66affSColin Finck                                       FilePipeRemoteInformation);
844c2c66affSColin Finck         if (!NT_SUCCESS(Status))
845c2c66affSColin Finck         {
846c2c66affSColin Finck             BaseSetLastNTError(Status);
847c2c66affSColin Finck             return FALSE;
848c2c66affSColin Finck         }
849c2c66affSColin Finck     }
850c2c66affSColin Finck 
851c2c66affSColin Finck     return TRUE;
852c2c66affSColin Finck }
853c2c66affSColin Finck 
854c2c66affSColin Finck 
855c2c66affSColin Finck /*
856c2c66affSColin Finck  * @implemented
857c2c66affSColin Finck  */
858c2c66affSColin Finck BOOL
859c2c66affSColin Finck WINAPI
CallNamedPipeA(LPCSTR lpNamedPipeName,LPVOID lpInBuffer,DWORD nInBufferSize,LPVOID lpOutBuffer,DWORD nOutBufferSize,LPDWORD lpBytesRead,DWORD nTimeOut)860c2c66affSColin Finck CallNamedPipeA(LPCSTR lpNamedPipeName,
861c2c66affSColin Finck                LPVOID lpInBuffer,
862c2c66affSColin Finck                DWORD nInBufferSize,
863c2c66affSColin Finck                LPVOID lpOutBuffer,
864c2c66affSColin Finck                DWORD nOutBufferSize,
865c2c66affSColin Finck                LPDWORD lpBytesRead,
866c2c66affSColin Finck                DWORD nTimeOut)
867c2c66affSColin Finck {
868c2c66affSColin Finck     PUNICODE_STRING PipeName = &NtCurrentTeb()->StaticUnicodeString;
869c2c66affSColin Finck     ANSI_STRING AnsiPipe;
870c2c66affSColin Finck 
871c2c66affSColin Finck     /* Initialize the string as ANSI_STRING and convert to Unicode */
872c2c66affSColin Finck     RtlInitAnsiString(&AnsiPipe, (LPSTR)lpNamedPipeName);
873c2c66affSColin Finck     RtlAnsiStringToUnicodeString(PipeName, &AnsiPipe, FALSE);
874c2c66affSColin Finck 
875c2c66affSColin Finck     /* Call the Unicode function */
876c2c66affSColin Finck     return CallNamedPipeW(PipeName->Buffer,
877c2c66affSColin Finck                           lpInBuffer,
878c2c66affSColin Finck                           nInBufferSize,
879c2c66affSColin Finck                           lpOutBuffer,
880c2c66affSColin Finck                           nOutBufferSize,
881c2c66affSColin Finck                           lpBytesRead,
882c2c66affSColin Finck                           nTimeOut);
883c2c66affSColin Finck }
884c2c66affSColin Finck 
885c2c66affSColin Finck 
886c2c66affSColin Finck /*
887c2c66affSColin Finck  * @implemented
888c2c66affSColin Finck  */
889c2c66affSColin Finck BOOL
890c2c66affSColin Finck WINAPI
CallNamedPipeW(LPCWSTR lpNamedPipeName,LPVOID lpInBuffer,DWORD nInBufferSize,LPVOID lpOutBuffer,DWORD nOutBufferSize,LPDWORD lpBytesRead,DWORD nTimeOut)891c2c66affSColin Finck CallNamedPipeW(LPCWSTR lpNamedPipeName,
892c2c66affSColin Finck                LPVOID lpInBuffer,
893c2c66affSColin Finck                DWORD nInBufferSize,
894c2c66affSColin Finck                LPVOID lpOutBuffer,
895c2c66affSColin Finck                DWORD nOutBufferSize,
896c2c66affSColin Finck                LPDWORD lpBytesRead,
897c2c66affSColin Finck                DWORD nTimeOut)
898c2c66affSColin Finck {
899c2c66affSColin Finck     HANDLE hPipe;
900c2c66affSColin Finck     BOOL bRetry = TRUE;
901c2c66affSColin Finck     BOOL bError;
902c2c66affSColin Finck     DWORD dwPipeMode;
903c2c66affSColin Finck 
904c2c66affSColin Finck     while (TRUE)
905c2c66affSColin Finck     {
906c2c66affSColin Finck         /* Try creating it */
907c2c66affSColin Finck         hPipe = CreateFileW(lpNamedPipeName,
908c2c66affSColin Finck                             GENERIC_READ | GENERIC_WRITE,
909c2c66affSColin Finck                             FILE_SHARE_READ | FILE_SHARE_WRITE,
910c2c66affSColin Finck                             NULL,
911c2c66affSColin Finck                             OPEN_EXISTING,
912c2c66affSColin Finck                             FILE_ATTRIBUTE_NORMAL,
913c2c66affSColin Finck                             NULL);
914c2c66affSColin Finck 
915c2c66affSColin Finck         /* Success, break out */
916c2c66affSColin Finck         if (hPipe != INVALID_HANDLE_VALUE)
917c2c66affSColin Finck             break;
918c2c66affSColin Finck 
919c2c66affSColin Finck         /* Already tried twice, give up */
920c2c66affSColin Finck         if (bRetry == FALSE)
921c2c66affSColin Finck             return FALSE;
922c2c66affSColin Finck 
923c2c66affSColin Finck         /* Wait on it */
924c2c66affSColin Finck         WaitNamedPipeW(lpNamedPipeName, nTimeOut);
925c2c66affSColin Finck 
926c2c66affSColin Finck         /* Get ready to try again */
927c2c66affSColin Finck         bRetry = FALSE;
928c2c66affSColin Finck     }
929c2c66affSColin Finck 
930c2c66affSColin Finck     /* Set the pipe mode */
931c2c66affSColin Finck     dwPipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
932c2c66affSColin Finck     bError = SetNamedPipeHandleState(hPipe, &dwPipeMode, NULL, NULL);
933c2c66affSColin Finck     if (!bError)
934c2c66affSColin Finck     {
935c2c66affSColin Finck         /* Couldn't change state, fail */
936c2c66affSColin Finck         CloseHandle(hPipe);
937c2c66affSColin Finck         return FALSE;
938c2c66affSColin Finck     }
939c2c66affSColin Finck 
940c2c66affSColin Finck     /* Do the transact */
941c2c66affSColin Finck     bError = TransactNamedPipe(hPipe,
942c2c66affSColin Finck                                lpInBuffer,
943c2c66affSColin Finck                                nInBufferSize,
944c2c66affSColin Finck                                lpOutBuffer,
945c2c66affSColin Finck                                nOutBufferSize,
946c2c66affSColin Finck                                lpBytesRead,
947c2c66affSColin Finck                                NULL);
948c2c66affSColin Finck 
949c2c66affSColin Finck     /* Close the handle */
950c2c66affSColin Finck     CloseHandle(hPipe);
951c2c66affSColin Finck 
952c2c66affSColin Finck     return bError;
953c2c66affSColin Finck }
954c2c66affSColin Finck 
955c2c66affSColin Finck 
956c2c66affSColin Finck /*
957c2c66affSColin Finck  * @implemented
958c2c66affSColin Finck  */
959c2c66affSColin Finck BOOL
960c2c66affSColin Finck WINAPI
DisconnectNamedPipe(HANDLE hNamedPipe)961c2c66affSColin Finck DisconnectNamedPipe(HANDLE hNamedPipe)
962c2c66affSColin Finck {
963c2c66affSColin Finck     IO_STATUS_BLOCK Iosb;
964c2c66affSColin Finck     NTSTATUS Status;
965c2c66affSColin Finck 
966c2c66affSColin Finck     /* Send the FSCTL to the driver */
967c2c66affSColin Finck     Status = NtFsControlFile(hNamedPipe,
968c2c66affSColin Finck                              NULL,
969c2c66affSColin Finck                              NULL,
970c2c66affSColin Finck                              NULL,
971c2c66affSColin Finck                              &Iosb,
972c2c66affSColin Finck                              FSCTL_PIPE_DISCONNECT,
973c2c66affSColin Finck                              NULL,
974c2c66affSColin Finck                              0,
975c2c66affSColin Finck                              NULL,
976c2c66affSColin Finck                              0);
977c2c66affSColin Finck     if (Status == STATUS_PENDING)
978c2c66affSColin Finck     {
979c2c66affSColin Finck         /* Wait on NPFS to finish and get updated status */
980c2c66affSColin Finck         Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
981c2c66affSColin Finck         if (NT_SUCCESS(Status))
982c2c66affSColin Finck             Status = Iosb.Status;
983c2c66affSColin Finck     }
984c2c66affSColin Finck 
985c2c66affSColin Finck     /* Check for error */
986c2c66affSColin Finck     if (!NT_SUCCESS(Status))
987c2c66affSColin Finck     {
988c2c66affSColin Finck         /* Fail */
989c2c66affSColin Finck         BaseSetLastNTError(Status);
990c2c66affSColin Finck         return FALSE;
991c2c66affSColin Finck     }
992c2c66affSColin Finck 
993c2c66affSColin Finck     return TRUE;
994c2c66affSColin Finck }
995c2c66affSColin Finck 
996c2c66affSColin Finck 
997c2c66affSColin Finck /*
998c2c66affSColin Finck  * @unimplemented
999c2c66affSColin Finck  */
1000c2c66affSColin Finck BOOL
1001c2c66affSColin Finck WINAPI
GetNamedPipeHandleStateW(HANDLE hNamedPipe,LPDWORD lpState,LPDWORD lpCurInstances,LPDWORD lpMaxCollectionCount,LPDWORD lpCollectDataTimeout,LPWSTR lpUserName,DWORD nMaxUserNameSize)1002c2c66affSColin Finck GetNamedPipeHandleStateW(HANDLE hNamedPipe,
1003c2c66affSColin Finck                          LPDWORD lpState,
1004c2c66affSColin Finck                          LPDWORD lpCurInstances,
1005c2c66affSColin Finck                          LPDWORD lpMaxCollectionCount,
1006c2c66affSColin Finck                          LPDWORD lpCollectDataTimeout,
1007c2c66affSColin Finck                          LPWSTR lpUserName,
1008c2c66affSColin Finck                          DWORD nMaxUserNameSize)
1009c2c66affSColin Finck {
1010c2c66affSColin Finck     IO_STATUS_BLOCK StatusBlock;
1011c2c66affSColin Finck     NTSTATUS Status;
1012c2c66affSColin Finck 
1013c2c66affSColin Finck     if (lpState != NULL)
1014c2c66affSColin Finck     {
1015c2c66affSColin Finck         FILE_PIPE_INFORMATION PipeInfo;
1016c2c66affSColin Finck 
1017c2c66affSColin Finck         Status = NtQueryInformationFile(hNamedPipe,
1018c2c66affSColin Finck                                         &StatusBlock,
1019c2c66affSColin Finck                                         &PipeInfo,
1020*d6d30f9eSHermès Bélusca-Maïto                                         sizeof(PipeInfo),
1021c2c66affSColin Finck                                         FilePipeInformation);
1022c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1023c2c66affSColin Finck         {
1024c2c66affSColin Finck             BaseSetLastNTError(Status);
1025c2c66affSColin Finck             return FALSE;
1026c2c66affSColin Finck         }
1027c2c66affSColin Finck 
1028c2c66affSColin Finck         *lpState = ((PipeInfo.CompletionMode != FILE_PIPE_QUEUE_OPERATION) ? PIPE_NOWAIT : PIPE_WAIT);
1029c2c66affSColin Finck         *lpState |= ((PipeInfo.ReadMode != FILE_PIPE_BYTE_STREAM_MODE) ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
1030c2c66affSColin Finck     }
1031c2c66affSColin Finck 
1032c2c66affSColin Finck     if (lpCurInstances != NULL)
1033c2c66affSColin Finck     {
1034c2c66affSColin Finck         FILE_PIPE_LOCAL_INFORMATION LocalInfo;
1035c2c66affSColin Finck 
1036c2c66affSColin Finck         Status = NtQueryInformationFile(hNamedPipe,
1037c2c66affSColin Finck                                         &StatusBlock,
1038c2c66affSColin Finck                                         &LocalInfo,
1039*d6d30f9eSHermès Bélusca-Maïto                                         sizeof(LocalInfo),
1040c2c66affSColin Finck                                         FilePipeLocalInformation);
1041c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1042c2c66affSColin Finck         {
1043c2c66affSColin Finck             BaseSetLastNTError(Status);
1044c2c66affSColin Finck             return FALSE;
1045c2c66affSColin Finck         }
1046c2c66affSColin Finck 
1047c2c66affSColin Finck         *lpCurInstances = min(LocalInfo.CurrentInstances, PIPE_UNLIMITED_INSTANCES);
1048c2c66affSColin Finck     }
1049c2c66affSColin Finck 
1050c2c66affSColin Finck     if (lpMaxCollectionCount != NULL || lpCollectDataTimeout != NULL)
1051c2c66affSColin Finck     {
1052c2c66affSColin Finck         FILE_PIPE_REMOTE_INFORMATION RemoteInfo;
1053c2c66affSColin Finck 
1054c2c66affSColin Finck         Status = NtQueryInformationFile(hNamedPipe,
1055c2c66affSColin Finck                                         &StatusBlock,
1056c2c66affSColin Finck                                         &RemoteInfo,
1057*d6d30f9eSHermès Bélusca-Maïto                                         sizeof(RemoteInfo),
1058c2c66affSColin Finck                                         FilePipeRemoteInformation);
1059c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1060c2c66affSColin Finck         {
1061c2c66affSColin Finck             BaseSetLastNTError(Status);
1062c2c66affSColin Finck             return FALSE;
1063c2c66affSColin Finck         }
1064c2c66affSColin Finck 
1065c2c66affSColin Finck         if (lpMaxCollectionCount != NULL)
1066c2c66affSColin Finck         {
1067c2c66affSColin Finck             *lpMaxCollectionCount = RemoteInfo.MaximumCollectionCount;
1068c2c66affSColin Finck         }
1069c2c66affSColin Finck 
1070c2c66affSColin Finck         if (lpCollectDataTimeout != NULL)
1071c2c66affSColin Finck         {
107219cef780SPierre Schweitzer             LARGE_INTEGER CollectDataTime;
107319cef780SPierre Schweitzer 
107419cef780SPierre Schweitzer             /* Convert time and return it */
107519cef780SPierre Schweitzer             RemoteInfo.CollectDataTime.QuadPart *= -1;
107619cef780SPierre Schweitzer             CollectDataTime = RtlExtendedLargeIntegerDivide(RemoteInfo.CollectDataTime, 10000, NULL);
107719cef780SPierre Schweitzer             /* In case of overflow, just return MAX - 1 */
107819cef780SPierre Schweitzer             if (CollectDataTime.HighPart != 0)
107919cef780SPierre Schweitzer             {
108019cef780SPierre Schweitzer                 *lpCollectDataTimeout = -2;
108119cef780SPierre Schweitzer             }
108219cef780SPierre Schweitzer             else
108319cef780SPierre Schweitzer             {
108419cef780SPierre Schweitzer                 *lpCollectDataTimeout = CollectDataTime.LowPart;
108519cef780SPierre Schweitzer             }
1086c2c66affSColin Finck         }
1087c2c66affSColin Finck     }
1088c2c66affSColin Finck 
1089c2c66affSColin Finck     if (lpUserName != NULL)
1090c2c66affSColin Finck     {
109119cef780SPierre Schweitzer         return NpGetUserNamep(hNamedPipe, lpUserName, nMaxUserNameSize);
1092c2c66affSColin Finck     }
1093c2c66affSColin Finck 
1094c2c66affSColin Finck     return TRUE;
1095c2c66affSColin Finck }
1096c2c66affSColin Finck 
1097c2c66affSColin Finck 
1098c2c66affSColin Finck /*
1099c2c66affSColin Finck  * @implemented
1100c2c66affSColin Finck  */
1101c2c66affSColin Finck BOOL
1102c2c66affSColin Finck WINAPI
GetNamedPipeHandleStateA(HANDLE hNamedPipe,LPDWORD lpState,LPDWORD lpCurInstances,LPDWORD lpMaxCollectionCount,LPDWORD lpCollectDataTimeout,LPSTR lpUserName,DWORD nMaxUserNameSize)1103c2c66affSColin Finck GetNamedPipeHandleStateA(HANDLE hNamedPipe,
1104c2c66affSColin Finck                          LPDWORD lpState,
1105c2c66affSColin Finck                          LPDWORD lpCurInstances,
1106c2c66affSColin Finck                          LPDWORD lpMaxCollectionCount,
1107c2c66affSColin Finck                          LPDWORD lpCollectDataTimeout,
1108c2c66affSColin Finck                          LPSTR lpUserName,
1109c2c66affSColin Finck                          DWORD nMaxUserNameSize)
1110c2c66affSColin Finck {
1111c2c66affSColin Finck     UNICODE_STRING UserNameW = { 0, 0, NULL };
1112c2c66affSColin Finck     ANSI_STRING UserNameA;
1113c2c66affSColin Finck     BOOL Ret;
1114c2c66affSColin Finck 
1115c2c66affSColin Finck     if (lpUserName != NULL)
1116c2c66affSColin Finck     {
1117c2c66affSColin Finck         UserNameW.MaximumLength = (USHORT)nMaxUserNameSize * sizeof(WCHAR);
1118c2c66affSColin Finck         UserNameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW.MaximumLength);
1119c2c66affSColin Finck         if (UserNameW.Buffer == NULL)
1120c2c66affSColin Finck         {
1121c2c66affSColin Finck             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1122c2c66affSColin Finck             return FALSE;
1123c2c66affSColin Finck         }
1124c2c66affSColin Finck 
1125c2c66affSColin Finck         UserNameA.Buffer = lpUserName;
1126c2c66affSColin Finck         UserNameA.Length = 0;
1127c2c66affSColin Finck         UserNameA.MaximumLength = (USHORT)nMaxUserNameSize;
1128c2c66affSColin Finck     }
1129c2c66affSColin Finck 
1130c2c66affSColin Finck     Ret = GetNamedPipeHandleStateW(hNamedPipe,
1131c2c66affSColin Finck                                    lpState,
1132c2c66affSColin Finck                                    lpCurInstances,
1133c2c66affSColin Finck                                    lpMaxCollectionCount,
1134c2c66affSColin Finck                                    lpCollectDataTimeout,
1135c2c66affSColin Finck                                    UserNameW.Buffer,
1136c2c66affSColin Finck                                    nMaxUserNameSize);
1137c2c66affSColin Finck     if (Ret && lpUserName != NULL)
1138c2c66affSColin Finck     {
1139c2c66affSColin Finck         NTSTATUS Status;
1140c2c66affSColin Finck 
1141c2c66affSColin Finck         RtlInitUnicodeString(&UserNameW, UserNameW.Buffer);
1142c2c66affSColin Finck         Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
1143c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1144c2c66affSColin Finck         {
1145c2c66affSColin Finck             BaseSetLastNTError(Status);
1146c2c66affSColin Finck             Ret = FALSE;
1147c2c66affSColin Finck         }
1148c2c66affSColin Finck     }
1149c2c66affSColin Finck 
1150c2c66affSColin Finck     if (UserNameW.Buffer != NULL)
1151c2c66affSColin Finck     {
1152c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW.Buffer);
1153c2c66affSColin Finck     }
1154c2c66affSColin Finck 
1155c2c66affSColin Finck     return Ret;
1156c2c66affSColin Finck }
1157c2c66affSColin Finck 
1158c2c66affSColin Finck 
1159c2c66affSColin Finck /*
1160c2c66affSColin Finck  * @implemented
1161c2c66affSColin Finck  */
1162c2c66affSColin Finck BOOL
1163c2c66affSColin Finck WINAPI
GetNamedPipeInfo(HANDLE hNamedPipe,LPDWORD lpFlags,LPDWORD lpOutBufferSize,LPDWORD lpInBufferSize,LPDWORD lpMaxInstances)1164c2c66affSColin Finck GetNamedPipeInfo(HANDLE hNamedPipe,
1165c2c66affSColin Finck                  LPDWORD lpFlags,
1166c2c66affSColin Finck                  LPDWORD lpOutBufferSize,
1167c2c66affSColin Finck                  LPDWORD lpInBufferSize,
1168c2c66affSColin Finck                  LPDWORD lpMaxInstances)
1169c2c66affSColin Finck {
1170c2c66affSColin Finck     FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation;
1171c2c66affSColin Finck     IO_STATUS_BLOCK StatusBlock;
1172c2c66affSColin Finck     NTSTATUS Status;
1173c2c66affSColin Finck 
1174c2c66affSColin Finck     Status = NtQueryInformationFile(hNamedPipe,
1175c2c66affSColin Finck                                     &StatusBlock,
1176c2c66affSColin Finck                                     &PipeLocalInformation,
1177*d6d30f9eSHermès Bélusca-Maïto                                     sizeof(PipeLocalInformation),
1178c2c66affSColin Finck                                     FilePipeLocalInformation);
1179c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1180c2c66affSColin Finck     {
1181c2c66affSColin Finck         BaseSetLastNTError(Status);
1182c2c66affSColin Finck         return FALSE;
1183c2c66affSColin Finck     }
1184c2c66affSColin Finck 
1185c2c66affSColin Finck     if (lpFlags != NULL)
1186c2c66affSColin Finck     {
1187c2c66affSColin Finck         *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
1188*d6d30f9eSHermès Bélusca-Maïto         *lpFlags |= (PipeLocalInformation.NamedPipeType == FILE_PIPE_MESSAGE_TYPE) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
1189c2c66affSColin Finck     }
1190c2c66affSColin Finck 
1191c2c66affSColin Finck     if (lpOutBufferSize != NULL)
1192c2c66affSColin Finck         *lpOutBufferSize = PipeLocalInformation.OutboundQuota;
1193c2c66affSColin Finck 
1194c2c66affSColin Finck     if (lpInBufferSize != NULL)
1195c2c66affSColin Finck         *lpInBufferSize = PipeLocalInformation.InboundQuota;
1196c2c66affSColin Finck 
1197c2c66affSColin Finck     if (lpMaxInstances != NULL)
1198c2c66affSColin Finck     {
1199c2c66affSColin Finck         if (PipeLocalInformation.MaximumInstances >= 255)
1200c2c66affSColin Finck             *lpMaxInstances = PIPE_UNLIMITED_INSTANCES;
1201c2c66affSColin Finck         else
1202c2c66affSColin Finck             *lpMaxInstances = PipeLocalInformation.MaximumInstances;
1203c2c66affSColin Finck     }
1204c2c66affSColin Finck 
1205c2c66affSColin Finck     return TRUE;
1206c2c66affSColin Finck }
1207c2c66affSColin Finck 
1208c2c66affSColin Finck 
1209c2c66affSColin Finck /*
1210c2c66affSColin Finck  * @implemented
1211c2c66affSColin Finck  */
1212c2c66affSColin Finck BOOL
1213c2c66affSColin Finck WINAPI
PeekNamedPipe(HANDLE hNamedPipe,LPVOID lpBuffer,DWORD nBufferSize,LPDWORD lpBytesRead,LPDWORD lpTotalBytesAvail,LPDWORD lpBytesLeftThisMessage)1214c2c66affSColin Finck PeekNamedPipe(HANDLE hNamedPipe,
1215c2c66affSColin Finck               LPVOID lpBuffer,
1216c2c66affSColin Finck               DWORD nBufferSize,
1217c2c66affSColin Finck               LPDWORD lpBytesRead,
1218c2c66affSColin Finck               LPDWORD lpTotalBytesAvail,
1219c2c66affSColin Finck               LPDWORD lpBytesLeftThisMessage)
1220c2c66affSColin Finck {
1221c2c66affSColin Finck     PFILE_PIPE_PEEK_BUFFER Buffer;
1222c2c66affSColin Finck     IO_STATUS_BLOCK Iosb;
1223c2c66affSColin Finck     ULONG BufferSize;
1224c2c66affSColin Finck     ULONG BytesRead;
1225c2c66affSColin Finck     NTSTATUS Status;
1226c2c66affSColin Finck 
1227c2c66affSColin Finck     /* Calculate the buffer space that we'll need and allocate it */
1228c2c66affSColin Finck     BufferSize = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[nBufferSize]);
1229c2c66affSColin Finck     Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
1230c2c66affSColin Finck     if (Buffer == NULL)
1231c2c66affSColin Finck     {
1232c2c66affSColin Finck         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1233c2c66affSColin Finck         return FALSE;
1234c2c66affSColin Finck     }
1235c2c66affSColin Finck 
1236c2c66affSColin Finck     /* Tell the driver to seek */
1237c2c66affSColin Finck     Status = NtFsControlFile(hNamedPipe,
1238c2c66affSColin Finck                              NULL,
1239c2c66affSColin Finck                              NULL,
1240c2c66affSColin Finck                              NULL,
1241c2c66affSColin Finck                              &Iosb,
1242c2c66affSColin Finck                              FSCTL_PIPE_PEEK,
1243c2c66affSColin Finck                              NULL,
1244c2c66affSColin Finck                              0,
1245c2c66affSColin Finck                              Buffer,
1246c2c66affSColin Finck                              BufferSize);
1247c2c66affSColin Finck     if (Status == STATUS_PENDING)
1248c2c66affSColin Finck     {
1249c2c66affSColin Finck         /* Wait for npfs to be done, and update the status */
1250c2c66affSColin Finck         Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
1251c2c66affSColin Finck         if (NT_SUCCESS(Status))
1252c2c66affSColin Finck             Status = Iosb.Status;
1253c2c66affSColin Finck     }
1254c2c66affSColin Finck 
1255c2c66affSColin Finck     /* Overflow is success for us */
1256c2c66affSColin Finck     if (Status == STATUS_BUFFER_OVERFLOW)
1257c2c66affSColin Finck         Status = STATUS_SUCCESS;
1258c2c66affSColin Finck 
1259c2c66affSColin Finck     /* If we failed */
1260c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1261c2c66affSColin Finck     {
1262c2c66affSColin Finck         /* Free the buffer and return failure */
1263c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1264c2c66affSColin Finck         BaseSetLastNTError(Status);
1265c2c66affSColin Finck         return FALSE;
1266c2c66affSColin Finck     }
1267c2c66affSColin Finck 
1268c2c66affSColin Finck     /* Check if caller requested bytes available */
1269c2c66affSColin Finck     if (lpTotalBytesAvail)
1270c2c66affSColin Finck     {
1271c2c66affSColin Finck         /* Return bytes available */
1272c2c66affSColin Finck         *lpTotalBytesAvail = Buffer->ReadDataAvailable;
1273c2c66affSColin Finck     }
1274c2c66affSColin Finck 
1275c2c66affSColin Finck     /* Calculate the bytes returned, minus our structure overhead */
1276c2c66affSColin Finck     BytesRead = (ULONG)(Iosb.Information -
1277c2c66affSColin Finck                         FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
1278c2c66affSColin Finck     ASSERT(BytesRead <= nBufferSize);
1279c2c66affSColin Finck 
1280c2c66affSColin Finck     /* Check if caller requested bytes read */
1281c2c66affSColin Finck     if (lpBytesRead)
1282c2c66affSColin Finck     {
1283c2c66affSColin Finck         /* Return the bytes read */
1284c2c66affSColin Finck         *lpBytesRead = BytesRead;
1285c2c66affSColin Finck     }
1286c2c66affSColin Finck 
1287c2c66affSColin Finck     /* Check if caller requested bytes left */
1288c2c66affSColin Finck     if (lpBytesLeftThisMessage)
1289c2c66affSColin Finck     {
1290c2c66affSColin Finck         /* Calculate total minus what we returned and our structure overhead */
1291c2c66affSColin Finck         *lpBytesLeftThisMessage = Buffer->MessageLength - BytesRead;
1292c2c66affSColin Finck     }
1293c2c66affSColin Finck 
1294c2c66affSColin Finck     /* Check if the caller wanted to see the actual data */
1295c2c66affSColin Finck     if (lpBuffer)
1296c2c66affSColin Finck     {
1297c2c66affSColin Finck         /* Give him what he wants */
1298c2c66affSColin Finck         RtlCopyMemory(lpBuffer,
1299c2c66affSColin Finck                       Buffer->Data,
1300c2c66affSColin Finck                       BytesRead);
1301c2c66affSColin Finck     }
1302c2c66affSColin Finck 
1303c2c66affSColin Finck     /* Free the buffer */
1304c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1305c2c66affSColin Finck 
1306c2c66affSColin Finck     return TRUE;
1307c2c66affSColin Finck }
1308c2c66affSColin Finck 
1309c2c66affSColin Finck 
1310c2c66affSColin Finck /*
1311c2c66affSColin Finck  * @implemented
1312c2c66affSColin Finck  */
1313c2c66affSColin Finck BOOL
1314c2c66affSColin Finck WINAPI
TransactNamedPipe(IN HANDLE hNamedPipe,IN LPVOID lpInBuffer,IN DWORD nInBufferSize,OUT LPVOID lpOutBuffer,IN DWORD nOutBufferSize,OUT LPDWORD lpBytesRead OPTIONAL,IN LPOVERLAPPED lpOverlapped OPTIONAL)1315c2c66affSColin Finck TransactNamedPipe(IN HANDLE hNamedPipe,
1316c2c66affSColin Finck                   IN LPVOID lpInBuffer,
1317c2c66affSColin Finck                   IN DWORD nInBufferSize,
1318c2c66affSColin Finck                   OUT LPVOID lpOutBuffer,
1319c2c66affSColin Finck                   IN DWORD nOutBufferSize,
1320c2c66affSColin Finck                   OUT LPDWORD lpBytesRead  OPTIONAL,
1321c2c66affSColin Finck                   IN LPOVERLAPPED lpOverlapped  OPTIONAL)
1322c2c66affSColin Finck {
1323c2c66affSColin Finck     NTSTATUS Status;
1324c2c66affSColin Finck 
1325c2c66affSColin Finck     if (lpBytesRead != NULL)
1326c2c66affSColin Finck     {
1327c2c66affSColin Finck         *lpBytesRead = 0;
1328c2c66affSColin Finck     }
1329c2c66affSColin Finck 
1330c2c66affSColin Finck     if (lpOverlapped != NULL)
1331c2c66affSColin Finck     {
1332c2c66affSColin Finck         PVOID ApcContext;
1333c2c66affSColin Finck 
1334c2c66affSColin Finck         ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
1335c2c66affSColin Finck         lpOverlapped->Internal = STATUS_PENDING;
1336c2c66affSColin Finck 
1337c2c66affSColin Finck         Status = NtFsControlFile(hNamedPipe,
1338c2c66affSColin Finck                                  lpOverlapped->hEvent,
1339c2c66affSColin Finck                                  NULL,
1340c2c66affSColin Finck                                  ApcContext,
1341c2c66affSColin Finck                                  (PIO_STATUS_BLOCK)lpOverlapped,
1342c2c66affSColin Finck                                  FSCTL_PIPE_TRANSCEIVE,
1343c2c66affSColin Finck                                  lpInBuffer,
1344c2c66affSColin Finck                                  nInBufferSize,
1345c2c66affSColin Finck                                  lpOutBuffer,
1346c2c66affSColin Finck                                  nOutBufferSize);
1347c2c66affSColin Finck         if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
1348c2c66affSColin Finck         {
1349c2c66affSColin Finck             BaseSetLastNTError(Status);
1350c2c66affSColin Finck             return FALSE;
1351c2c66affSColin Finck         }
1352c2c66affSColin Finck 
1353c2c66affSColin Finck         if (lpBytesRead != NULL)
1354c2c66affSColin Finck         {
1355c2c66affSColin Finck             *lpBytesRead = lpOverlapped->InternalHigh;
1356c2c66affSColin Finck         }
1357c2c66affSColin Finck     }
1358c2c66affSColin Finck     else
1359c2c66affSColin Finck     {
1360c2c66affSColin Finck         IO_STATUS_BLOCK Iosb;
1361c2c66affSColin Finck 
1362c2c66affSColin Finck         Status = NtFsControlFile(hNamedPipe,
1363c2c66affSColin Finck                                  NULL,
1364c2c66affSColin Finck                                  NULL,
1365c2c66affSColin Finck                                  NULL,
1366c2c66affSColin Finck                                  &Iosb,
1367c2c66affSColin Finck                                  FSCTL_PIPE_TRANSCEIVE,
1368c2c66affSColin Finck                                  lpInBuffer,
1369c2c66affSColin Finck                                  nInBufferSize,
1370c2c66affSColin Finck                                  lpOutBuffer,
1371c2c66affSColin Finck                                  nOutBufferSize);
1372c2c66affSColin Finck         if (Status == STATUS_PENDING)
1373c2c66affSColin Finck         {
1374c2c66affSColin Finck             Status = NtWaitForSingleObject(hNamedPipe,
1375c2c66affSColin Finck                                            FALSE,
1376c2c66affSColin Finck                                            NULL);
1377c2c66affSColin Finck             if (NT_SUCCESS(Status))
1378c2c66affSColin Finck                 Status = Iosb.Status;
1379c2c66affSColin Finck         }
1380c2c66affSColin Finck 
1381c2c66affSColin Finck         if (NT_SUCCESS(Status))
1382c2c66affSColin Finck         {
1383c2c66affSColin Finck             /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
1384c2c66affSColin Finck                check that case either and crashes (only after the operation
1385c2c66affSColin Finck                completed) */
1386c2c66affSColin Finck             *lpBytesRead = Iosb.Information;
1387c2c66affSColin Finck         }
1388c2c66affSColin Finck         else
1389c2c66affSColin Finck         {
1390c2c66affSColin Finck             BaseSetLastNTError(Status);
1391c2c66affSColin Finck             return FALSE;
1392c2c66affSColin Finck         }
1393c2c66affSColin Finck     }
1394c2c66affSColin Finck 
1395c2c66affSColin Finck     return TRUE;
1396c2c66affSColin Finck }
1397c2c66affSColin Finck 
1398c2c66affSColin Finck /* EOF */
1399