- fixed TransactNamedPipe to properly wait on completion for synchronous
operations
- prevent completion port notification by not passing an APC context to
the kernel when the low-order bit of the event handle is set (for
asynchronous operations)
Modified: trunk/reactos/lib/kernel32/file/npipe.c
_____
Modified: trunk/reactos/lib/kernel32/file/npipe.c
--- trunk/reactos/lib/kernel32/file/npipe.c 2005-05-06 16:23:24 UTC
(rev 15050)
+++ trunk/reactos/lib/kernel32/file/npipe.c 2005-05-06 16:47:09 UTC
(rev 15051)
@@ -892,64 +892,93 @@
* @implemented
*/
BOOL STDCALL
-TransactNamedPipe(HANDLE hNamedPipe,
- LPVOID lpInBuffer,
- DWORD nInBufferSize,
- LPVOID lpOutBuffer,
- DWORD nOutBufferSize,
- LPDWORD lpBytesRead,
- LPOVERLAPPED lpOverlapped)
+TransactNamedPipe(IN HANDLE hNamedPipe,
+ IN LPVOID lpInBuffer,
+ IN DWORD nInBufferSize,
+ OUT LPVOID lpOutBuffer,
+ IN DWORD nOutBufferSize,
+ OUT LPDWORD lpBytesRead OPTIONAL,
+ IN LPOVERLAPPED lpOverlapped OPTIONAL)
{
- IO_STATUS_BLOCK IoStatusBlock;
- NTSTATUS Status;
+ NTSTATUS Status;
+
+ if (lpBytesRead != NULL)
+ {
+ *lpBytesRead = 0;
+ }
- if (lpOverlapped == NULL)
- {
- Status = NtFsControlFile(hNamedPipe,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- FSCTL_PIPE_TRANSCEIVE,
- lpInBuffer,
- nInBufferSize,
- lpOutBuffer,
- nOutBufferSize);
- if (Status == STATUS_PENDING)
- {
- NtWaitForSingleObject(hNamedPipe,
- 0,
- FALSE);
- Status = IoStatusBlock.Status;
- }
- if (NT_SUCCESS(Status))
- {
- *lpBytesRead = IoStatusBlock.Information;
- }
- }
- else
- {
- lpOverlapped->Internal = STATUS_PENDING;
+ if (lpOverlapped != NULL)
+ {
+ PVOID ApcContext;
- Status = NtFsControlFile(hNamedPipe,
- lpOverlapped->hEvent,
- NULL,
- NULL,
- (PIO_STATUS_BLOCK)lpOverlapped,
- FSCTL_PIPE_TRANSCEIVE,
- lpInBuffer,
- nInBufferSize,
- lpOutBuffer,
- nOutBufferSize);
- }
+ ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL :
lpOverlapped);
+ lpOverlapped->Internal = STATUS_PENDING;
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return(FALSE);
- }
+ Status = NtFsControlFile(hNamedPipe,
+ lpOverlapped->hEvent,
+ NULL,
+ ApcContext,
+ (PIO_STATUS_BLOCK)lpOverlapped,
+ FSCTL_PIPE_TRANSCEIVE,
+ lpInBuffer,
+ nInBufferSize,
+ lpOutBuffer,
+ nOutBufferSize);
- return(TRUE);
+ /* return FALSE in case of failure and pending operations! */
+ if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
+ {
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+
+ if (lpBytesRead != NULL)
+ {
+ *lpBytesRead = lpOverlapped->InternalHigh;
+ }
+ }
+ else
+ {
+ IO_STATUS_BLOCK Iosb;
+
+ Status = NtFsControlFile(hNamedPipe,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ FSCTL_PIPE_TRANSCEIVE,
+ lpInBuffer,
+ nInBufferSize,
+ lpOutBuffer,
+ nOutBufferSize);
+
+ /* wait in case operation is pending */
+ if (Status == STATUS_PENDING)
+ {
+ Status = NtWaitForSingleObject(hNamedPipe,
+ FALSE,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ Status = Iosb.Status;
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ /* lpNumberOfBytesRead must not be NULL here, in fact Win
doesn't
+ check that case either and crashes (only after the
operation
+ completed) */
+ *lpBytesRead = Iosb.Information;
+ }
+ else
+ {
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
}
/* EOF */