HANDLE NamedPipeHandle;
UNICODE_STRING NameU;
ANSI_STRING NameA;
-
+
RtlInitAnsiString(&NameA, (LPSTR)lpName);
RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
-
+
NamedPipeHandle = CreateNamedPipeW(NameU.Buffer,
dwOpenMode,
dwPipeMode,
nInBufferSize,
nDefaultTimeOut,
lpSecurityAttributes);
-
+
RtlFreeUnicodeString(&NameU);
-
+
return(NamedPipeHandle);
}
HANDLE PipeHandle;
ACCESS_MASK DesiredAccess;
ULONG CreateOptions;
- ULONG CreateDisposition;
ULONG WriteModeMessage;
ULONG ReadModeMessage;
ULONG NonBlocking;
LARGE_INTEGER DefaultTimeOut;
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
+ if (nMaxInstances == 0 || nMaxInstances > PIPE_UNLIMITED_INSTANCES)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+
Result = RtlDosPathNameToNtPathName_U((LPWSTR)lpName,
&NamedPipeName,
NULL,
NULL,
SecurityDescriptor);
- DesiredAccess = 0;
+ DesiredAccess = SYNCHRONIZE | (dwOpenMode & (WRITE_DAC | WRITE_OWNER | ACCESS_SYSTEM_SECURITY));
ShareAccess = 0;
- CreateDisposition = FILE_OPEN_IF;
CreateOptions = 0;
+
if (dwOpenMode & FILE_FLAG_WRITE_THROUGH)
- {
- CreateOptions = CreateOptions | FILE_WRITE_THROUGH;
- }
+ CreateOptions = CreateOptions | FILE_WRITE_THROUGH;
+
if (!(dwOpenMode & FILE_FLAG_OVERLAPPED))
- {
- CreateOptions = CreateOptions | FILE_SYNCHRONOUS_IO_NONALERT;
- }
- if (dwOpenMode & PIPE_ACCESS_DUPLEX)
- {
- CreateOptions = CreateOptions | FILE_PIPE_FULL_DUPLEX;
- DesiredAccess |= (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
- }
- else if (dwOpenMode & PIPE_ACCESS_INBOUND)
- {
- CreateOptions = CreateOptions | FILE_PIPE_INBOUND;
- DesiredAccess |= FILE_GENERIC_READ;
- }
- else if (dwOpenMode & PIPE_ACCESS_OUTBOUND)
- {
- CreateOptions = CreateOptions | FILE_PIPE_OUTBOUND;
- DesiredAccess |= FILE_GENERIC_WRITE;
- }
+ CreateOptions = CreateOptions | FILE_SYNCHRONOUS_IO_NONALERT;
- if (dwPipeMode & PIPE_TYPE_BYTE)
+ if (dwOpenMode & PIPE_ACCESS_OUTBOUND)
{
- WriteModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
+ ShareAccess |= FILE_SHARE_READ;
+ DesiredAccess |= GENERIC_WRITE;
}
- else if (dwPipeMode & PIPE_TYPE_MESSAGE)
+ if (dwOpenMode & PIPE_ACCESS_INBOUND)
{
- WriteModeMessage = FILE_PIPE_MESSAGE_MODE;
+ ShareAccess |= FILE_SHARE_WRITE;
+ DesiredAccess |= GENERIC_READ;
}
+ if (dwPipeMode & PIPE_TYPE_MESSAGE)
+ WriteModeMessage = FILE_PIPE_MESSAGE_MODE;
else
- {
- WriteModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
- }
+ WriteModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
- if (dwPipeMode & PIPE_READMODE_BYTE)
- {
- ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
- }
- else if (dwPipeMode & PIPE_READMODE_MESSAGE)
- {
- ReadModeMessage = FILE_PIPE_MESSAGE_MODE;
- }
+ if (dwPipeMode & PIPE_READMODE_MESSAGE)
+ ReadModeMessage = FILE_PIPE_MESSAGE_MODE;
else
- {
- ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
- }
+ ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
- if (dwPipeMode & PIPE_WAIT)
- {
- NonBlocking = FILE_PIPE_QUEUE_OPERATION;
- }
- else if (dwPipeMode & PIPE_NOWAIT)
- {
- NonBlocking = FILE_PIPE_COMPLETE_OPERATION;
- }
+ if (dwPipeMode & PIPE_NOWAIT)
+ NonBlocking = FILE_PIPE_COMPLETE_OPERATION;
else
- {
- NonBlocking = FILE_PIPE_QUEUE_OPERATION;
- }
+ NonBlocking = FILE_PIPE_QUEUE_OPERATION;
- if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES)
- {
- nMaxInstances = ULONG_MAX;
- }
-
- DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000;
+ DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000LL;
Status = NtCreateNamedPipeFile(&PipeHandle,
DesiredAccess,
&ObjectAttributes,
&Iosb,
ShareAccess,
- CreateDisposition,
+ FILE_OPEN_IF,
CreateOptions,
WriteModeMessage,
ReadModeMessage,
BOOL r;
UNICODE_STRING NameU;
ANSI_STRING NameA;
-
+
RtlInitAnsiString(&NameA, (LPSTR)lpNamedPipeName);
RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
-
+
r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
-
+
RtlFreeUnicodeString(&NameU);
-
+
return(r);
}
+/*
+ * When NPFS will work properly, use this code instead. It is compatible with
+ * Microsoft's NPFS.SYS. The main difference is that:
+ * - This code actually respects the timeout instead of ignoring it!
+ * - This code validates and creates the proper names for both UNC and local pipes
+ * - On NT, you open the *root* pipe directory (either \DosDevices\Pipe or
+ * \DosDevices\Unc\Server\Pipe) and then send the pipe to wait on in the
+ * FILE_PIPE_WAIT_FOR_BUFFER structure.
+ */
+#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+WaitNamedPipeW(LPCWSTR lpNamedPipeName,
+ DWORD nTimeOut)
+{
+ UNICODE_STRING NamedPipeName, NewName, DevicePath, PipePrefix;
+ ULONG NameLength;
+ ULONG i;
+ PWCHAR p;
+ ULONG Type;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ HANDLE FileHandle;
+ IO_STATUS_BLOCK IoStatusBlock;
+ ULONG WaitPipeInfoSize;
+ PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo;
+
+ /* Start by making a unicode string of the name */
+ DPRINT("Sent path: %S\n", lpNamedPipeName);
+ RtlCreateUnicodeString(&NamedPipeName, lpNamedPipeName);
+ NameLength = NamedPipeName.Length / sizeof(WCHAR);
+
+ /* All slashes must become backslashes */
+ for (i = 0; i < NameLength; i++)
+ {
+ /* Check and convert */
+ if (NamedPipeName.Buffer[i] == L'/') NamedPipeName.Buffer[i] = L'\\';
+ }
+
+ /* Find the path type of the name we were given */
+ NewName = NamedPipeName;
+ Type = RtlDetermineDosPathNameType_U(lpNamedPipeName);
+
+ /* Check if this was a device path, ie : "\\.\pipe\name" */
+ if (Type == DEVICE_PATH)
+ {
+ /* Make sure it's a valid prefix */
+ RtlInitUnicodeString(&PipePrefix, L"\\\\.\\pipe\\");
+ RtlPrefixString((PANSI_STRING)&PipePrefix, (PANSI_STRING)&NewName, TRUE);
+
+ /* Move past it */
+ NewName.Buffer += 9;
+ NewName.Length -= 9 * sizeof(WCHAR);
+
+ /* Initialize the Dos Devices name */
+ DPRINT("NewName: %wZ\n", &NewName);
+ RtlInitUnicodeString(&DevicePath, L"\\DosDevices\\pipe\\");
+ }
+ else if (Type == UNC_PATH)
+ {
+ /* The path is \\server\\pipe\name; find the pipename itself */
+ p = &NewName.Buffer[2];
+
+ /* First loop to get past the server name */
+ do
+ {
+ /* Check if this is a backslash */
+ if (*p == L'\\') break;
+
+ /* Check next */
+ p++;
+ } while (*p);
+
+ /* Now make sure the full name contains "pipe\" */
+ if ((*p) && !(_wcsnicmp(p + 1, L"pipe\\", sizeof("pipe\\"))))
+ {
+ /* Get to the pipe name itself now */
+ p += sizeof("pipe\\") - 1;
+ }
+ else
+ {
+ /* The name is invalid */
+ DPRINT1("Invalid name!\n");
+ SetLastErrorByStatus(STATUS_OBJECT_PATH_SYNTAX_BAD);
+ return FALSE;
+ }
+
+ /* FIXME: Open \DosDevices\Unc\Server\Pipe\Name */
+ }
+ else
+ {
+ DPRINT1("Invalid path type\n");
+ SetLastErrorByStatus(STATUS_OBJECT_PATH_SYNTAX_BAD);
+ return FALSE;
+ }
+ /* Initialize the object attributes */
+ DPRINT("Opening: %wZ\n", &DevicePath);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &DevicePath,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ /* Open the path */
+ Status = NtOpenFile(&FileHandle,
+ FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail; couldn't open */
+ DPRINT1("Status: %lx\n", Status);
+ SetLastErrorByStatus(Status);
+ RtlFreeUnicodeString(&NamedPipeName);
+ return(FALSE);
+ }
+
+ /* Now calculate the total length of the structure and allocate it */
+ WaitPipeInfoSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) +
+ NewName.Length;
+ WaitPipeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize);
+
+ /* Check what timeout we got */
+ if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT)
+ {
+ /* Don't use a timeout */
+ WaitPipeInfo->TimeoutSpecified = FALSE;
+ }
+ else
+ {
+ /* Check if we should wait forever */
+ if (nTimeOut == NMPWAIT_WAIT_FOREVER)
+ {
+ /* Set the max */
+ WaitPipeInfo->Timeout.LowPart = 0;
+ WaitPipeInfo->Timeout.HighPart = 0x80000000;
+ }
+ else
+ {
+ /* Convert to NT format */
+ WaitPipeInfo->Timeout.QuadPart = UInt32x32To64(-10000, nTimeOut);
+ }
+
+ /* In both cases, we do have a timeout */
+ WaitPipeInfo->TimeoutSpecified = FALSE;
+ }
+
+ /* Set the length and copy the name */
+ WaitPipeInfo->NameLength = NewName.Length;
+ RtlCopyMemory(WaitPipeInfo->Name, NewName.Buffer, NewName.Length);
+
+ /* Get rid of the full name */
+ RtlFreeUnicodeString(&NamedPipeName);
+
+ /* Let NPFS know of our request */
+ Status = NtFsControlFile(FileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ FSCTL_PIPE_WAIT,
+ WaitPipeInfo,
+ WaitPipeInfoSize,
+ NULL,
+ 0);
+
+ /* Free our pipe info data and close the handle */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo);
+ NtClose(FileHandle);
+
+ /* Check the status */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failure to wait on the pipe */
+ DPRINT1("Status: %lx\n", Status);
+ SetLastErrorByStatus (Status);
+ return FALSE;
+ }
+
+ /* Success */
+ return TRUE;
+}
+#else
/*
* @implemented
*/
BOOL r;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
- NPFS_WAIT_PIPE WaitPipe;
+ FILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
HANDLE FileHandle;
IO_STATUS_BLOCK Iosb;
-
+
r = RtlDosPathNameToNtPathName_U((LPWSTR)lpNamedPipeName,
&NamedPipeName,
NULL,
{
return(FALSE);
}
-
+
InitializeObjectAttributes(&ObjectAttributes,
&NamedPipeName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(&FileHandle,
- FILE_GENERIC_READ,
+ FILE_READ_ATTRIBUTES | SYNCHRONIZE,
&ObjectAttributes,
&Iosb,
FILE_SHARE_READ | FILE_SHARE_WRITE,
SetLastErrorByStatus (Status);
return(FALSE);
}
-
- WaitPipe.Timeout.QuadPart = nTimeOut * -10000;
-
+
+ WaitPipe.Timeout.QuadPart = nTimeOut * -10000LL;
+
Status = NtFsControlFile(FileHandle,
NULL,
NULL,
SetLastErrorByStatus (Status);
return(FALSE);
}
-
+
return(TRUE);
}
-
+#endif
/*
* @implemented
*/
BOOL STDCALL
-ConnectNamedPipe(HANDLE hNamedPipe,
- LPOVERLAPPED lpOverlapped)
+ConnectNamedPipe(IN HANDLE hNamedPipe,
+ IN LPOVERLAPPED lpOverlapped)
{
- PIO_STATUS_BLOCK IoStatusBlock;
- IO_STATUS_BLOCK Iosb;
- HANDLE hEvent;
- NTSTATUS Status;
-
- if (lpOverlapped != NULL)
- {
- lpOverlapped->Internal = STATUS_PENDING;
- hEvent = lpOverlapped->hEvent;
- IoStatusBlock = (PIO_STATUS_BLOCK)lpOverlapped;
- }
- else
- {
- IoStatusBlock = &Iosb;
- hEvent = NULL;
- }
-
- Status = NtFsControlFile(hNamedPipe,
- hEvent,
- NULL,
- NULL,
- IoStatusBlock,
- FSCTL_PIPE_LISTEN,
- NULL,
- 0,
- NULL,
- 0);
- if ((lpOverlapped == NULL) && (Status == STATUS_PENDING))
- {
- Status = NtWaitForSingleObject(hNamedPipe,
- FALSE,
- NULL);
- if (NT_SUCCESS(Status))
- {
- Status = Iosb.Status;
- }
- }
+ NTSTATUS Status;
- if ((!NT_SUCCESS(Status) && Status != STATUS_PIPE_CONNECTED) ||
- (Status == STATUS_PENDING))
- {
- SetLastErrorByStatus(Status);
- return FALSE;
- }
+ if (lpOverlapped != NULL)
+ {
+ PVOID ApcContext;
+
+ lpOverlapped->Internal = STATUS_PENDING;
+ ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
+
+ Status = NtFsControlFile(hNamedPipe,
+ lpOverlapped->hEvent,
+ NULL,
+ ApcContext,
+ (PIO_STATUS_BLOCK)lpOverlapped,
+ FSCTL_PIPE_LISTEN,
+ NULL,
+ 0,
+ NULL,
+ 0);
+
+ /* return FALSE in case of failure and pending operations! */
+ if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
+ {
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+ }
+ else
+ {
+ IO_STATUS_BLOCK Iosb;
+
+ Status = NtFsControlFile(hNamedPipe,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ FSCTL_PIPE_LISTEN,
+ NULL,
+ 0,
+ NULL,
+ 0);
+
+ /* 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))
+ {
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+ }
- return TRUE;
+ return TRUE;
}
-
/*
* @implemented
*/
-BOOL STDCALL
+BOOL
+STDCALL
SetNamedPipeHandleState(HANDLE hNamedPipe,
- LPDWORD lpMode,
- LPDWORD lpMaxCollectionCount,
- LPDWORD lpCollectDataTimeout)
+ LPDWORD lpMode,
+ LPDWORD lpMaxCollectionCount,
+ LPDWORD lpCollectDataTimeout)
{
- NPFS_GET_STATE GetState;
- NPFS_SET_STATE SetState;
- IO_STATUS_BLOCK Iosb;
- NTSTATUS Status;
-
- Status = NtFsControlFile(hNamedPipe,
- NULL,
- NULL,
- NULL,
- &Iosb,
- FSCTL_PIPE_GET_STATE,
- NULL,
- 0,
- &GetState,
- sizeof(NPFS_GET_STATE));
- if (Status == STATUS_PENDING)
- {
- Status = NtWaitForSingleObject(hNamedPipe,
- FALSE,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return(FALSE);
- }
- }
+ IO_STATUS_BLOCK Iosb;
+ NTSTATUS Status;
- if (lpMode != NULL)
- {
- if ((*lpMode) & PIPE_READMODE_MESSAGE)
- {
- SetState.ReadModeMessage = TRUE;
- }
- else
- {
- SetState.ReadModeMessage = FALSE;
- }
- if ((*lpMode) & PIPE_NOWAIT)
- {
- SetState.NonBlocking = TRUE;
- }
- else
- {
- SetState.NonBlocking = FALSE;
- }
- SetState.WriteModeMessage = GetState.WriteModeMessage;
- }
- else
- {
- SetState.ReadModeMessage = GetState.ReadModeMessage;
- SetState.WriteModeMessage = GetState.WriteModeMessage;
- SetState.NonBlocking = SetState.NonBlocking;
- }
-
- if (lpMaxCollectionCount != NULL)
- {
- SetState.InBufferSize = *lpMaxCollectionCount;
- }
- else
- {
- SetState.InBufferSize = GetState.InBufferSize;
- }
-
- SetState.OutBufferSize = GetState.OutBufferSize;
-
- if (lpCollectDataTimeout != NULL)
- {
- SetState.Timeout.QuadPart = (*lpCollectDataTimeout) * -10000;
- }
- else
- {
- SetState.Timeout = GetState.Timeout;
- }
+ /* Check if the Mode is being changed */
+ if (lpMode)
+ {
+ FILE_PIPE_INFORMATION Settings;
+
+ /* Set the Completion Mode */
+ Settings.CompletionMode = (*lpMode & PIPE_NOWAIT) ?
+ FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
+
+ /* Set the Read Mode */
+ Settings.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE) ?
+ FILE_PIPE_MESSAGE_MODE: FILE_PIPE_BYTE_STREAM_MODE;
+
+ /* Send the changes to the Driver */
+ Status = NtSetInformationFile(hNamedPipe,
+ &Iosb,
+ &Settings,
+ sizeof(FILE_PIPE_INFORMATION),
+ FilePipeInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+ }
- Status = NtFsControlFile(hNamedPipe,
- NULL,
- NULL,
- NULL,
- &Iosb,
- FSCTL_PIPE_SET_STATE,
- &SetState,
- sizeof(NPFS_SET_STATE),
- NULL,
- 0);
- if (Status == STATUS_PENDING)
- {
- Status = NtWaitForSingleObject(hNamedPipe,
- FALSE,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return(FALSE);
- }
- }
+ /* Check if the Collection count or Timeout are being changed */
+ if (lpMaxCollectionCount || lpCollectDataTimeout)
+ {
+ FILE_PIPE_REMOTE_INFORMATION RemoteSettings;
+
+ /* Setting one without the other would delete it, so we read old one */
+ if (!lpMaxCollectionCount || !lpCollectDataTimeout)
+ {
+ Status = NtQueryInformationFile(hNamedPipe,
+ &Iosb,
+ &RemoteSettings,
+ sizeof(FILE_PIPE_REMOTE_INFORMATION),
+ FilePipeRemoteInformation);
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+ }
+
+ /* Now set the new settings */
+ RemoteSettings.MaximumCollectionCount = (lpMaxCollectionCount) ?
+ *lpMaxCollectionCount :
+ RemoteSettings.MaximumCollectionCount;
+ if (lpCollectDataTimeout)
+ {
+ /* Convert it to Quad */
+ RemoteSettings.CollectDataTime.QuadPart = -(LONGLONG)
+ UInt32x32To64(10000,
+ *lpCollectDataTimeout);
+ }
+
+ /* Tell the driver to change them */
+ Status = NtSetInformationFile(hNamedPipe,
+ &Iosb,
+ &RemoteSettings,
+ sizeof(FILE_PIPE_REMOTE_INFORMATION),
+ FilePipeRemoteInformation);
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return(FALSE);
+ }
+ }
- return(TRUE);
+ /* All done */
+ return TRUE;
}
-
/*
* @implemented
*/
{
UNICODE_STRING PipeName;
BOOL Result;
-
+
RtlCreateUnicodeStringFromAsciiz(&PipeName,
(LPSTR)lpNamedPipeName);
-
+
Result = CallNamedPipeW(PipeName.Buffer,
lpInBuffer,
nInBufferSize,
nOutBufferSize,
lpBytesRead,
nTimeOut);
-
+
RtlFreeUnicodeString(&PipeName);
-
+
return(Result);
}
if (lpState != NULL)
{
FILE_PIPE_INFORMATION PipeInfo;
-
+
Status = NtQueryInformationFile(hNamedPipe,
&StatusBlock,
&PipeInfo,
if(lpCurInstances != NULL)
{
FILE_PIPE_LOCAL_INFORMATION LocalInfo;
-
+
Status = NtQueryInformationFile(hNamedPipe,
&StatusBlock,
&LocalInfo,
if(lpMaxCollectionCount != NULL || lpCollectDataTimeout != NULL)
{
FILE_PIPE_REMOTE_INFORMATION RemoteInfo;
-
+
Status = NtQueryInformationFile(hNamedPipe,
&StatusBlock,
&RemoteInfo,
{
*lpMaxCollectionCount = RemoteInfo.MaximumCollectionCount;
}
-
+
if(lpCollectDataTimeout != NULL)
{
/* FIXME */
*lpCollectDataTimeout = 0;
}
}
-
+
if(lpUserName != NULL)
{
/* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
UNICODE_STRING UserNameW;
ANSI_STRING UserNameA;
BOOL Ret;
-
+
if(lpUserName != NULL)
{
UserNameW.Length = 0;
UserNameW.MaximumLength = nMaxUserNameSize * sizeof(WCHAR);
UserNameW.Buffer = HeapAlloc(GetCurrentProcess(), 0, UserNameW.MaximumLength);
-
+
UserNameA.Buffer = lpUserName;
UserNameA.Length = 0;
UserNameA.MaximumLength = nMaxUserNameSize;
}
-
+
Ret = GetNamedPipeHandleStateW(hNamedPipe,
lpState,
lpCurInstances,
Ret = FALSE;
}
}
-
+
if(UserNameW.Buffer != NULL)
{
HeapFree(GetCurrentProcess(), 0, UserNameW.Buffer);
}
-
+
return Ret;
}
FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation;
IO_STATUS_BLOCK StatusBlock;
NTSTATUS Status;
-
+
Status = NtQueryInformationFile(hNamedPipe,
&StatusBlock,
&PipeLocalInformation,
SetLastErrorByStatus(Status);
return(FALSE);
}
-
+
if (lpFlags != NULL)
{
*lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
*lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
}
-
+
if (lpOutBufferSize != NULL)
*lpOutBufferSize = PipeLocalInformation.OutboundQuota;
-
+
if (lpInBufferSize != NULL)
*lpInBufferSize = PipeLocalInformation.InboundQuota;
-
+
if (lpMaxInstances != NULL)
{
if (PipeLocalInformation.MaximumInstances >= 255)
else
*lpMaxInstances = PipeLocalInformation.MaximumInstances;
}
-
+
return(TRUE);
}
* @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;
-
- Status = NtFsControlFile(hNamedPipe,
- lpOverlapped->hEvent,
- NULL,
- NULL,
- (PIO_STATUS_BLOCK)lpOverlapped,
- FSCTL_PIPE_TRANSCEIVE,
- lpInBuffer,
- nInBufferSize,
- lpOutBuffer,
- nOutBufferSize);
- }
+ if (lpBytesRead != NULL)
+ {
+ *lpBytesRead = 0;
+ }
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return(FALSE);
- }
+ if (lpOverlapped != NULL)
+ {
+ PVOID ApcContext;
+
+ ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
+ lpOverlapped->Internal = STATUS_PENDING;
+
+ 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);
+ return TRUE;
}
/* EOF */