- 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
*/
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 (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 (lpBytesRead != NULL)
{
*lpBytesRead = 0;
}
Status = NtFsControlFile(hNamedPipe,
lpOverlapped->hEvent,
NULL,
NULL,
(PIO_STATUS_BLOCK)lpOverlapped,
FSCTL_PIPE_TRANSCEIVE,
lpInBuffer,
nInBufferSize,
lpOutBuffer,
nOutBufferSize);
}
if (lpOverlapped != NULL)
{
PVOID ApcContext;
if (!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return(FALSE);
}
ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
lpOverlapped->Internal = STATUS_PENDING;
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 */