ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

npipe.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Win32 Kernel Library
00004  * FILE:            lib/kernel32/file/npipe.c
00005  * PURPOSE:         Named Pipe Functions
00006  * PROGRAMMER:      Alex Ionescu (alex@relsoft.net)
00007  *                  Ariadne ( ariadne@xs4all.nl)
00008  */
00009 
00010 /* INCLUDES *******************************************************************/
00011 
00012 #include <k32.h>
00013 #define NDEBUG
00014 #include <debug.h>
00015 DEBUG_CHANNEL(kernel32file);
00016 
00017 //#define USING_PROPER_NPFS_WAIT_SEMANTICS
00018 
00019 /* GLOBALS ********************************************************************/
00020 
00021 LONG ProcessPipeId;
00022 
00023 /* FUNCTIONS ******************************************************************/
00024 
00025 /*
00026  * @implemented
00027  */
00028 BOOL
00029 WINAPI
00030 CreatePipe(PHANDLE hReadPipe,
00031            PHANDLE hWritePipe,
00032            LPSECURITY_ATTRIBUTES lpPipeAttributes,
00033            DWORD nSize)
00034 {
00035     WCHAR Buffer[64];
00036     UNICODE_STRING PipeName;
00037     OBJECT_ATTRIBUTES ObjectAttributes;
00038     IO_STATUS_BLOCK StatusBlock;
00039     LARGE_INTEGER DefaultTimeout;
00040     NTSTATUS Status;
00041     HANDLE ReadPipeHandle;
00042     HANDLE WritePipeHandle;
00043     LONG PipeId;
00044     ULONG Attributes;
00045     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
00046 
00047     /* Set the timeout to 120 seconds */
00048     DefaultTimeout.QuadPart = -1200000000;
00049 
00050     /* Use default buffer size if desired */
00051     if (!nSize) nSize = 0x1000;
00052 
00053     /* Increase the Pipe ID */
00054     PipeId = InterlockedIncrement(&ProcessPipeId);
00055 
00056     /* Create the pipe name */
00057     swprintf(Buffer,
00058              L"\\Device\\NamedPipe\\Win32Pipes.%08x.%08x",
00059              NtCurrentTeb()->ClientId.UniqueProcess,
00060              PipeId);
00061     RtlInitUnicodeString(&PipeName, Buffer);
00062 
00063     /* Always use case insensitive */
00064     Attributes = OBJ_CASE_INSENSITIVE;
00065 
00066     /* Check if we got attributes */
00067     if (lpPipeAttributes)
00068     {
00069         /* Use the attributes' SD instead */
00070         SecurityDescriptor = lpPipeAttributes->lpSecurityDescriptor;
00071 
00072         /* Set OBJ_INHERIT if requested */
00073         if (lpPipeAttributes->bInheritHandle) Attributes |= OBJ_INHERIT;
00074     }
00075 
00076     /* Initialize the attributes */
00077     InitializeObjectAttributes(&ObjectAttributes,
00078                                &PipeName,
00079                                Attributes,
00080                                NULL,
00081                                SecurityDescriptor);
00082 
00083     /* Create the named pipe */
00084     Status = NtCreateNamedPipeFile(&ReadPipeHandle,
00085                                    GENERIC_READ |FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
00086                                    &ObjectAttributes,
00087                                    &StatusBlock,
00088                                    FILE_SHARE_READ | FILE_SHARE_WRITE,
00089                                    FILE_CREATE,
00090                                    FILE_SYNCHRONOUS_IO_NONALERT,
00091                                    FILE_PIPE_BYTE_STREAM_TYPE,
00092                                    FILE_PIPE_BYTE_STREAM_MODE,
00093                                    FILE_PIPE_QUEUE_OPERATION,
00094                                    1,
00095                                    nSize,
00096                                    nSize,
00097                                    &DefaultTimeout);
00098     if (!NT_SUCCESS(Status))
00099     {
00100         /* Convert error and fail */
00101         WARN("Status: %lx\n", Status);
00102         BaseSetLastNTError(Status);
00103         return FALSE;
00104     }
00105 
00106     /* Now try opening it for write access */
00107     Status = NtOpenFile(&WritePipeHandle,
00108                         FILE_GENERIC_WRITE | SYNCHRONIZE,
00109                         &ObjectAttributes,
00110                         &StatusBlock,
00111                         FILE_SHARE_READ,
00112                         FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
00113     if (!NT_SUCCESS(Status))
00114     {
00115         /* Convert error and fail */
00116         WARN("Status: %lx\n", Status);
00117         NtClose(ReadPipeHandle);
00118         BaseSetLastNTError(Status);
00119         return FALSE;
00120     }
00121 
00122     /* Return both handles */
00123     *hReadPipe = ReadPipeHandle;
00124     *hWritePipe = WritePipeHandle;
00125     return TRUE;
00126 }
00127 
00128 /*
00129  * @implemented
00130  */
00131 HANDLE
00132 WINAPI
00133 CreateNamedPipeA(LPCSTR lpName,
00134                  DWORD dwOpenMode,
00135                  DWORD dwPipeMode,
00136                  DWORD nMaxInstances,
00137                  DWORD nOutBufferSize,
00138                  DWORD nInBufferSize,
00139                  DWORD nDefaultTimeOut,
00140                  LPSECURITY_ATTRIBUTES lpSecurityAttributes)
00141 {
00142     /* Call the W(ide) function */
00143     ConvertWin32AnsiChangeApiToUnicodeApi(CreateNamedPipe,
00144                                           lpName,
00145                                           dwOpenMode,
00146                                           dwPipeMode,
00147                                           nMaxInstances,
00148                                           nOutBufferSize,
00149                                           nInBufferSize,
00150                                           nDefaultTimeOut,
00151                                           lpSecurityAttributes);
00152 }
00153 
00154 
00155 /*
00156  * @implemented
00157  */
00158 HANDLE
00159 WINAPI
00160 CreateNamedPipeW(LPCWSTR lpName,
00161                  DWORD dwOpenMode,
00162                  DWORD dwPipeMode,
00163                  DWORD nMaxInstances,
00164                  DWORD nOutBufferSize,
00165                  DWORD nInBufferSize,
00166                  DWORD nDefaultTimeOut,
00167                  LPSECURITY_ATTRIBUTES lpSecurityAttributes)
00168 {
00169     UNICODE_STRING NamedPipeName;
00170     BOOL Result;
00171     NTSTATUS Status;
00172     OBJECT_ATTRIBUTES ObjectAttributes;
00173     HANDLE PipeHandle;
00174     ACCESS_MASK DesiredAccess;
00175     ULONG CreateOptions = 0;
00176     ULONG WriteModeMessage;
00177     ULONG ReadModeMessage;
00178     ULONG NonBlocking;
00179     IO_STATUS_BLOCK Iosb;
00180     ULONG ShareAccess = 0, Attributes;
00181     LARGE_INTEGER DefaultTimeOut;
00182     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
00183 
00184     /* Check for valid instances */
00185     if (nMaxInstances == 0 || nMaxInstances > PIPE_UNLIMITED_INSTANCES)
00186     {
00187         /* Fail */
00188         SetLastError(ERROR_INVALID_PARAMETER);
00189         return INVALID_HANDLE_VALUE;
00190     }
00191 
00192     /* Convert to NT syntax */
00193     if (nMaxInstances == PIPE_UNLIMITED_INSTANCES)
00194         nMaxInstances = -1;
00195 
00196     /* Convert the name */
00197     Result = RtlDosPathNameToNtPathName_U(lpName,
00198                                            &NamedPipeName,
00199                                            NULL,
00200                                            NULL);
00201     if (!Result)
00202     {
00203         /* Conversion failed */
00204         SetLastError(ERROR_PATH_NOT_FOUND);
00205         return INVALID_HANDLE_VALUE;
00206     }
00207 
00208     TRACE("Pipe name: %wZ\n", &NamedPipeName);
00209     TRACE("Pipe name: %S\n", NamedPipeName.Buffer);
00210 
00211     /* Always case insensitive, check if we got extra attributes */
00212     Attributes = OBJ_CASE_INSENSITIVE;
00213     if(lpSecurityAttributes)
00214     {
00215         /* We did; get the security descriptor */
00216         SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
00217 
00218         /* And check if this is pipe's handle will beinheritable */
00219         if (lpSecurityAttributes->bInheritHandle)
00220             Attributes |= OBJ_INHERIT;
00221     }
00222 
00223     /* Now we can initialize the object attributes */
00224     InitializeObjectAttributes(&ObjectAttributes,
00225                                &NamedPipeName,
00226                                Attributes,
00227                                NULL,
00228                                SecurityDescriptor);
00229 
00230     /* Setup the default Desired Access */
00231     DesiredAccess = SYNCHRONIZE | (dwOpenMode & (WRITE_DAC |
00232                                                  WRITE_OWNER |
00233                                                  ACCESS_SYSTEM_SECURITY));
00234 
00235     /* Convert to NT Create Flags */
00236     if (dwOpenMode & FILE_FLAG_WRITE_THROUGH)
00237     {
00238         CreateOptions |= FILE_WRITE_THROUGH;
00239     }
00240 
00241     if (!(dwOpenMode & FILE_FLAG_OVERLAPPED))
00242     {
00243         CreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT;
00244     }
00245 
00246     /* Handle all open modes */
00247     if (dwOpenMode & PIPE_ACCESS_OUTBOUND)
00248     {
00249         ShareAccess |= FILE_SHARE_READ;
00250         DesiredAccess |= GENERIC_WRITE;
00251     }
00252 
00253     if (dwOpenMode & PIPE_ACCESS_INBOUND)
00254     {
00255         ShareAccess |= FILE_SHARE_WRITE;
00256         DesiredAccess |= GENERIC_READ;
00257     }
00258 
00259     /* Handle the type flags */
00260     if (dwPipeMode & PIPE_TYPE_MESSAGE)
00261     {
00262         WriteModeMessage = FILE_PIPE_MESSAGE_TYPE;
00263     }
00264     else
00265     {
00266         WriteModeMessage = FILE_PIPE_BYTE_STREAM_TYPE;
00267     }
00268 
00269     /* Handle the mode flags */
00270     if (dwPipeMode & PIPE_READMODE_MESSAGE)
00271     {
00272         ReadModeMessage = FILE_PIPE_MESSAGE_MODE;
00273     }
00274     else
00275     {
00276         ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
00277     }
00278 
00279     /* Handle the blocking mode */
00280     if (dwPipeMode & PIPE_NOWAIT)
00281     {
00282         NonBlocking = FILE_PIPE_COMPLETE_OPERATION;
00283     }
00284     else
00285     {
00286         NonBlocking = FILE_PIPE_QUEUE_OPERATION;
00287     }
00288 
00289     /* Check if we have a timeout */
00290     if (nDefaultTimeOut)
00291     {
00292         /* Convert the time to NT format */
00293         DefaultTimeOut.QuadPart = UInt32x32To64(nDefaultTimeOut, -10000);
00294     }
00295     else
00296     {
00297         /* Use default timeout of 50 ms */
00298         DefaultTimeOut.QuadPart = -500000;
00299     }
00300 
00301     /* Now create the pipe */
00302     Status = NtCreateNamedPipeFile(&PipeHandle,
00303                                    DesiredAccess,
00304                                    &ObjectAttributes,
00305                                    &Iosb,
00306                                    ShareAccess,
00307                                    FILE_OPEN_IF,
00308                                    CreateOptions,
00309                                    WriteModeMessage,
00310                                    ReadModeMessage,
00311                                    NonBlocking,
00312                                    nMaxInstances,
00313                                    nInBufferSize,
00314                                    nOutBufferSize,
00315                                    &DefaultTimeOut);
00316 
00317     /* Normalize special error codes */
00318     if ((Status == STATUS_INVALID_DEVICE_REQUEST) ||
00319         (Status == STATUS_NOT_SUPPORTED))
00320     {
00321         Status = STATUS_OBJECT_NAME_INVALID;
00322     }
00323 
00324     /* Free the name */
00325     RtlFreeHeap(RtlGetProcessHeap(),
00326                 0,
00327                 NamedPipeName.Buffer);
00328 
00329     /* Check status */
00330     if (!NT_SUCCESS(Status))
00331     {
00332         /* Failed to create it */
00333         WARN("NtCreateNamedPipe failed (Status %x)!\n", Status);
00334         BaseSetLastNTError (Status);
00335         return INVALID_HANDLE_VALUE;
00336     }
00337 
00338     /* Return the handle */
00339     return PipeHandle;
00340 }
00341 
00342 
00343 /*
00344  * @implemented
00345  */
00346 BOOL
00347 WINAPI
00348 WaitNamedPipeA(LPCSTR lpNamedPipeName,
00349                DWORD nTimeOut)
00350 {
00351     BOOL r;
00352     UNICODE_STRING NameU;
00353 
00354     /* Convert the name to Unicode */
00355     Basep8BitStringToDynamicUnicodeString(&NameU, lpNamedPipeName);
00356 
00357     /* Call the Unicode API */
00358     r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
00359 
00360     /* Free the Unicode string */
00361     RtlFreeUnicodeString(&NameU);
00362 
00363     /* Return result */
00364     return r;
00365 }
00366 
00367 
00368 /*
00369  * When NPFS will work properly, use this code instead. It is compatible with
00370  * Microsoft's NPFS.SYS. The main difference is that:
00371  *      - This code actually respects the timeout instead of ignoring it!
00372  *      - This code validates and creates the proper names for both UNC and local pipes
00373  *      - On NT, you open the *root* pipe directory (either \DosDevices\Pipe or
00374  *        \DosDevices\Unc\Server\Pipe) and then send the pipe to wait on in the
00375  *        FILE_PIPE_WAIT_FOR_BUFFER structure.
00376  */
00377 #ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
00378 /*
00379  * @implemented
00380  */
00381 BOOL
00382 WINAPI
00383 WaitNamedPipeW(LPCWSTR lpNamedPipeName,
00384                DWORD nTimeOut)
00385 {
00386     UNICODE_STRING NamedPipeName, NewName, DevicePath, PipePrefix;
00387     ULONG NameLength;
00388     ULONG i;
00389     PWCHAR p;
00390     ULONG Type;
00391     OBJECT_ATTRIBUTES ObjectAttributes;
00392     NTSTATUS Status;
00393     HANDLE FileHandle;
00394     IO_STATUS_BLOCK IoStatusBlock;
00395     ULONG WaitPipeInfoSize;
00396     PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo;
00397 
00398     /* Start by making a unicode string of the name */
00399     TRACE("Sent path: %S\n", lpNamedPipeName);
00400     RtlCreateUnicodeString(&NamedPipeName, lpNamedPipeName);
00401     NameLength = NamedPipeName.Length / sizeof(WCHAR);
00402 
00403     /* All slashes must become backslashes */
00404     for (i = 0; i < NameLength; i++)
00405     {
00406         /* Check and convert */
00407         if (NamedPipeName.Buffer[i] == L'/') NamedPipeName.Buffer[i] = L'\\';
00408     }
00409 
00410     /* Find the path type of the name we were given */
00411     NewName = NamedPipeName;
00412     Type = RtlDetermineDosPathNameType_U(lpNamedPipeName);
00413 
00414     /* Check if this was a device path, ie : "\\.\pipe\name" */
00415     if (Type == RtlPathTypeLocalDevice)
00416     {
00417         /* Make sure it's a valid prefix */
00418         RtlInitUnicodeString(&PipePrefix, L"\\\\.\\pipe\\");
00419         RtlPrefixString((PANSI_STRING)&PipePrefix, (PANSI_STRING)&NewName, TRUE);
00420 
00421         /* Move past it */
00422         NewName.Buffer += 9;
00423         NewName.Length -= 9 * sizeof(WCHAR);
00424 
00425         /* Initialize the Dos Devices name */
00426         TRACE("NewName: %wZ\n", &NewName);
00427         RtlInitUnicodeString(&DevicePath, L"\\DosDevices\\pipe\\");
00428     }
00429     else if (Type == RtlPathTypeRootLocalDevice)
00430     {
00431         /* The path is \\server\\pipe\name; find the pipename itself */
00432         p = &NewName.Buffer[2];
00433 
00434         /* First loop to get past the server name */
00435         do
00436         {
00437             /* Check if this is a backslash */
00438             if (*p == L'\\') break;
00439 
00440             /* Check next */
00441             p++;
00442         } while (*p);
00443 
00444         /* Now make sure the full name contains "pipe\" */
00445         if ((*p) && !(_wcsnicmp(p + 1, L"pipe\\", sizeof("pipe\\"))))
00446         {
00447             /* Get to the pipe name itself now */
00448             p += sizeof("pipe\\") - 1;
00449         }
00450         else
00451         {
00452             /* The name is invalid */
00453             WARN("Invalid name!\n");
00454             BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
00455             return FALSE;
00456         }
00457 
00458         /* FIXME: Open \DosDevices\Unc\Server\Pipe\Name */
00459     }
00460     else
00461     {
00462         WARN("Invalid path type\n");
00463         BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
00464         return FALSE;
00465     }
00466 
00467     /* Now calculate the total length of the structure and allocate it */
00468     WaitPipeInfoSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) +
00469                        NewName.Length;
00470     WaitPipeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize);
00471     if (WaitPipeInfo == NULL)
00472     {
00473         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00474         return FALSE;
00475     }
00476 
00477     /* Initialize the object attributes */
00478     TRACE("Opening: %wZ\n", &DevicePath);
00479     InitializeObjectAttributes(&ObjectAttributes,
00480                                &DevicePath,
00481                                OBJ_CASE_INSENSITIVE,
00482                                NULL,
00483                                NULL);
00484 
00485     /* Open the path */
00486     Status = NtOpenFile(&FileHandle,
00487                         FILE_READ_ATTRIBUTES | SYNCHRONIZE,
00488                         &ObjectAttributes,
00489                         &IoStatusBlock,
00490                         FILE_SHARE_READ | FILE_SHARE_WRITE,
00491                         FILE_SYNCHRONOUS_IO_NONALERT);
00492     if (!NT_SUCCESS(Status))
00493     {
00494         /* Fail; couldn't open */
00495         WARN("Status: %lx\n", Status);
00496         BaseSetLastNTError(Status);
00497         RtlFreeUnicodeString(&NamedPipeName);
00498         RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo);
00499         return FALSE;
00500     }
00501 
00502     /* Check what timeout we got */
00503     if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT)
00504     {
00505         /* Don't use a timeout */
00506         WaitPipeInfo->TimeoutSpecified = FALSE;
00507     }
00508     else
00509     {
00510         /* Check if we should wait forever */
00511         if (nTimeOut == NMPWAIT_WAIT_FOREVER)
00512         {
00513             /* Set the max */
00514             WaitPipeInfo->Timeout.LowPart = 0;
00515             WaitPipeInfo->Timeout.HighPart = 0x80000000;
00516         }
00517         else
00518         {
00519             /* Convert to NT format */
00520             WaitPipeInfo->Timeout.QuadPart = UInt32x32To64(-10000, nTimeOut);
00521         }
00522 
00523         /* In both cases, we do have a timeout */
00524         WaitPipeInfo->TimeoutSpecified = TRUE;
00525     }
00526 
00527     /* Set the length and copy the name */
00528     WaitPipeInfo->NameLength = NewName.Length;
00529     RtlCopyMemory(WaitPipeInfo->Name, NewName.Buffer, NewName.Length);
00530 
00531     /* Get rid of the full name */
00532     RtlFreeUnicodeString(&NamedPipeName);
00533 
00534     /* Let NPFS know of our request */
00535     Status = NtFsControlFile(FileHandle,
00536                              NULL,
00537                              NULL,
00538                              NULL,
00539                              &IoStatusBlock,
00540                              FSCTL_PIPE_WAIT,
00541                              WaitPipeInfo,
00542                              WaitPipeInfoSize,
00543                              NULL,
00544                              0);
00545 
00546     /* Free our pipe info data and close the handle */
00547     RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo);
00548     NtClose(FileHandle);
00549 
00550     /* Check the status */
00551     if (!NT_SUCCESS(Status))
00552     {
00553         /* Failure to wait on the pipe */
00554         WARN("Status: %lx\n", Status);
00555         BaseSetLastNTError (Status);
00556         return FALSE;
00557      }
00558 
00559     /* Success */
00560     return TRUE;
00561 }
00562 #else
00563 /*
00564  * @implemented
00565  */
00566 BOOL
00567 WINAPI
00568 WaitNamedPipeW(LPCWSTR lpNamedPipeName,
00569                DWORD nTimeOut)
00570 {
00571     UNICODE_STRING NamedPipeName;
00572     NTSTATUS Status;
00573     OBJECT_ATTRIBUTES ObjectAttributes;
00574     FILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
00575     HANDLE FileHandle;
00576     IO_STATUS_BLOCK Iosb;
00577 
00578     if (RtlDosPathNameToNtPathName_U(lpNamedPipeName,
00579                                      &NamedPipeName,
00580                                      NULL,
00581                                      NULL) == FALSE)
00582     {
00583         return FALSE;
00584     }
00585 
00586     InitializeObjectAttributes(&ObjectAttributes,
00587                                &NamedPipeName,
00588                                OBJ_CASE_INSENSITIVE,
00589                                NULL,
00590                                NULL);
00591     Status = NtOpenFile(&FileHandle,
00592                         FILE_READ_ATTRIBUTES | SYNCHRONIZE,
00593                         &ObjectAttributes,
00594                         &Iosb,
00595                         FILE_SHARE_READ | FILE_SHARE_WRITE,
00596                         FILE_SYNCHRONOUS_IO_NONALERT);
00597     if (!NT_SUCCESS(Status))
00598     {
00599         BaseSetLastNTError(Status);
00600         RtlFreeUnicodeString(&NamedPipeName);
00601         return FALSE;
00602     }
00603 
00604     /* Check what timeout we got */
00605     if (nTimeOut == NMPWAIT_WAIT_FOREVER)
00606     {
00607         /* Don't use a timeout */
00608         WaitPipe.TimeoutSpecified = FALSE;
00609     }
00610     else
00611     {
00612         /* Check if default */
00613         if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT)
00614         {
00615             /* Set it to 0 */
00616             WaitPipe.Timeout.LowPart = 0;
00617             WaitPipe.Timeout.HighPart = 0;
00618         }
00619         else
00620         {
00621             /* Convert to NT format */
00622             WaitPipe.Timeout.QuadPart = UInt32x32To64(-10000, nTimeOut);
00623         }
00624 
00625         /* In both cases, we do have a timeout */
00626         WaitPipe.TimeoutSpecified = TRUE;
00627     }
00628 
00629     Status = NtFsControlFile(FileHandle,
00630                              NULL,
00631                              NULL,
00632                              NULL,
00633                              &Iosb,
00634                              FSCTL_PIPE_WAIT,
00635                              &WaitPipe,
00636                              sizeof(WaitPipe),
00637                              NULL,
00638                              0);
00639     NtClose(FileHandle);
00640     if (!NT_SUCCESS(Status))
00641     {
00642         BaseSetLastNTError(Status);
00643         RtlFreeUnicodeString(&NamedPipeName);
00644         return FALSE;
00645     }
00646 
00647     RtlFreeUnicodeString(&NamedPipeName);
00648     return TRUE;
00649 }
00650 #endif
00651 
00652 
00653 /*
00654  * @implemented
00655  */
00656 BOOL
00657 WINAPI
00658 ConnectNamedPipe(IN HANDLE hNamedPipe,
00659                  IN LPOVERLAPPED lpOverlapped)
00660 {
00661     NTSTATUS Status;
00662 
00663     if (lpOverlapped != NULL)
00664     {
00665         PVOID ApcContext;
00666 
00667         lpOverlapped->Internal = STATUS_PENDING;
00668         ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
00669 
00670         Status = NtFsControlFile(hNamedPipe,
00671                                  lpOverlapped->hEvent,
00672                                  NULL,
00673                                  ApcContext,
00674                                  (PIO_STATUS_BLOCK)lpOverlapped,
00675                                  FSCTL_PIPE_LISTEN,
00676                                  NULL,
00677                                  0,
00678                                  NULL,
00679                                  0);
00680 
00681         /* return FALSE in case of failure and pending operations! */
00682         if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
00683         {
00684             BaseSetLastNTError(Status);
00685             return FALSE;
00686         }
00687     }
00688     else
00689     {
00690         IO_STATUS_BLOCK Iosb;
00691 
00692         Status = NtFsControlFile(hNamedPipe,
00693                                  NULL,
00694                                  NULL,
00695                                  NULL,
00696                                  &Iosb,
00697                                  FSCTL_PIPE_LISTEN,
00698                                  NULL,
00699                                  0,
00700                                  NULL,
00701                                  0);
00702 
00703         /* wait in case operation is pending */
00704         if (Status == STATUS_PENDING)
00705         {
00706              Status = NtWaitForSingleObject(hNamedPipe,
00707                                             FALSE,
00708                                             NULL);
00709              if (NT_SUCCESS(Status))
00710              {
00711                  Status = Iosb.Status;
00712              }
00713         }
00714 
00715         if (!NT_SUCCESS(Status))
00716         {
00717             BaseSetLastNTError(Status);
00718             return FALSE;
00719         }
00720     }
00721 
00722     return TRUE;
00723 }
00724 
00725 
00726 /*
00727  * @implemented
00728  */
00729 BOOL
00730 WINAPI
00731 SetNamedPipeHandleState(HANDLE hNamedPipe,
00732                         LPDWORD lpMode,
00733                         LPDWORD lpMaxCollectionCount,
00734                         LPDWORD lpCollectDataTimeout)
00735 {
00736     IO_STATUS_BLOCK Iosb;
00737     NTSTATUS Status;
00738 
00739     /* Check if the Mode is being changed */
00740     if (lpMode)
00741     {
00742         FILE_PIPE_INFORMATION Settings;
00743 
00744         /* Set the Completion Mode */
00745         Settings.CompletionMode = (*lpMode & PIPE_NOWAIT) ?
00746                                   FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
00747 
00748         /* Set the Read Mode */
00749         Settings.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE) ?
00750                             FILE_PIPE_MESSAGE_MODE: FILE_PIPE_BYTE_STREAM_MODE;
00751 
00752         /* Send the changes to the Driver */
00753         Status = NtSetInformationFile(hNamedPipe,
00754                                       &Iosb,
00755                                       &Settings,
00756                                       sizeof(FILE_PIPE_INFORMATION),
00757                                       FilePipeInformation);
00758         if (!NT_SUCCESS(Status))
00759         {
00760             BaseSetLastNTError(Status);
00761             return FALSE;
00762         }
00763     }
00764 
00765     /* Check if the Collection count or Timeout are being changed */
00766     if (lpMaxCollectionCount || lpCollectDataTimeout)
00767     {
00768         FILE_PIPE_REMOTE_INFORMATION RemoteSettings;
00769 
00770         /* Setting one without the other would delete it, so we read old one */
00771         if (!lpMaxCollectionCount || !lpCollectDataTimeout)
00772         {
00773             Status = NtQueryInformationFile(hNamedPipe,
00774                                             &Iosb,
00775                                             &RemoteSettings,
00776                                             sizeof(FILE_PIPE_REMOTE_INFORMATION),
00777                                             FilePipeRemoteInformation);
00778             if (!NT_SUCCESS(Status))
00779             {
00780                 BaseSetLastNTError(Status);
00781                 return FALSE;
00782             }
00783         }
00784 
00785         /* Now set the new settings */
00786         RemoteSettings.MaximumCollectionCount = (lpMaxCollectionCount) ?
00787                                                 *lpMaxCollectionCount :
00788                                                 RemoteSettings.MaximumCollectionCount;
00789         if (lpCollectDataTimeout)
00790         {
00791             /* Convert it to Quad */
00792             RemoteSettings.CollectDataTime.QuadPart =
00793                 -(LONGLONG)UInt32x32To64(10000, *lpCollectDataTimeout);
00794         }
00795 
00796         /* Tell the driver to change them */
00797         Status = NtSetInformationFile(hNamedPipe,
00798                                       &Iosb,
00799                                       &RemoteSettings,
00800                                       sizeof(FILE_PIPE_REMOTE_INFORMATION),
00801                                       FilePipeRemoteInformation);
00802         if (!NT_SUCCESS(Status))
00803         {
00804             BaseSetLastNTError(Status);
00805             return FALSE;
00806         }
00807     }
00808 
00809     return TRUE;
00810 }
00811 
00812 
00813 /*
00814  * @implemented
00815  */
00816 BOOL
00817 WINAPI
00818 CallNamedPipeA(LPCSTR lpNamedPipeName,
00819                LPVOID lpInBuffer,
00820                DWORD nInBufferSize,
00821                LPVOID lpOutBuffer,
00822                DWORD nOutBufferSize,
00823                LPDWORD lpBytesRead,
00824                DWORD nTimeOut)
00825 {
00826     PUNICODE_STRING PipeName = &NtCurrentTeb()->StaticUnicodeString;
00827     ANSI_STRING AnsiPipe;
00828 
00829     /* Initialize the string as ANSI_STRING and convert to Unicode */
00830     RtlInitAnsiString(&AnsiPipe, (LPSTR)lpNamedPipeName);
00831     RtlAnsiStringToUnicodeString(PipeName, &AnsiPipe, FALSE);
00832 
00833     /* Call the Unicode function */
00834     return CallNamedPipeW(PipeName->Buffer,
00835                           lpInBuffer,
00836                           nInBufferSize,
00837                           lpOutBuffer,
00838                           nOutBufferSize,
00839                           lpBytesRead,
00840                           nTimeOut);
00841 }
00842 
00843 
00844 /*
00845  * @implemented
00846  */
00847 BOOL
00848 WINAPI
00849 CallNamedPipeW(LPCWSTR lpNamedPipeName,
00850                LPVOID lpInBuffer,
00851                DWORD nInBufferSize,
00852                LPVOID lpOutBuffer,
00853                DWORD nOutBufferSize,
00854                LPDWORD lpBytesRead,
00855                DWORD nTimeOut)
00856 {
00857     HANDLE hPipe;
00858     BOOL bRetry = TRUE;
00859     BOOL bError;
00860     DWORD dwPipeMode;
00861 
00862     while (TRUE)
00863     {
00864         /* Try creating it */
00865         hPipe = CreateFileW(lpNamedPipeName,
00866                             GENERIC_READ | GENERIC_WRITE,
00867                             FILE_SHARE_READ | FILE_SHARE_WRITE,
00868                             NULL,
00869                             OPEN_EXISTING,
00870                             FILE_ATTRIBUTE_NORMAL,
00871                             NULL);
00872 
00873         /* Success, break out */
00874         if (hPipe != INVALID_HANDLE_VALUE)
00875             break;
00876 
00877         /* Already tried twice, give up */
00878         if (bRetry == FALSE)
00879             return FALSE;
00880 
00881         /* Wait on it */
00882         WaitNamedPipeW(lpNamedPipeName, nTimeOut);
00883 
00884         /* Get ready to try again */
00885         bRetry = FALSE;
00886     }
00887 
00888     /* Set the pipe mode */
00889     dwPipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
00890     bError = SetNamedPipeHandleState(hPipe, &dwPipeMode, NULL, NULL);
00891     if (!bError)
00892     {
00893         /* Couldn't change state, fail */
00894         CloseHandle(hPipe);
00895         return FALSE;
00896     }
00897 
00898     /* Do the transact */
00899     bError = TransactNamedPipe(hPipe,
00900                                lpInBuffer,
00901                                nInBufferSize,
00902                                lpOutBuffer,
00903                                nOutBufferSize,
00904                                lpBytesRead,
00905                                NULL);
00906 
00907     /* Close the handle */
00908     CloseHandle(hPipe);
00909 
00910     return bError;
00911 }
00912 
00913 
00914 /*
00915  * @implemented
00916  */
00917 BOOL
00918 WINAPI
00919 DisconnectNamedPipe(HANDLE hNamedPipe)
00920 {
00921     IO_STATUS_BLOCK Iosb;
00922     NTSTATUS Status;
00923 
00924     /* Send the FSCTL to the driver */
00925     Status = NtFsControlFile(hNamedPipe,
00926                              NULL,
00927                              NULL,
00928                              NULL,
00929                              &Iosb,
00930                              FSCTL_PIPE_DISCONNECT,
00931                              NULL,
00932                              0,
00933                              NULL,
00934                              0);
00935     if (Status == STATUS_PENDING)
00936     {
00937         /* Wait on NPFS to finish and get updated status */
00938         Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
00939         if (NT_SUCCESS(Status))
00940             Status = Iosb.Status;
00941     }
00942 
00943     /* Check for error */
00944     if (!NT_SUCCESS(Status))
00945     {
00946         /* Fail */
00947         BaseSetLastNTError(Status);
00948         return FALSE;
00949     }
00950 
00951     return TRUE;
00952 }
00953 
00954 
00955 /*
00956  * @unimplemented
00957  */
00958 BOOL
00959 WINAPI
00960 GetNamedPipeHandleStateW(HANDLE hNamedPipe,
00961                          LPDWORD lpState,
00962                          LPDWORD lpCurInstances,
00963                          LPDWORD lpMaxCollectionCount,
00964                          LPDWORD lpCollectDataTimeout,
00965                          LPWSTR lpUserName,
00966                          DWORD nMaxUserNameSize)
00967 {
00968     IO_STATUS_BLOCK StatusBlock;
00969     NTSTATUS Status;
00970 
00971     if (lpState != NULL)
00972     {
00973         FILE_PIPE_INFORMATION PipeInfo;
00974 
00975         Status = NtQueryInformationFile(hNamedPipe,
00976                                         &StatusBlock,
00977                                         &PipeInfo,
00978                                         sizeof(FILE_PIPE_INFORMATION),
00979                                         FilePipeInformation);
00980         if (!NT_SUCCESS(Status))
00981         {
00982             BaseSetLastNTError(Status);
00983             return FALSE;
00984         }
00985 
00986         *lpState = ((PipeInfo.CompletionMode != FILE_PIPE_QUEUE_OPERATION) ? PIPE_NOWAIT : PIPE_WAIT);
00987         *lpState |= ((PipeInfo.ReadMode != FILE_PIPE_BYTE_STREAM_MODE) ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
00988     }
00989 
00990     if(lpCurInstances != NULL)
00991     {
00992         FILE_PIPE_LOCAL_INFORMATION LocalInfo;
00993 
00994         Status = NtQueryInformationFile(hNamedPipe,
00995                                         &StatusBlock,
00996                                         &LocalInfo,
00997                                         sizeof(FILE_PIPE_LOCAL_INFORMATION),
00998                                         FilePipeLocalInformation);
00999         if (!NT_SUCCESS(Status))
01000         {
01001             BaseSetLastNTError(Status);
01002             return FALSE;
01003         }
01004 
01005         *lpCurInstances = min(LocalInfo.CurrentInstances, PIPE_UNLIMITED_INSTANCES);
01006     }
01007 
01008     if (lpMaxCollectionCount != NULL || lpCollectDataTimeout != NULL)
01009     {
01010         FILE_PIPE_REMOTE_INFORMATION RemoteInfo;
01011 
01012         Status = NtQueryInformationFile(hNamedPipe,
01013                                         &StatusBlock,
01014                                         &RemoteInfo,
01015                                         sizeof(FILE_PIPE_REMOTE_INFORMATION),
01016                                         FilePipeRemoteInformation);
01017         if (!NT_SUCCESS(Status))
01018         {
01019             BaseSetLastNTError(Status);
01020             return FALSE;
01021         }
01022 
01023         if (lpMaxCollectionCount != NULL)
01024         {
01025             *lpMaxCollectionCount = RemoteInfo.MaximumCollectionCount;
01026         }
01027 
01028         if(lpCollectDataTimeout != NULL)
01029         {
01030             /* FIXME */
01031            *lpCollectDataTimeout = 0;
01032         }
01033     }
01034 
01035     if (lpUserName != NULL)
01036     {
01037       /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
01038                  retreive the user name with GetUserName(), revert the impersonation
01039                  and finally restore the thread token */
01040     }
01041 
01042     return TRUE;
01043 }
01044 
01045 
01046 /*
01047  * @implemented
01048  */
01049 BOOL
01050 WINAPI
01051 GetNamedPipeHandleStateA(HANDLE hNamedPipe,
01052                          LPDWORD lpState,
01053                          LPDWORD lpCurInstances,
01054                          LPDWORD lpMaxCollectionCount,
01055                          LPDWORD lpCollectDataTimeout,
01056                          LPSTR lpUserName,
01057                          DWORD nMaxUserNameSize)
01058 {
01059     UNICODE_STRING UserNameW = { 0, 0, NULL };
01060     ANSI_STRING UserNameA;
01061     BOOL Ret;
01062 
01063     if(lpUserName != NULL)
01064     {
01065         UserNameW.MaximumLength = (USHORT)nMaxUserNameSize * sizeof(WCHAR);
01066         UserNameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW.MaximumLength);
01067         if (UserNameW.Buffer == NULL)
01068         {
01069             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01070             return FALSE;
01071         }
01072 
01073         UserNameA.Buffer = lpUserName;
01074         UserNameA.Length = 0;
01075         UserNameA.MaximumLength = (USHORT)nMaxUserNameSize;
01076     }
01077 
01078     Ret = GetNamedPipeHandleStateW(hNamedPipe,
01079                                    lpState,
01080                                    lpCurInstances,
01081                                    lpMaxCollectionCount,
01082                                    lpCollectDataTimeout,
01083                                    UserNameW.Buffer,
01084                                    nMaxUserNameSize);
01085     if (Ret && lpUserName != NULL)
01086     {
01087         NTSTATUS Status;
01088 
01089         RtlInitUnicodeString(&UserNameW, UserNameW.Buffer);
01090         Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
01091         if (!NT_SUCCESS(Status))
01092         {
01093             BaseSetLastNTError(Status);
01094             Ret = FALSE;
01095         }
01096     }
01097 
01098     if (UserNameW.Buffer != NULL)
01099     {
01100         RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW.Buffer);
01101     }
01102 
01103     return Ret;
01104 }
01105 
01106 
01107 /*
01108  * @implemented
01109  */
01110 BOOL
01111 WINAPI
01112 GetNamedPipeInfo(HANDLE hNamedPipe,
01113                  LPDWORD lpFlags,
01114                  LPDWORD lpOutBufferSize,
01115                  LPDWORD lpInBufferSize,
01116                  LPDWORD lpMaxInstances)
01117 {
01118     FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation;
01119     IO_STATUS_BLOCK StatusBlock;
01120     NTSTATUS Status;
01121 
01122     Status = NtQueryInformationFile(hNamedPipe,
01123                                     &StatusBlock,
01124                                     &PipeLocalInformation,
01125                                     sizeof(FILE_PIPE_LOCAL_INFORMATION),
01126                                     FilePipeLocalInformation);
01127     if (!NT_SUCCESS(Status))
01128     {
01129         BaseSetLastNTError(Status);
01130         return FALSE;
01131     }
01132 
01133     if (lpFlags != NULL)
01134     {
01135         *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
01136         *lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
01137     }
01138 
01139     if (lpOutBufferSize != NULL)
01140         *lpOutBufferSize = PipeLocalInformation.OutboundQuota;
01141 
01142     if (lpInBufferSize != NULL)
01143         *lpInBufferSize = PipeLocalInformation.InboundQuota;
01144 
01145     if (lpMaxInstances != NULL)
01146     {
01147         if (PipeLocalInformation.MaximumInstances >= 255)
01148             *lpMaxInstances = PIPE_UNLIMITED_INSTANCES;
01149         else
01150             *lpMaxInstances = PipeLocalInformation.MaximumInstances;
01151     }
01152 
01153     return TRUE;
01154 }
01155 
01156 
01157 /*
01158  * @implemented
01159  */
01160 BOOL
01161 WINAPI
01162 PeekNamedPipe(HANDLE hNamedPipe,
01163               LPVOID lpBuffer,
01164               DWORD nBufferSize,
01165               LPDWORD lpBytesRead,
01166               LPDWORD lpTotalBytesAvail,
01167               LPDWORD lpBytesLeftThisMessage)
01168 {
01169     PFILE_PIPE_PEEK_BUFFER Buffer;
01170     IO_STATUS_BLOCK Iosb;
01171     ULONG BufferSize;
01172     ULONG BytesRead;
01173     NTSTATUS Status;
01174 
01175     /* Calculate the buffer space that we'll need and allocate it */
01176     BufferSize = nBufferSize + sizeof(FILE_PIPE_PEEK_BUFFER);
01177     Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
01178     if (Buffer == NULL)
01179     {
01180         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01181         return FALSE;
01182     }
01183 
01184     /* Tell the driver to seek */
01185     Status = NtFsControlFile(hNamedPipe,
01186                              NULL,
01187                              NULL,
01188                              NULL,
01189                              &Iosb,
01190                              FSCTL_PIPE_PEEK,
01191                              NULL,
01192                              0,
01193                              Buffer,
01194                              BufferSize);
01195     if (Status == STATUS_PENDING)
01196     {
01197         /* Wait for npfs to be done, and update the status */
01198         Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
01199         if (NT_SUCCESS(Status))
01200             Status = Iosb.Status;
01201     }
01202 
01203     /* Overflow is success for us */
01204     if (Status == STATUS_BUFFER_OVERFLOW)
01205         Status = STATUS_SUCCESS;
01206 
01207     /* If we failed */
01208     if (!NT_SUCCESS(Status))
01209     {
01210         /* Free the buffer and return failure */
01211         RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
01212         BaseSetLastNTError(Status);
01213         return FALSE;
01214     }
01215 
01216     /* Check if caller requested bytes available */
01217     if (lpTotalBytesAvail)
01218         *lpTotalBytesAvail = Buffer->ReadDataAvailable;
01219 
01220     /* Calculate the bytes returned, minus our structure overhead */
01221     BytesRead = (ULONG)(Iosb.Information -
01222                         FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
01223 
01224     /* Check if caller requested bytes read */
01225     if (lpBytesRead)
01226     {
01227         /* Return the bytes read */
01228         *lpBytesRead = BytesRead;
01229     }
01230 
01231     /* Check if caller requested bytes left */
01232     if (lpBytesLeftThisMessage)
01233     {
01234         /* Calculate total minus what we returned and our structure overhead */
01235         *lpBytesLeftThisMessage = Buffer->MessageLength - BytesRead;
01236     }
01237 
01238     /* Check if the caller wanted to see the actual data */
01239     if (lpBuffer)
01240     {
01241         /* Give him what he wants */
01242         RtlCopyMemory(lpBuffer,
01243                       Buffer->Data,
01244                       BytesRead);
01245     }
01246 
01247     /* Free the buffer */
01248     RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
01249 
01250     return TRUE;
01251 }
01252 
01253 
01254 /*
01255  * @implemented
01256  */
01257 BOOL
01258 WINAPI
01259 TransactNamedPipe(IN HANDLE hNamedPipe,
01260                   IN LPVOID lpInBuffer,
01261                   IN DWORD nInBufferSize,
01262                   OUT LPVOID lpOutBuffer,
01263                   IN DWORD nOutBufferSize,
01264                   OUT LPDWORD lpBytesRead  OPTIONAL,
01265                   IN LPOVERLAPPED lpOverlapped  OPTIONAL)
01266 {
01267     NTSTATUS Status;
01268 
01269     if (lpBytesRead != NULL)
01270     {
01271         *lpBytesRead = 0;
01272     }
01273 
01274     if (lpOverlapped != NULL)
01275     {
01276         PVOID ApcContext;
01277 
01278         ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
01279         lpOverlapped->Internal = STATUS_PENDING;
01280 
01281         Status = NtFsControlFile(hNamedPipe,
01282                                  lpOverlapped->hEvent,
01283                                  NULL,
01284                                  ApcContext,
01285                                  (PIO_STATUS_BLOCK)lpOverlapped,
01286                                  FSCTL_PIPE_TRANSCEIVE,
01287                                  lpInBuffer,
01288                                  nInBufferSize,
01289                                  lpOutBuffer,
01290                                  nOutBufferSize);
01291         if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
01292         {
01293             BaseSetLastNTError(Status);
01294             return FALSE;
01295         }
01296 
01297         if (lpBytesRead != NULL)
01298         {
01299             *lpBytesRead = lpOverlapped->InternalHigh;
01300         }
01301     }
01302     else
01303     {
01304 #if 0 /* We don't implement FSCTL_PIPE_TRANSCEIVE yet */
01305         IO_STATUS_BLOCK Iosb;
01306 
01307         Status = NtFsControlFile(hNamedPipe,
01308                                  NULL,
01309                                  NULL,
01310                                  NULL,
01311                                  &Iosb,
01312                                  FSCTL_PIPE_TRANSCEIVE,
01313                                  lpInBuffer,
01314                                  nInBufferSize,
01315                                  lpOutBuffer,
01316                                  nOutBufferSize);
01317         if (Status == STATUS_PENDING)
01318         {
01319             Status = NtWaitForSingleObject(hNamedPipe,
01320                                            FALSE,
01321                                            NULL);
01322             if (NT_SUCCESS(Status))
01323                 Status = Iosb.Status;
01324         }
01325 
01326         if (NT_SUCCESS(Status))
01327         {
01328             /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
01329                check that case either and crashes (only after the operation
01330                completed) */
01331             *lpBytesRead = Iosb.Information;
01332         }
01333         else
01334         {
01335             BaseSetLastNTError(Status);
01336             return FALSE;
01337         }
01338 #else /* Workaround while FSCTL_PIPE_TRANSCEIVE not available */
01339         DWORD nActualBytes;
01340 
01341         while (0 != nInBufferSize &&
01342                WriteFile(hNamedPipe, lpInBuffer, nInBufferSize, &nActualBytes,
01343                          NULL))
01344         {
01345              lpInBuffer = (LPVOID)((char *) lpInBuffer + nActualBytes);
01346              nInBufferSize -= nActualBytes;
01347         }
01348 
01349         if (0 != nInBufferSize)
01350         {
01351              /* Must have dropped out of the while 'cause WriteFile failed */
01352              return FALSE;
01353         }
01354 
01355         if (!ReadFile(hNamedPipe, lpOutBuffer, nOutBufferSize, &nActualBytes,
01356                       NULL))
01357         {
01358              return FALSE;
01359         }
01360 
01361         if (NULL != lpBytesRead)
01362         {
01363             *lpBytesRead = nActualBytes;
01364         }
01365 #endif
01366     }
01367 
01368     return TRUE;
01369 }
01370 
01371 /* EOF */

Generated on Mon May 28 2012 04:24:05 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.