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;
- }
-
- if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES)
- {
- nMaxInstances = 0xFFFFFFFF;
- }
+ NonBlocking = FILE_PIPE_QUEUE_OPERATION;
DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000LL;
&ObjectAttributes,
&Iosb,
ShareAccess,
- CreateDisposition,
+ FILE_OPEN_IF,
CreateOptions,
WriteModeMessage,
ReadModeMessage,
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
*/
return(TRUE);
}
-
+#endif
/*
* @implemented
return TRUE;
}
-
/*
* @implemented
*/
-BOOL
+BOOL
STDCALL
SetNamedPipeHandleState(HANDLE hNamedPipe,
LPDWORD lpMode,
Settings.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE) ?
FILE_PIPE_MESSAGE_MODE: FILE_PIPE_BYTE_STREAM_MODE;
- /* Send the changes to the Driver */
+ /* Send the changes to the Driver */
Status = NtSetInformationFile(hNamedPipe,
&Iosb,
&Settings,
return(FALSE);
}
}
-
+
/* Check if the Collection count or Timeout are being changed */
if (lpMaxCollectionCount || lpCollectDataTimeout)
{
}
}
- /* Now set the new settings */
- RemoteSettings.MaximumCollectionCount = (lpMaxCollectionCount) ?
- *lpMaxCollectionCount :
+ /* Now set the new settings */
+ RemoteSettings.MaximumCollectionCount = (lpMaxCollectionCount) ?
+ *lpMaxCollectionCount :
RemoteSettings.MaximumCollectionCount;
if (lpCollectDataTimeout)
{