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 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 */ 48*0add5d0aSPierre Schweitzer pRevertToSelf = (BOOL (WINAPI *)(void))GetProcAddress(hAdvapi, "RevertToSelf"); 49*0add5d0aSPierre Schweitzer pGetUserNameW = (BOOL (WINAPI *)(LPWSTR, LPDWORD))GetProcAddress(hAdvapi, "GetUserNameW"); 50*0add5d0aSPierre 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, 7934c39a13SPierre Schweitzer &hToken, sizeof(HANDLE)); 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 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, 145c2c66affSColin Finck L"\\Device\\NamedPipe\\Win32Pipes.%08x.%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 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 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 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 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; 471c2c66affSColin Finck PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo; 472c2c66affSColin Finck 473c2c66affSColin Finck /* Start by making a unicode string of the name */ 474c2c66affSColin Finck TRACE("Sent path: %S\n", lpNamedPipeName); 475c2c66affSColin Finck if (!RtlCreateUnicodeString(&NamedPipeName, lpNamedPipeName)) 476c2c66affSColin Finck { 477c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY); 478c2c66affSColin Finck return FALSE; 479c2c66affSColin Finck } 480c2c66affSColin Finck NameLength = NamedPipeName.Length / sizeof(WCHAR); 481c2c66affSColin Finck 482c2c66affSColin Finck /* All slashes must become backslashes */ 483c2c66affSColin Finck for (i = 0; i < NameLength; i++) 484c2c66affSColin Finck { 485c2c66affSColin Finck /* Check and convert */ 486c2c66affSColin Finck if (NamedPipeName.Buffer[i] == L'/') NamedPipeName.Buffer[i] = L'\\'; 487c2c66affSColin Finck } 488c2c66affSColin Finck 489c2c66affSColin Finck /* Find the path type of the name we were given */ 490c2c66affSColin Finck NewName = NamedPipeName; 491c2c66affSColin Finck Type = RtlDetermineDosPathNameType_U(lpNamedPipeName); 492c2c66affSColin Finck 493c2c66affSColin Finck /* Check if this was a device path, ie : "\\.\pipe\name" */ 494c2c66affSColin Finck if (Type == RtlPathTypeLocalDevice) 495c2c66affSColin Finck { 496c2c66affSColin Finck /* Make sure it's a valid prefix */ 497c2c66affSColin Finck RtlInitUnicodeString(&PipePrefix, L"\\\\.\\pipe\\"); 498c2c66affSColin Finck if (!RtlPrefixUnicodeString(&PipePrefix, &NewName, TRUE)) 499c2c66affSColin Finck { 500c2c66affSColin Finck /* The name is invalid */ 501c2c66affSColin Finck WARN("Invalid name!\n"); 502c2c66affSColin Finck RtlFreeUnicodeString(&NamedPipeName); 503c2c66affSColin Finck BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD); 504c2c66affSColin Finck return FALSE; 505c2c66affSColin Finck } 506c2c66affSColin Finck 507c2c66affSColin Finck /* Move past it */ 508c2c66affSColin Finck NewName.Buffer += PipePrefix.Length / sizeof(WCHAR); 509c2c66affSColin Finck NewName.Length -= PipePrefix.Length; 510c2c66affSColin Finck NewName.MaximumLength -= PipePrefix.Length; 511c2c66affSColin Finck 512c2c66affSColin Finck /* Initialize the Dos Devices name */ 513c2c66affSColin Finck TRACE("NewName: %wZ\n", &NewName); 514c2c66affSColin Finck RtlInitUnicodeString(&DevicePath, L"\\DosDevices\\pipe\\"); 515c2c66affSColin Finck } 516c2c66affSColin Finck else if (Type == RtlPathTypeUncAbsolute) 517c2c66affSColin Finck { 518c2c66affSColin Finck /* The path is \\server\\pipe\name; find the pipename itself */ 519c2c66affSColin Finck p = &NewName.Buffer[2]; 520c2c66affSColin Finck 521c2c66affSColin Finck /* First loop to get past the server name */ 522c2c66affSColin Finck do 523c2c66affSColin Finck { 524c2c66affSColin Finck /* Check if this is a backslash */ 525c2c66affSColin Finck if (*p == L'\\') break; 526c2c66affSColin Finck 527c2c66affSColin Finck /* Check next */ 528c2c66affSColin Finck p++; 529c2c66affSColin Finck } while (*p); 530c2c66affSColin Finck 531c2c66affSColin Finck /* Now make sure the full name contains "pipe\" */ 532c2c66affSColin Finck if ((*p) && !(_wcsnicmp(p + 1, L"pipe\\", sizeof("pipe\\") - sizeof(ANSI_NULL)))) 533c2c66affSColin Finck { 534c2c66affSColin Finck /* Get to the pipe name itself now */ 535c2c66affSColin Finck p += sizeof("pipe\\") - sizeof(ANSI_NULL); 536c2c66affSColin Finck } 537c2c66affSColin Finck else 538c2c66affSColin Finck { 539c2c66affSColin Finck /* The name is invalid */ 540c2c66affSColin Finck WARN("Invalid name!\n"); 541c2c66affSColin Finck RtlFreeUnicodeString(&NamedPipeName); 542c2c66affSColin Finck BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD); 543c2c66affSColin Finck return FALSE; 544c2c66affSColin Finck } 545c2c66affSColin Finck 546c2c66affSColin Finck /* FIXME: Open \DosDevices\Unc\Server\Pipe\Name */ 547c2c66affSColin Finck } 548c2c66affSColin Finck else 549c2c66affSColin Finck { 550c2c66affSColin Finck WARN("Invalid path type\n"); 551c2c66affSColin Finck RtlFreeUnicodeString(&NamedPipeName); 552c2c66affSColin Finck BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD); 553c2c66affSColin Finck return FALSE; 554c2c66affSColin Finck } 555c2c66affSColin Finck 556c2c66affSColin Finck /* Now calculate the total length of the structure and allocate it */ 557c2c66affSColin Finck WaitPipeInfoSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) + 558c2c66affSColin Finck NewName.Length; 559c2c66affSColin Finck WaitPipeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize); 560c2c66affSColin Finck if (WaitPipeInfo == NULL) 561c2c66affSColin Finck { 562c2c66affSColin Finck RtlFreeUnicodeString(&NamedPipeName); 563c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY); 564c2c66affSColin Finck return FALSE; 565c2c66affSColin Finck } 566c2c66affSColin Finck 567c2c66affSColin Finck /* Initialize the object attributes */ 568c2c66affSColin Finck TRACE("Opening: %wZ\n", &DevicePath); 569c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 570c2c66affSColin Finck &DevicePath, 571c2c66affSColin Finck OBJ_CASE_INSENSITIVE, 572c2c66affSColin Finck NULL, 573c2c66affSColin Finck NULL); 574c2c66affSColin Finck 575c2c66affSColin Finck /* Open the path */ 576c2c66affSColin Finck Status = NtOpenFile(&FileHandle, 577c2c66affSColin Finck FILE_READ_ATTRIBUTES | SYNCHRONIZE, 578c2c66affSColin Finck &ObjectAttributes, 579c2c66affSColin Finck &IoStatusBlock, 580c2c66affSColin Finck FILE_SHARE_READ | FILE_SHARE_WRITE, 581c2c66affSColin Finck FILE_SYNCHRONOUS_IO_NONALERT); 582c2c66affSColin Finck if (!NT_SUCCESS(Status)) 583c2c66affSColin Finck { 584c2c66affSColin Finck /* Fail; couldn't open */ 585c2c66affSColin Finck WARN("Status: %lx\n", Status); 586c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo); 587c2c66affSColin Finck RtlFreeUnicodeString(&NamedPipeName); 588c2c66affSColin Finck BaseSetLastNTError(Status); 589c2c66affSColin Finck return FALSE; 590c2c66affSColin Finck } 591c2c66affSColin Finck 592c2c66affSColin Finck /* Check what timeout we got */ 593c2c66affSColin Finck if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT) 594c2c66affSColin Finck { 595c2c66affSColin Finck /* Don't use a timeout */ 596c2c66affSColin Finck WaitPipeInfo->TimeoutSpecified = FALSE; 597c2c66affSColin Finck } 598c2c66affSColin Finck else 599c2c66affSColin Finck { 600c2c66affSColin Finck /* Check if we should wait forever */ 601c2c66affSColin Finck if (nTimeOut == NMPWAIT_WAIT_FOREVER) 602c2c66affSColin Finck { 603c2c66affSColin Finck /* Set the max */ 604c2c66affSColin Finck WaitPipeInfo->Timeout.LowPart = 0; 605c2c66affSColin Finck WaitPipeInfo->Timeout.HighPart = 0x80000000; 606c2c66affSColin Finck } 607c2c66affSColin Finck else 608c2c66affSColin Finck { 609c2c66affSColin Finck /* Convert to NT format */ 610c2c66affSColin Finck WaitPipeInfo->Timeout.QuadPart = nTimeOut * -10000LL; 611c2c66affSColin Finck } 612c2c66affSColin Finck 613c2c66affSColin Finck /* In both cases, we do have a timeout */ 614c2c66affSColin Finck WaitPipeInfo->TimeoutSpecified = TRUE; 615c2c66affSColin Finck } 616c2c66affSColin Finck 617c2c66affSColin Finck /* Set the length and copy the name */ 618c2c66affSColin Finck WaitPipeInfo->NameLength = NewName.Length; 619c2c66affSColin Finck RtlCopyMemory(WaitPipeInfo->Name, NewName.Buffer, NewName.Length); 620c2c66affSColin Finck 621c2c66affSColin Finck /* Get rid of the full name */ 622c2c66affSColin Finck RtlFreeUnicodeString(&NamedPipeName); 623c2c66affSColin Finck 624c2c66affSColin Finck /* Let NPFS know of our request */ 625c2c66affSColin Finck Status = NtFsControlFile(FileHandle, 626c2c66affSColin Finck NULL, 627c2c66affSColin Finck NULL, 628c2c66affSColin Finck NULL, 629c2c66affSColin Finck &IoStatusBlock, 630c2c66affSColin Finck FSCTL_PIPE_WAIT, 631c2c66affSColin Finck WaitPipeInfo, 632c2c66affSColin Finck WaitPipeInfoSize, 633c2c66affSColin Finck NULL, 634c2c66affSColin Finck 0); 635c2c66affSColin Finck 636c2c66affSColin Finck /* Free our pipe info data and close the handle */ 637c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo); 638c2c66affSColin Finck NtClose(FileHandle); 639c2c66affSColin Finck 640c2c66affSColin Finck /* Check the status */ 641c2c66affSColin Finck if (!NT_SUCCESS(Status)) 642c2c66affSColin Finck { 643c2c66affSColin Finck /* Failure to wait on the pipe */ 644c2c66affSColin Finck WARN("Status: %lx\n", Status); 645c2c66affSColin Finck BaseSetLastNTError(Status); 646c2c66affSColin Finck return FALSE; 647c2c66affSColin Finck } 648c2c66affSColin Finck 649c2c66affSColin Finck /* Success */ 650c2c66affSColin Finck return TRUE; 651c2c66affSColin Finck } 652c2c66affSColin Finck 653c2c66affSColin Finck /* 654c2c66affSColin Finck * @implemented 655c2c66affSColin Finck */ 656c2c66affSColin Finck BOOL 657c2c66affSColin Finck WINAPI 658c2c66affSColin Finck ConnectNamedPipe(IN HANDLE hNamedPipe, 659c2c66affSColin Finck IN LPOVERLAPPED lpOverlapped) 660c2c66affSColin Finck { 661c2c66affSColin Finck NTSTATUS Status; 662c2c66affSColin Finck 663c2c66affSColin Finck if (lpOverlapped != NULL) 664c2c66affSColin Finck { 665c2c66affSColin Finck PVOID ApcContext; 666c2c66affSColin Finck 667c2c66affSColin Finck lpOverlapped->Internal = STATUS_PENDING; 668c2c66affSColin Finck ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); 669c2c66affSColin Finck 670c2c66affSColin Finck Status = NtFsControlFile(hNamedPipe, 671c2c66affSColin Finck lpOverlapped->hEvent, 672c2c66affSColin Finck NULL, 673c2c66affSColin Finck ApcContext, 674c2c66affSColin Finck (PIO_STATUS_BLOCK)lpOverlapped, 675c2c66affSColin Finck FSCTL_PIPE_LISTEN, 676c2c66affSColin Finck NULL, 677c2c66affSColin Finck 0, 678c2c66affSColin Finck NULL, 679c2c66affSColin Finck 0); 680c2c66affSColin Finck 681c2c66affSColin Finck /* return FALSE in case of failure and pending operations! */ 682c2c66affSColin Finck if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) 683c2c66affSColin Finck { 684c2c66affSColin Finck BaseSetLastNTError(Status); 685c2c66affSColin Finck return FALSE; 686c2c66affSColin Finck } 687c2c66affSColin Finck } 688c2c66affSColin Finck else 689c2c66affSColin Finck { 690c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 691c2c66affSColin Finck 692c2c66affSColin Finck Status = NtFsControlFile(hNamedPipe, 693c2c66affSColin Finck NULL, 694c2c66affSColin Finck NULL, 695c2c66affSColin Finck NULL, 696c2c66affSColin Finck &Iosb, 697c2c66affSColin Finck FSCTL_PIPE_LISTEN, 698c2c66affSColin Finck NULL, 699c2c66affSColin Finck 0, 700c2c66affSColin Finck NULL, 701c2c66affSColin Finck 0); 702c2c66affSColin Finck 703c2c66affSColin Finck /* wait in case operation is pending */ 704c2c66affSColin Finck if (Status == STATUS_PENDING) 705c2c66affSColin Finck { 706c2c66affSColin Finck Status = NtWaitForSingleObject(hNamedPipe, 707c2c66affSColin Finck FALSE, 708c2c66affSColin Finck NULL); 709c2c66affSColin Finck if (NT_SUCCESS(Status)) 710c2c66affSColin Finck { 711c2c66affSColin Finck Status = Iosb.Status; 712c2c66affSColin Finck } 713c2c66affSColin Finck } 714c2c66affSColin Finck 715c2c66affSColin Finck if (!NT_SUCCESS(Status)) 716c2c66affSColin Finck { 717c2c66affSColin Finck BaseSetLastNTError(Status); 718c2c66affSColin Finck return FALSE; 719c2c66affSColin Finck } 720c2c66affSColin Finck } 721c2c66affSColin Finck 722c2c66affSColin Finck return TRUE; 723c2c66affSColin Finck } 724c2c66affSColin Finck 725c2c66affSColin Finck 726c2c66affSColin Finck /* 727c2c66affSColin Finck * @implemented 728c2c66affSColin Finck */ 729c2c66affSColin Finck BOOL 730c2c66affSColin Finck WINAPI 731c2c66affSColin Finck SetNamedPipeHandleState(HANDLE hNamedPipe, 732c2c66affSColin Finck LPDWORD lpMode, 733c2c66affSColin Finck LPDWORD lpMaxCollectionCount, 734c2c66affSColin Finck LPDWORD lpCollectDataTimeout) 735c2c66affSColin Finck { 736c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 737c2c66affSColin Finck NTSTATUS Status; 738c2c66affSColin Finck 739c2c66affSColin Finck /* Check if the Mode is being changed */ 740c2c66affSColin Finck if (lpMode) 741c2c66affSColin Finck { 742c2c66affSColin Finck FILE_PIPE_INFORMATION Settings; 743c2c66affSColin Finck 744c2c66affSColin Finck /* Set the Completion Mode */ 745c2c66affSColin Finck Settings.CompletionMode = (*lpMode & PIPE_NOWAIT) ? 746c2c66affSColin Finck FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION; 747c2c66affSColin Finck 748c2c66affSColin Finck /* Set the Read Mode */ 749c2c66affSColin Finck Settings.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE) ? 750c2c66affSColin Finck FILE_PIPE_MESSAGE_MODE: FILE_PIPE_BYTE_STREAM_MODE; 751c2c66affSColin Finck 752c2c66affSColin Finck /* Send the changes to the Driver */ 753c2c66affSColin Finck Status = NtSetInformationFile(hNamedPipe, 754c2c66affSColin Finck &Iosb, 755c2c66affSColin Finck &Settings, 756c2c66affSColin Finck sizeof(FILE_PIPE_INFORMATION), 757c2c66affSColin Finck FilePipeInformation); 758c2c66affSColin Finck if (!NT_SUCCESS(Status)) 759c2c66affSColin Finck { 760c2c66affSColin Finck BaseSetLastNTError(Status); 761c2c66affSColin Finck return FALSE; 762c2c66affSColin Finck } 763c2c66affSColin Finck } 764c2c66affSColin Finck 765c2c66affSColin Finck /* Check if the Collection count or Timeout are being changed */ 766c2c66affSColin Finck if (lpMaxCollectionCount || lpCollectDataTimeout) 767c2c66affSColin Finck { 768c2c66affSColin Finck FILE_PIPE_REMOTE_INFORMATION RemoteSettings; 769c2c66affSColin Finck 770c2c66affSColin Finck /* Setting one without the other would delete it, so we read old one */ 771c2c66affSColin Finck if (!lpMaxCollectionCount || !lpCollectDataTimeout) 772c2c66affSColin Finck { 773c2c66affSColin Finck Status = NtQueryInformationFile(hNamedPipe, 774c2c66affSColin Finck &Iosb, 775c2c66affSColin Finck &RemoteSettings, 776c2c66affSColin Finck sizeof(FILE_PIPE_REMOTE_INFORMATION), 777c2c66affSColin Finck FilePipeRemoteInformation); 778c2c66affSColin Finck if (!NT_SUCCESS(Status)) 779c2c66affSColin Finck { 780c2c66affSColin Finck BaseSetLastNTError(Status); 781c2c66affSColin Finck return FALSE; 782c2c66affSColin Finck } 783c2c66affSColin Finck } 784c2c66affSColin Finck 785c2c66affSColin Finck /* Now set the new settings */ 786c2c66affSColin Finck RemoteSettings.MaximumCollectionCount = (lpMaxCollectionCount) ? 787c2c66affSColin Finck *lpMaxCollectionCount : 788c2c66affSColin Finck RemoteSettings.MaximumCollectionCount; 789c2c66affSColin Finck if (lpCollectDataTimeout) 790c2c66affSColin Finck { 791c2c66affSColin Finck /* Convert it to Quad */ 792c2c66affSColin Finck RemoteSettings.CollectDataTime.QuadPart = *lpCollectDataTimeout * -10000LL; 793c2c66affSColin Finck } 794c2c66affSColin Finck 795c2c66affSColin Finck /* Tell the driver to change them */ 796c2c66affSColin Finck Status = NtSetInformationFile(hNamedPipe, 797c2c66affSColin Finck &Iosb, 798c2c66affSColin Finck &RemoteSettings, 799c2c66affSColin Finck sizeof(FILE_PIPE_REMOTE_INFORMATION), 800c2c66affSColin Finck FilePipeRemoteInformation); 801c2c66affSColin Finck if (!NT_SUCCESS(Status)) 802c2c66affSColin Finck { 803c2c66affSColin Finck BaseSetLastNTError(Status); 804c2c66affSColin Finck return FALSE; 805c2c66affSColin Finck } 806c2c66affSColin Finck } 807c2c66affSColin Finck 808c2c66affSColin Finck return TRUE; 809c2c66affSColin Finck } 810c2c66affSColin Finck 811c2c66affSColin Finck 812c2c66affSColin Finck /* 813c2c66affSColin Finck * @implemented 814c2c66affSColin Finck */ 815c2c66affSColin Finck BOOL 816c2c66affSColin Finck WINAPI 817c2c66affSColin Finck CallNamedPipeA(LPCSTR lpNamedPipeName, 818c2c66affSColin Finck LPVOID lpInBuffer, 819c2c66affSColin Finck DWORD nInBufferSize, 820c2c66affSColin Finck LPVOID lpOutBuffer, 821c2c66affSColin Finck DWORD nOutBufferSize, 822c2c66affSColin Finck LPDWORD lpBytesRead, 823c2c66affSColin Finck DWORD nTimeOut) 824c2c66affSColin Finck { 825c2c66affSColin Finck PUNICODE_STRING PipeName = &NtCurrentTeb()->StaticUnicodeString; 826c2c66affSColin Finck ANSI_STRING AnsiPipe; 827c2c66affSColin Finck 828c2c66affSColin Finck /* Initialize the string as ANSI_STRING and convert to Unicode */ 829c2c66affSColin Finck RtlInitAnsiString(&AnsiPipe, (LPSTR)lpNamedPipeName); 830c2c66affSColin Finck RtlAnsiStringToUnicodeString(PipeName, &AnsiPipe, FALSE); 831c2c66affSColin Finck 832c2c66affSColin Finck /* Call the Unicode function */ 833c2c66affSColin Finck return CallNamedPipeW(PipeName->Buffer, 834c2c66affSColin Finck lpInBuffer, 835c2c66affSColin Finck nInBufferSize, 836c2c66affSColin Finck lpOutBuffer, 837c2c66affSColin Finck nOutBufferSize, 838c2c66affSColin Finck lpBytesRead, 839c2c66affSColin Finck nTimeOut); 840c2c66affSColin Finck } 841c2c66affSColin Finck 842c2c66affSColin Finck 843c2c66affSColin Finck /* 844c2c66affSColin Finck * @implemented 845c2c66affSColin Finck */ 846c2c66affSColin Finck BOOL 847c2c66affSColin Finck WINAPI 848c2c66affSColin Finck CallNamedPipeW(LPCWSTR lpNamedPipeName, 849c2c66affSColin Finck LPVOID lpInBuffer, 850c2c66affSColin Finck DWORD nInBufferSize, 851c2c66affSColin Finck LPVOID lpOutBuffer, 852c2c66affSColin Finck DWORD nOutBufferSize, 853c2c66affSColin Finck LPDWORD lpBytesRead, 854c2c66affSColin Finck DWORD nTimeOut) 855c2c66affSColin Finck { 856c2c66affSColin Finck HANDLE hPipe; 857c2c66affSColin Finck BOOL bRetry = TRUE; 858c2c66affSColin Finck BOOL bError; 859c2c66affSColin Finck DWORD dwPipeMode; 860c2c66affSColin Finck 861c2c66affSColin Finck while (TRUE) 862c2c66affSColin Finck { 863c2c66affSColin Finck /* Try creating it */ 864c2c66affSColin Finck hPipe = CreateFileW(lpNamedPipeName, 865c2c66affSColin Finck GENERIC_READ | GENERIC_WRITE, 866c2c66affSColin Finck FILE_SHARE_READ | FILE_SHARE_WRITE, 867c2c66affSColin Finck NULL, 868c2c66affSColin Finck OPEN_EXISTING, 869c2c66affSColin Finck FILE_ATTRIBUTE_NORMAL, 870c2c66affSColin Finck NULL); 871c2c66affSColin Finck 872c2c66affSColin Finck /* Success, break out */ 873c2c66affSColin Finck if (hPipe != INVALID_HANDLE_VALUE) 874c2c66affSColin Finck break; 875c2c66affSColin Finck 876c2c66affSColin Finck /* Already tried twice, give up */ 877c2c66affSColin Finck if (bRetry == FALSE) 878c2c66affSColin Finck return FALSE; 879c2c66affSColin Finck 880c2c66affSColin Finck /* Wait on it */ 881c2c66affSColin Finck WaitNamedPipeW(lpNamedPipeName, nTimeOut); 882c2c66affSColin Finck 883c2c66affSColin Finck /* Get ready to try again */ 884c2c66affSColin Finck bRetry = FALSE; 885c2c66affSColin Finck } 886c2c66affSColin Finck 887c2c66affSColin Finck /* Set the pipe mode */ 888c2c66affSColin Finck dwPipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; 889c2c66affSColin Finck bError = SetNamedPipeHandleState(hPipe, &dwPipeMode, NULL, NULL); 890c2c66affSColin Finck if (!bError) 891c2c66affSColin Finck { 892c2c66affSColin Finck /* Couldn't change state, fail */ 893c2c66affSColin Finck CloseHandle(hPipe); 894c2c66affSColin Finck return FALSE; 895c2c66affSColin Finck } 896c2c66affSColin Finck 897c2c66affSColin Finck /* Do the transact */ 898c2c66affSColin Finck bError = TransactNamedPipe(hPipe, 899c2c66affSColin Finck lpInBuffer, 900c2c66affSColin Finck nInBufferSize, 901c2c66affSColin Finck lpOutBuffer, 902c2c66affSColin Finck nOutBufferSize, 903c2c66affSColin Finck lpBytesRead, 904c2c66affSColin Finck NULL); 905c2c66affSColin Finck 906c2c66affSColin Finck /* Close the handle */ 907c2c66affSColin Finck CloseHandle(hPipe); 908c2c66affSColin Finck 909c2c66affSColin Finck return bError; 910c2c66affSColin Finck } 911c2c66affSColin Finck 912c2c66affSColin Finck 913c2c66affSColin Finck /* 914c2c66affSColin Finck * @implemented 915c2c66affSColin Finck */ 916c2c66affSColin Finck BOOL 917c2c66affSColin Finck WINAPI 918c2c66affSColin Finck DisconnectNamedPipe(HANDLE hNamedPipe) 919c2c66affSColin Finck { 920c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 921c2c66affSColin Finck NTSTATUS Status; 922c2c66affSColin Finck 923c2c66affSColin Finck /* Send the FSCTL to the driver */ 924c2c66affSColin Finck Status = NtFsControlFile(hNamedPipe, 925c2c66affSColin Finck NULL, 926c2c66affSColin Finck NULL, 927c2c66affSColin Finck NULL, 928c2c66affSColin Finck &Iosb, 929c2c66affSColin Finck FSCTL_PIPE_DISCONNECT, 930c2c66affSColin Finck NULL, 931c2c66affSColin Finck 0, 932c2c66affSColin Finck NULL, 933c2c66affSColin Finck 0); 934c2c66affSColin Finck if (Status == STATUS_PENDING) 935c2c66affSColin Finck { 936c2c66affSColin Finck /* Wait on NPFS to finish and get updated status */ 937c2c66affSColin Finck Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL); 938c2c66affSColin Finck if (NT_SUCCESS(Status)) 939c2c66affSColin Finck Status = Iosb.Status; 940c2c66affSColin Finck } 941c2c66affSColin Finck 942c2c66affSColin Finck /* Check for error */ 943c2c66affSColin Finck if (!NT_SUCCESS(Status)) 944c2c66affSColin Finck { 945c2c66affSColin Finck /* Fail */ 946c2c66affSColin Finck BaseSetLastNTError(Status); 947c2c66affSColin Finck return FALSE; 948c2c66affSColin Finck } 949c2c66affSColin Finck 950c2c66affSColin Finck return TRUE; 951c2c66affSColin Finck } 952c2c66affSColin Finck 953c2c66affSColin Finck 954c2c66affSColin Finck /* 955c2c66affSColin Finck * @unimplemented 956c2c66affSColin Finck */ 957c2c66affSColin Finck BOOL 958c2c66affSColin Finck WINAPI 959c2c66affSColin Finck GetNamedPipeHandleStateW(HANDLE hNamedPipe, 960c2c66affSColin Finck LPDWORD lpState, 961c2c66affSColin Finck LPDWORD lpCurInstances, 962c2c66affSColin Finck LPDWORD lpMaxCollectionCount, 963c2c66affSColin Finck LPDWORD lpCollectDataTimeout, 964c2c66affSColin Finck LPWSTR lpUserName, 965c2c66affSColin Finck DWORD nMaxUserNameSize) 966c2c66affSColin Finck { 967c2c66affSColin Finck IO_STATUS_BLOCK StatusBlock; 968c2c66affSColin Finck NTSTATUS Status; 969c2c66affSColin Finck 970c2c66affSColin Finck if (lpState != NULL) 971c2c66affSColin Finck { 972c2c66affSColin Finck FILE_PIPE_INFORMATION PipeInfo; 973c2c66affSColin Finck 974c2c66affSColin Finck Status = NtQueryInformationFile(hNamedPipe, 975c2c66affSColin Finck &StatusBlock, 976c2c66affSColin Finck &PipeInfo, 977c2c66affSColin Finck sizeof(FILE_PIPE_INFORMATION), 978c2c66affSColin Finck FilePipeInformation); 979c2c66affSColin Finck if (!NT_SUCCESS(Status)) 980c2c66affSColin Finck { 981c2c66affSColin Finck BaseSetLastNTError(Status); 982c2c66affSColin Finck return FALSE; 983c2c66affSColin Finck } 984c2c66affSColin Finck 985c2c66affSColin Finck *lpState = ((PipeInfo.CompletionMode != FILE_PIPE_QUEUE_OPERATION) ? PIPE_NOWAIT : PIPE_WAIT); 986c2c66affSColin Finck *lpState |= ((PipeInfo.ReadMode != FILE_PIPE_BYTE_STREAM_MODE) ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE); 987c2c66affSColin Finck } 988c2c66affSColin Finck 989c2c66affSColin Finck if(lpCurInstances != NULL) 990c2c66affSColin Finck { 991c2c66affSColin Finck FILE_PIPE_LOCAL_INFORMATION LocalInfo; 992c2c66affSColin Finck 993c2c66affSColin Finck Status = NtQueryInformationFile(hNamedPipe, 994c2c66affSColin Finck &StatusBlock, 995c2c66affSColin Finck &LocalInfo, 996c2c66affSColin Finck sizeof(FILE_PIPE_LOCAL_INFORMATION), 997c2c66affSColin Finck FilePipeLocalInformation); 998c2c66affSColin Finck if (!NT_SUCCESS(Status)) 999c2c66affSColin Finck { 1000c2c66affSColin Finck BaseSetLastNTError(Status); 1001c2c66affSColin Finck return FALSE; 1002c2c66affSColin Finck } 1003c2c66affSColin Finck 1004c2c66affSColin Finck *lpCurInstances = min(LocalInfo.CurrentInstances, PIPE_UNLIMITED_INSTANCES); 1005c2c66affSColin Finck } 1006c2c66affSColin Finck 1007c2c66affSColin Finck if (lpMaxCollectionCount != NULL || lpCollectDataTimeout != NULL) 1008c2c66affSColin Finck { 1009c2c66affSColin Finck FILE_PIPE_REMOTE_INFORMATION RemoteInfo; 1010c2c66affSColin Finck 1011c2c66affSColin Finck Status = NtQueryInformationFile(hNamedPipe, 1012c2c66affSColin Finck &StatusBlock, 1013c2c66affSColin Finck &RemoteInfo, 1014c2c66affSColin Finck sizeof(FILE_PIPE_REMOTE_INFORMATION), 1015c2c66affSColin Finck FilePipeRemoteInformation); 1016c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1017c2c66affSColin Finck { 1018c2c66affSColin Finck BaseSetLastNTError(Status); 1019c2c66affSColin Finck return FALSE; 1020c2c66affSColin Finck } 1021c2c66affSColin Finck 1022c2c66affSColin Finck if (lpMaxCollectionCount != NULL) 1023c2c66affSColin Finck { 1024c2c66affSColin Finck *lpMaxCollectionCount = RemoteInfo.MaximumCollectionCount; 1025c2c66affSColin Finck } 1026c2c66affSColin Finck 1027c2c66affSColin Finck if (lpCollectDataTimeout != NULL) 1028c2c66affSColin Finck { 102919cef780SPierre Schweitzer LARGE_INTEGER CollectDataTime; 103019cef780SPierre Schweitzer 103119cef780SPierre Schweitzer /* Convert time and return it */ 103219cef780SPierre Schweitzer RemoteInfo.CollectDataTime.QuadPart *= -1; 103319cef780SPierre Schweitzer CollectDataTime = RtlExtendedLargeIntegerDivide(RemoteInfo.CollectDataTime, 10000, NULL); 103419cef780SPierre Schweitzer /* In case of overflow, just return MAX - 1 */ 103519cef780SPierre Schweitzer if (CollectDataTime.HighPart != 0) 103619cef780SPierre Schweitzer { 103719cef780SPierre Schweitzer *lpCollectDataTimeout = -2; 103819cef780SPierre Schweitzer } 103919cef780SPierre Schweitzer else 104019cef780SPierre Schweitzer { 104119cef780SPierre Schweitzer *lpCollectDataTimeout = CollectDataTime.LowPart; 104219cef780SPierre Schweitzer } 1043c2c66affSColin Finck } 1044c2c66affSColin Finck } 1045c2c66affSColin Finck 1046c2c66affSColin Finck if (lpUserName != NULL) 1047c2c66affSColin Finck { 104819cef780SPierre Schweitzer return NpGetUserNamep(hNamedPipe, lpUserName, nMaxUserNameSize); 1049c2c66affSColin Finck } 1050c2c66affSColin Finck 1051c2c66affSColin Finck return TRUE; 1052c2c66affSColin Finck } 1053c2c66affSColin Finck 1054c2c66affSColin Finck 1055c2c66affSColin Finck /* 1056c2c66affSColin Finck * @implemented 1057c2c66affSColin Finck */ 1058c2c66affSColin Finck BOOL 1059c2c66affSColin Finck WINAPI 1060c2c66affSColin Finck GetNamedPipeHandleStateA(HANDLE hNamedPipe, 1061c2c66affSColin Finck LPDWORD lpState, 1062c2c66affSColin Finck LPDWORD lpCurInstances, 1063c2c66affSColin Finck LPDWORD lpMaxCollectionCount, 1064c2c66affSColin Finck LPDWORD lpCollectDataTimeout, 1065c2c66affSColin Finck LPSTR lpUserName, 1066c2c66affSColin Finck DWORD nMaxUserNameSize) 1067c2c66affSColin Finck { 1068c2c66affSColin Finck UNICODE_STRING UserNameW = { 0, 0, NULL }; 1069c2c66affSColin Finck ANSI_STRING UserNameA; 1070c2c66affSColin Finck BOOL Ret; 1071c2c66affSColin Finck 1072c2c66affSColin Finck if(lpUserName != NULL) 1073c2c66affSColin Finck { 1074c2c66affSColin Finck UserNameW.MaximumLength = (USHORT)nMaxUserNameSize * sizeof(WCHAR); 1075c2c66affSColin Finck UserNameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW.MaximumLength); 1076c2c66affSColin Finck if (UserNameW.Buffer == NULL) 1077c2c66affSColin Finck { 1078c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1079c2c66affSColin Finck return FALSE; 1080c2c66affSColin Finck } 1081c2c66affSColin Finck 1082c2c66affSColin Finck UserNameA.Buffer = lpUserName; 1083c2c66affSColin Finck UserNameA.Length = 0; 1084c2c66affSColin Finck UserNameA.MaximumLength = (USHORT)nMaxUserNameSize; 1085c2c66affSColin Finck } 1086c2c66affSColin Finck 1087c2c66affSColin Finck Ret = GetNamedPipeHandleStateW(hNamedPipe, 1088c2c66affSColin Finck lpState, 1089c2c66affSColin Finck lpCurInstances, 1090c2c66affSColin Finck lpMaxCollectionCount, 1091c2c66affSColin Finck lpCollectDataTimeout, 1092c2c66affSColin Finck UserNameW.Buffer, 1093c2c66affSColin Finck nMaxUserNameSize); 1094c2c66affSColin Finck if (Ret && lpUserName != NULL) 1095c2c66affSColin Finck { 1096c2c66affSColin Finck NTSTATUS Status; 1097c2c66affSColin Finck 1098c2c66affSColin Finck RtlInitUnicodeString(&UserNameW, UserNameW.Buffer); 1099c2c66affSColin Finck Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE); 1100c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1101c2c66affSColin Finck { 1102c2c66affSColin Finck BaseSetLastNTError(Status); 1103c2c66affSColin Finck Ret = FALSE; 1104c2c66affSColin Finck } 1105c2c66affSColin Finck } 1106c2c66affSColin Finck 1107c2c66affSColin Finck if (UserNameW.Buffer != NULL) 1108c2c66affSColin Finck { 1109c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW.Buffer); 1110c2c66affSColin Finck } 1111c2c66affSColin Finck 1112c2c66affSColin Finck return Ret; 1113c2c66affSColin Finck } 1114c2c66affSColin Finck 1115c2c66affSColin Finck 1116c2c66affSColin Finck /* 1117c2c66affSColin Finck * @implemented 1118c2c66affSColin Finck */ 1119c2c66affSColin Finck BOOL 1120c2c66affSColin Finck WINAPI 1121c2c66affSColin Finck GetNamedPipeInfo(HANDLE hNamedPipe, 1122c2c66affSColin Finck LPDWORD lpFlags, 1123c2c66affSColin Finck LPDWORD lpOutBufferSize, 1124c2c66affSColin Finck LPDWORD lpInBufferSize, 1125c2c66affSColin Finck LPDWORD lpMaxInstances) 1126c2c66affSColin Finck { 1127c2c66affSColin Finck FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation; 1128c2c66affSColin Finck IO_STATUS_BLOCK StatusBlock; 1129c2c66affSColin Finck NTSTATUS Status; 1130c2c66affSColin Finck 1131c2c66affSColin Finck Status = NtQueryInformationFile(hNamedPipe, 1132c2c66affSColin Finck &StatusBlock, 1133c2c66affSColin Finck &PipeLocalInformation, 1134c2c66affSColin Finck sizeof(FILE_PIPE_LOCAL_INFORMATION), 1135c2c66affSColin Finck FilePipeLocalInformation); 1136c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1137c2c66affSColin Finck { 1138c2c66affSColin Finck BaseSetLastNTError(Status); 1139c2c66affSColin Finck return FALSE; 1140c2c66affSColin Finck } 1141c2c66affSColin Finck 1142c2c66affSColin Finck if (lpFlags != NULL) 1143c2c66affSColin Finck { 1144c2c66affSColin Finck *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END; 1145c2c66affSColin Finck *lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE; 1146c2c66affSColin Finck } 1147c2c66affSColin Finck 1148c2c66affSColin Finck if (lpOutBufferSize != NULL) 1149c2c66affSColin Finck *lpOutBufferSize = PipeLocalInformation.OutboundQuota; 1150c2c66affSColin Finck 1151c2c66affSColin Finck if (lpInBufferSize != NULL) 1152c2c66affSColin Finck *lpInBufferSize = PipeLocalInformation.InboundQuota; 1153c2c66affSColin Finck 1154c2c66affSColin Finck if (lpMaxInstances != NULL) 1155c2c66affSColin Finck { 1156c2c66affSColin Finck if (PipeLocalInformation.MaximumInstances >= 255) 1157c2c66affSColin Finck *lpMaxInstances = PIPE_UNLIMITED_INSTANCES; 1158c2c66affSColin Finck else 1159c2c66affSColin Finck *lpMaxInstances = PipeLocalInformation.MaximumInstances; 1160c2c66affSColin Finck } 1161c2c66affSColin Finck 1162c2c66affSColin Finck return TRUE; 1163c2c66affSColin Finck } 1164c2c66affSColin Finck 1165c2c66affSColin Finck 1166c2c66affSColin Finck /* 1167c2c66affSColin Finck * @implemented 1168c2c66affSColin Finck */ 1169c2c66affSColin Finck BOOL 1170c2c66affSColin Finck WINAPI 1171c2c66affSColin Finck PeekNamedPipe(HANDLE hNamedPipe, 1172c2c66affSColin Finck LPVOID lpBuffer, 1173c2c66affSColin Finck DWORD nBufferSize, 1174c2c66affSColin Finck LPDWORD lpBytesRead, 1175c2c66affSColin Finck LPDWORD lpTotalBytesAvail, 1176c2c66affSColin Finck LPDWORD lpBytesLeftThisMessage) 1177c2c66affSColin Finck { 1178c2c66affSColin Finck PFILE_PIPE_PEEK_BUFFER Buffer; 1179c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 1180c2c66affSColin Finck ULONG BufferSize; 1181c2c66affSColin Finck ULONG BytesRead; 1182c2c66affSColin Finck NTSTATUS Status; 1183c2c66affSColin Finck 1184c2c66affSColin Finck /* Calculate the buffer space that we'll need and allocate it */ 1185c2c66affSColin Finck BufferSize = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[nBufferSize]); 1186c2c66affSColin Finck Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize); 1187c2c66affSColin Finck if (Buffer == NULL) 1188c2c66affSColin Finck { 1189c2c66affSColin Finck SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1190c2c66affSColin Finck return FALSE; 1191c2c66affSColin Finck } 1192c2c66affSColin Finck 1193c2c66affSColin Finck /* Tell the driver to seek */ 1194c2c66affSColin Finck Status = NtFsControlFile(hNamedPipe, 1195c2c66affSColin Finck NULL, 1196c2c66affSColin Finck NULL, 1197c2c66affSColin Finck NULL, 1198c2c66affSColin Finck &Iosb, 1199c2c66affSColin Finck FSCTL_PIPE_PEEK, 1200c2c66affSColin Finck NULL, 1201c2c66affSColin Finck 0, 1202c2c66affSColin Finck Buffer, 1203c2c66affSColin Finck BufferSize); 1204c2c66affSColin Finck if (Status == STATUS_PENDING) 1205c2c66affSColin Finck { 1206c2c66affSColin Finck /* Wait for npfs to be done, and update the status */ 1207c2c66affSColin Finck Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL); 1208c2c66affSColin Finck if (NT_SUCCESS(Status)) 1209c2c66affSColin Finck Status = Iosb.Status; 1210c2c66affSColin Finck } 1211c2c66affSColin Finck 1212c2c66affSColin Finck /* Overflow is success for us */ 1213c2c66affSColin Finck if (Status == STATUS_BUFFER_OVERFLOW) 1214c2c66affSColin Finck Status = STATUS_SUCCESS; 1215c2c66affSColin Finck 1216c2c66affSColin Finck /* If we failed */ 1217c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1218c2c66affSColin Finck { 1219c2c66affSColin Finck /* Free the buffer and return failure */ 1220c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 1221c2c66affSColin Finck BaseSetLastNTError(Status); 1222c2c66affSColin Finck return FALSE; 1223c2c66affSColin Finck } 1224c2c66affSColin Finck 1225c2c66affSColin Finck /* Check if caller requested bytes available */ 1226c2c66affSColin Finck if (lpTotalBytesAvail) 1227c2c66affSColin Finck { 1228c2c66affSColin Finck /* Return bytes available */ 1229c2c66affSColin Finck *lpTotalBytesAvail = Buffer->ReadDataAvailable; 1230c2c66affSColin Finck } 1231c2c66affSColin Finck 1232c2c66affSColin Finck /* Calculate the bytes returned, minus our structure overhead */ 1233c2c66affSColin Finck BytesRead = (ULONG)(Iosb.Information - 1234c2c66affSColin Finck FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0])); 1235c2c66affSColin Finck ASSERT(BytesRead <= nBufferSize); 1236c2c66affSColin Finck 1237c2c66affSColin Finck /* Check if caller requested bytes read */ 1238c2c66affSColin Finck if (lpBytesRead) 1239c2c66affSColin Finck { 1240c2c66affSColin Finck /* Return the bytes read */ 1241c2c66affSColin Finck *lpBytesRead = BytesRead; 1242c2c66affSColin Finck } 1243c2c66affSColin Finck 1244c2c66affSColin Finck /* Check if caller requested bytes left */ 1245c2c66affSColin Finck if (lpBytesLeftThisMessage) 1246c2c66affSColin Finck { 1247c2c66affSColin Finck /* Calculate total minus what we returned and our structure overhead */ 1248c2c66affSColin Finck *lpBytesLeftThisMessage = Buffer->MessageLength - BytesRead; 1249c2c66affSColin Finck } 1250c2c66affSColin Finck 1251c2c66affSColin Finck /* Check if the caller wanted to see the actual data */ 1252c2c66affSColin Finck if (lpBuffer) 1253c2c66affSColin Finck { 1254c2c66affSColin Finck /* Give him what he wants */ 1255c2c66affSColin Finck RtlCopyMemory(lpBuffer, 1256c2c66affSColin Finck Buffer->Data, 1257c2c66affSColin Finck BytesRead); 1258c2c66affSColin Finck } 1259c2c66affSColin Finck 1260c2c66affSColin Finck /* Free the buffer */ 1261c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 1262c2c66affSColin Finck 1263c2c66affSColin Finck return TRUE; 1264c2c66affSColin Finck } 1265c2c66affSColin Finck 1266c2c66affSColin Finck 1267c2c66affSColin Finck /* 1268c2c66affSColin Finck * @implemented 1269c2c66affSColin Finck */ 1270c2c66affSColin Finck BOOL 1271c2c66affSColin Finck WINAPI 1272c2c66affSColin Finck TransactNamedPipe(IN HANDLE hNamedPipe, 1273c2c66affSColin Finck IN LPVOID lpInBuffer, 1274c2c66affSColin Finck IN DWORD nInBufferSize, 1275c2c66affSColin Finck OUT LPVOID lpOutBuffer, 1276c2c66affSColin Finck IN DWORD nOutBufferSize, 1277c2c66affSColin Finck OUT LPDWORD lpBytesRead OPTIONAL, 1278c2c66affSColin Finck IN LPOVERLAPPED lpOverlapped OPTIONAL) 1279c2c66affSColin Finck { 1280c2c66affSColin Finck NTSTATUS Status; 1281c2c66affSColin Finck 1282c2c66affSColin Finck if (lpBytesRead != NULL) 1283c2c66affSColin Finck { 1284c2c66affSColin Finck *lpBytesRead = 0; 1285c2c66affSColin Finck } 1286c2c66affSColin Finck 1287c2c66affSColin Finck if (lpOverlapped != NULL) 1288c2c66affSColin Finck { 1289c2c66affSColin Finck PVOID ApcContext; 1290c2c66affSColin Finck 1291c2c66affSColin Finck ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); 1292c2c66affSColin Finck lpOverlapped->Internal = STATUS_PENDING; 1293c2c66affSColin Finck 1294c2c66affSColin Finck Status = NtFsControlFile(hNamedPipe, 1295c2c66affSColin Finck lpOverlapped->hEvent, 1296c2c66affSColin Finck NULL, 1297c2c66affSColin Finck ApcContext, 1298c2c66affSColin Finck (PIO_STATUS_BLOCK)lpOverlapped, 1299c2c66affSColin Finck FSCTL_PIPE_TRANSCEIVE, 1300c2c66affSColin Finck lpInBuffer, 1301c2c66affSColin Finck nInBufferSize, 1302c2c66affSColin Finck lpOutBuffer, 1303c2c66affSColin Finck nOutBufferSize); 1304c2c66affSColin Finck if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) 1305c2c66affSColin Finck { 1306c2c66affSColin Finck BaseSetLastNTError(Status); 1307c2c66affSColin Finck return FALSE; 1308c2c66affSColin Finck } 1309c2c66affSColin Finck 1310c2c66affSColin Finck if (lpBytesRead != NULL) 1311c2c66affSColin Finck { 1312c2c66affSColin Finck *lpBytesRead = lpOverlapped->InternalHigh; 1313c2c66affSColin Finck } 1314c2c66affSColin Finck } 1315c2c66affSColin Finck else 1316c2c66affSColin Finck { 1317c2c66affSColin Finck IO_STATUS_BLOCK Iosb; 1318c2c66affSColin Finck 1319c2c66affSColin Finck Status = NtFsControlFile(hNamedPipe, 1320c2c66affSColin Finck NULL, 1321c2c66affSColin Finck NULL, 1322c2c66affSColin Finck NULL, 1323c2c66affSColin Finck &Iosb, 1324c2c66affSColin Finck FSCTL_PIPE_TRANSCEIVE, 1325c2c66affSColin Finck lpInBuffer, 1326c2c66affSColin Finck nInBufferSize, 1327c2c66affSColin Finck lpOutBuffer, 1328c2c66affSColin Finck nOutBufferSize); 1329c2c66affSColin Finck if (Status == STATUS_PENDING) 1330c2c66affSColin Finck { 1331c2c66affSColin Finck Status = NtWaitForSingleObject(hNamedPipe, 1332c2c66affSColin Finck FALSE, 1333c2c66affSColin Finck NULL); 1334c2c66affSColin Finck if (NT_SUCCESS(Status)) 1335c2c66affSColin Finck Status = Iosb.Status; 1336c2c66affSColin Finck } 1337c2c66affSColin Finck 1338c2c66affSColin Finck if (NT_SUCCESS(Status)) 1339c2c66affSColin Finck { 1340c2c66affSColin Finck /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't 1341c2c66affSColin Finck check that case either and crashes (only after the operation 1342c2c66affSColin Finck completed) */ 1343c2c66affSColin Finck *lpBytesRead = Iosb.Information; 1344c2c66affSColin Finck } 1345c2c66affSColin Finck else 1346c2c66affSColin Finck { 1347c2c66affSColin Finck BaseSetLastNTError(Status); 1348c2c66affSColin Finck return FALSE; 1349c2c66affSColin Finck } 1350c2c66affSColin Finck } 1351c2c66affSColin Finck 1352c2c66affSColin Finck return TRUE; 1353c2c66affSColin Finck } 1354c2c66affSColin Finck 1355c2c66affSColin Finck /* EOF */ 1356