- Fix CreateNamedPipeW to convert some NT flags properly, timeouts, etc,
and document/prettify the function.
- NT 5.2 NPFS now works great, the kernel32_wintest pipe runs without
crashing, and reports "411 tests passed, 30 failures".
Modified: trunk/reactos/include/ndk/iotypes.h
Modified: trunk/reactos/lib/kernel32/file/npipe.c
_____
Modified: trunk/reactos/include/ndk/iotypes.h
--- trunk/reactos/include/ndk/iotypes.h 2005-11-08 23:51:46 UTC (rev
19077)
+++ trunk/reactos/include/ndk/iotypes.h 2005-11-09 00:44:37 UTC (rev
19078)
@@ -38,6 +38,7 @@
/* Pipe Flags */
#define FILE_PIPE_BYTE_STREAM_TYPE 0x00000000
+#define FILE_PIPE_MESSAGE_TYPE 0x00000001
#define FILE_PIPE_BYTE_STREAM_MODE 0x00000000
#define FILE_PIPE_MESSAGE_MODE 0x00000001
#define FILE_PIPE_QUEUE_OPERATION 0x00000000
_____
Modified: trunk/reactos/lib/kernel32/file/npipe.c
--- trunk/reactos/lib/kernel32/file/npipe.c 2005-11-08 23:51:46 UTC
(rev 19077)
+++ trunk/reactos/lib/kernel32/file/npipe.c 2005-11-09 00:44:37 UTC
(rev 19078)
@@ -13,6 +13,7 @@
#include <k32.h>
#define NDEBUG
+//#define USING_PROPER_NPFS_WAIT_SEMANTICS
#include "../include/debug.h"
/* FUNCTIONS
****************************************************************/
@@ -51,130 +52,178 @@
return(NamedPipeHandle);
}
-
/*
* @implemented
*/
-HANDLE STDCALL
+HANDLE
+STDCALL
CreateNamedPipeW(LPCWSTR lpName,
- DWORD dwOpenMode,
- DWORD dwPipeMode,
- DWORD nMaxInstances,
- DWORD nOutBufferSize,
- DWORD nInBufferSize,
- DWORD nDefaultTimeOut,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes)
+ DWORD dwOpenMode,
+ DWORD dwPipeMode,
+ DWORD nMaxInstances,
+ DWORD nOutBufferSize,
+ DWORD nInBufferSize,
+ DWORD nDefaultTimeOut,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
- UNICODE_STRING NamedPipeName;
- BOOL Result;
- NTSTATUS Status;
- OBJECT_ATTRIBUTES ObjectAttributes;
- HANDLE PipeHandle;
- ACCESS_MASK DesiredAccess;
- ULONG CreateOptions;
- ULONG WriteModeMessage;
- ULONG ReadModeMessage;
- ULONG NonBlocking;
- IO_STATUS_BLOCK Iosb;
- ULONG ShareAccess, Attributes;
- LARGE_INTEGER DefaultTimeOut;
- PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
+ UNICODE_STRING NamedPipeName;
+ BOOL Result;
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE PipeHandle;
+ ACCESS_MASK DesiredAccess;
+ ULONG CreateOptions = 0;
+ ULONG WriteModeMessage;
+ ULONG ReadModeMessage;
+ ULONG NonBlocking;
+ IO_STATUS_BLOCK Iosb;
+ ULONG ShareAccess = 0, Attributes;
+ LARGE_INTEGER DefaultTimeOut;
+ PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
- if (nMaxInstances == 0 || nMaxInstances > PIPE_UNLIMITED_INSTANCES)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return INVALID_HANDLE_VALUE;
- }
+ /* Check for valid instances */
+ if (nMaxInstances == 0 || nMaxInstances > PIPE_UNLIMITED_INSTANCES)
+ {
+ /* Fail */
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
- Result = RtlDosPathNameToNtPathName_U((LPWSTR)lpName,
- &NamedPipeName,
- NULL,
- NULL);
- if (!Result)
- {
- SetLastError(ERROR_PATH_NOT_FOUND);
- return(INVALID_HANDLE_VALUE);
- }
+ /* Convert to NT syntax */
+ if (nMaxInstances == PIPE_UNLIMITED_INSTANCES) nMaxInstances = -1;
- DPRINT("Pipe name: %wZ\n", &NamedPipeName);
- DPRINT("Pipe name: %S\n", NamedPipeName.Buffer);
+ /* Convert the name */
+ Result = RtlDosPathNameToNtPathName_U((LPWSTR)lpName,
+ &NamedPipeName,
+ NULL,
+ NULL);
+ if (!Result)
+ {
+ /* Conversion failed */
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return(INVALID_HANDLE_VALUE);
+ }
- Attributes = OBJ_CASE_INSENSITIVE;
- if(lpSecurityAttributes)
- {
- SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
- if(lpSecurityAttributes->bInheritHandle)
- Attributes |= OBJ_INHERIT;
- }
+ DPRINT1("Pipe name: %wZ\n", &NamedPipeName);
+ DPRINT1("Pipe name: %S\n", NamedPipeName.Buffer);
- InitializeObjectAttributes(&ObjectAttributes,
- &NamedPipeName,
- Attributes,
- NULL,
- SecurityDescriptor);
+ /* Always case insensitive, check if we got extra attributes */
+ Attributes = OBJ_CASE_INSENSITIVE;
+ if(lpSecurityAttributes)
+ {
+ /* We did; get the security descriptor */
+ SecurityDescriptor =
lpSecurityAttributes->lpSecurityDescriptor;
- DesiredAccess = SYNCHRONIZE | (dwOpenMode & (WRITE_DAC | WRITE_OWNER
| ACCESS_SYSTEM_SECURITY));
- ShareAccess = 0;
- CreateOptions = 0;
+ /* And check if this is pipe's handle will beinheritable */
+ if(lpSecurityAttributes->bInheritHandle) Attributes |=
OBJ_INHERIT;
+ }
- if (dwOpenMode & FILE_FLAG_WRITE_THROUGH)
- CreateOptions = CreateOptions | FILE_WRITE_THROUGH;
+ /* Now we can initialize the object attributes */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &NamedPipeName,
+ Attributes,
+ NULL,
+ SecurityDescriptor);
- if (!(dwOpenMode & FILE_FLAG_OVERLAPPED))
- CreateOptions = CreateOptions | FILE_SYNCHRONOUS_IO_NONALERT;
+ /* Setup the default Desired Access */
+ DesiredAccess = SYNCHRONIZE | (dwOpenMode & (WRITE_DAC |
+ WRITE_OWNER |
+
ACCESS_SYSTEM_SECURITY));
- if (dwOpenMode & PIPE_ACCESS_OUTBOUND)
- {
- ShareAccess |= FILE_SHARE_READ;
- DesiredAccess |= GENERIC_WRITE;
- }
- if (dwOpenMode & PIPE_ACCESS_INBOUND)
- {
- ShareAccess |= FILE_SHARE_WRITE;
- DesiredAccess |= GENERIC_READ;
- }
- if (dwPipeMode & PIPE_TYPE_MESSAGE)
- WriteModeMessage = FILE_PIPE_MESSAGE_MODE;
- else
- WriteModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
+ /* Convert to NT Create Flags */
+ if (dwOpenMode & FILE_FLAG_WRITE_THROUGH)
+ {
+ CreateOptions |= FILE_WRITE_THROUGH;
+ }
+ if (!(dwOpenMode & FILE_FLAG_OVERLAPPED))
+ {
+ CreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT;
+ }
- if (dwPipeMode & PIPE_READMODE_MESSAGE)
- ReadModeMessage = FILE_PIPE_MESSAGE_MODE;
- else
- ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
+ /* Handle all open modes */
+ if (dwOpenMode & PIPE_ACCESS_OUTBOUND)
+ {
+ ShareAccess |= FILE_SHARE_READ;
+ DesiredAccess |= GENERIC_WRITE;
+ }
+ if (dwOpenMode & PIPE_ACCESS_INBOUND)
+ {
+ ShareAccess |= FILE_SHARE_WRITE;
+ DesiredAccess |= GENERIC_READ;
+ }
- if (dwPipeMode & PIPE_NOWAIT)
- NonBlocking = FILE_PIPE_COMPLETE_OPERATION;
- else
- NonBlocking = FILE_PIPE_QUEUE_OPERATION;
+ /* Handle the type flags */
+ if (dwPipeMode & PIPE_TYPE_MESSAGE)
+ {
+ WriteModeMessage = FILE_PIPE_MESSAGE_TYPE;
+ }
+ else
+ {
+ WriteModeMessage = FILE_PIPE_BYTE_STREAM_TYPE;
+ }
- DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000LL;
+ /* Handle the mode flags */
+ if (dwPipeMode & PIPE_READMODE_MESSAGE)
+ {
+ ReadModeMessage = FILE_PIPE_MESSAGE_MODE;
+ }
+ else
+ {
+ ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
+ }
- Status = NtCreateNamedPipeFile(&PipeHandle,
- DesiredAccess,
- &ObjectAttributes,
- &Iosb,
- ShareAccess,
- FILE_OPEN_IF,
- CreateOptions,
- WriteModeMessage,
- ReadModeMessage,
- NonBlocking,
- nMaxInstances,
- nInBufferSize,
- nOutBufferSize,
- &DefaultTimeOut);
+ /* Handle the blocking mode */
+ if (dwPipeMode & PIPE_NOWAIT)
+ {
+ NonBlocking = FILE_PIPE_COMPLETE_OPERATION;
+ }
+ else
+ {
+ NonBlocking = FILE_PIPE_QUEUE_OPERATION;
+ }
- RtlFreeUnicodeString(&NamedPipeName);
+ /* Check if we have a timeout */
+ if (nDefaultTimeOut)
+ {
+ /* Convert the time to NT format */
+ DefaultTimeOut.QuadPart = UInt32x32To64(nDefaultTimeOut,
-10000);
+ }
+ else
+ {
+ /* Use default timeout of 50 ms */
+ DefaultTimeOut.QuadPart = -500000;
+ }
- if (!NT_SUCCESS(Status))
- {
- DPRINT("NtCreateNamedPipe failed (Status %x)!\n", Status);
- SetLastErrorByStatus (Status);
- return INVALID_HANDLE_VALUE;
- }
+ /* Now create the pipe */
+ Status = NtCreateNamedPipeFile(&PipeHandle,
+ DesiredAccess,
+ &ObjectAttributes,
+ &Iosb,
+ ShareAccess,
+ FILE_OPEN_IF,
+ CreateOptions,
+ WriteModeMessage,
+ ReadModeMessage,
+ NonBlocking,
+ nMaxInstances,
+ nInBufferSize,
+ nOutBufferSize,
+ &DefaultTimeOut);
- return PipeHandle;
+ /* Free the name */
+ RtlFreeUnicodeString(&NamedPipeName);
+
+ /* Check status */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed to create it */
+ DPRINT1("NtCreateNamedPipe failed (Status %x)!\n", Status);
+ SetLastErrorByStatus (Status);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ /* Return the handle */
+ return PipeHandle;
}