- 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)

svn path=/trunk/; revision=15051
This commit is contained in:
Thomas Bluemel 2005-05-06 16:47:09 +00:00
parent bb1d3b119b
commit b62466eed1

View file

@ -892,64 +892,93 @@ PeekNamedPipe(HANDLE hNamedPipe,
* @implemented * @implemented
*/ */
BOOL STDCALL BOOL STDCALL
TransactNamedPipe(HANDLE hNamedPipe, TransactNamedPipe(IN HANDLE hNamedPipe,
LPVOID lpInBuffer, IN LPVOID lpInBuffer,
DWORD nInBufferSize, IN DWORD nInBufferSize,
LPVOID lpOutBuffer, OUT LPVOID lpOutBuffer,
DWORD nOutBufferSize, IN DWORD nOutBufferSize,
LPDWORD lpBytesRead, OUT LPDWORD lpBytesRead OPTIONAL,
LPOVERLAPPED lpOverlapped) IN LPOVERLAPPED lpOverlapped OPTIONAL)
{ {
IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status;
NTSTATUS Status;
if (lpOverlapped == NULL) if (lpBytesRead != NULL)
{ {
Status = NtFsControlFile(hNamedPipe, *lpBytesRead = 0;
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;
Status = NtFsControlFile(hNamedPipe, if (lpOverlapped != NULL)
lpOverlapped->hEvent, {
NULL, PVOID ApcContext;
NULL,
(PIO_STATUS_BLOCK)lpOverlapped,
FSCTL_PIPE_TRANSCEIVE,
lpInBuffer,
nInBufferSize,
lpOutBuffer,
nOutBufferSize);
}
if (!NT_SUCCESS(Status)) ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
{ lpOverlapped->Internal = STATUS_PENDING;
SetLastErrorByStatus(Status);
return(FALSE);
}
return(TRUE); Status = NtFsControlFile(hNamedPipe,
lpOverlapped->hEvent,
NULL,
ApcContext,
(PIO_STATUS_BLOCK)lpOverlapped,
FSCTL_PIPE_TRANSCEIVE,
lpInBuffer,
nInBufferSize,
lpOutBuffer,
nOutBufferSize);
/* 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 */ /* EOF */