diff --git a/reactos/drivers/filesystems/CMakeLists.txt b/reactos/drivers/filesystems/CMakeLists.txt index 3815d890f06..1dd2bc7f115 100644 --- a/reactos/drivers/filesystems/CMakeLists.txt +++ b/reactos/drivers/filesystems/CMakeLists.txt @@ -6,5 +6,5 @@ add_subdirectory(fastfat) add_subdirectory(fs_rec) add_subdirectory(msfs) add_subdirectory(mup) -add_subdirectory(npfs_new) +add_subdirectory(npfs) add_subdirectory(ntfs) diff --git a/reactos/drivers/filesystems/npfs/CMakeLists.txt b/reactos/drivers/filesystems/npfs/CMakeLists.txt index b1d4c044782..079709320ca 100644 --- a/reactos/drivers/filesystems/npfs/CMakeLists.txt +++ b/reactos/drivers/filesystems/npfs/CMakeLists.txt @@ -1,19 +1,29 @@ list(APPEND SOURCE + cleanup.c + close.c create.c - dirctl.c - finfo.c + datasup.c + fileinfo.c + fileobsup.c + flushbuf.c fsctrl.c - npfs.c - rw.c - volume.c - npfs.rc) + main.c + prefxsup.c + read.c + readsup.c + secursup.c + seinfo.c + statesup.c + strucsup.c + volinfo.c + waitsup.c + write.c + writesup.c) add_library(npfs SHARED ${SOURCE}) - -target_link_libraries(npfs ${PSEH_LIB}) - set_module_type(npfs kernelmodedriver) +target_link_libraries(npfs ${PSEH_LIB}) add_importlibs(npfs ntoskrnl hal) add_pch(npfs npfs.h) add_cd_file(TARGET npfs DESTINATION reactos/system32/drivers FOR all) diff --git a/reactos/drivers/filesystems/npfs_new/cleanup.c b/reactos/drivers/filesystems/npfs/cleanup.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/cleanup.c rename to reactos/drivers/filesystems/npfs/cleanup.c diff --git a/reactos/drivers/filesystems/npfs_new/close.c b/reactos/drivers/filesystems/npfs/close.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/close.c rename to reactos/drivers/filesystems/npfs/close.c diff --git a/reactos/drivers/filesystems/npfs/create.c b/reactos/drivers/filesystems/npfs/create.c index abdfe5e38d6..4e46e5b5ad2 100644 --- a/reactos/drivers/filesystems/npfs/create.c +++ b/reactos/drivers/filesystems/npfs/create.c @@ -1,1029 +1,746 @@ /* -* COPYRIGHT: See COPYING in the top level directory -* PROJECT: ReactOS kernel -* FILE: drivers/filesystems/npfs/create.c -* PURPOSE: Named pipe filesystem -* PROGRAMMER: David Welch -*/ + * PROJECT: ReactOS Named Pipe FileSystem + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/filesystems/npfs/create.c + * PURPOSE: Pipes Creation + * PROGRAMMERS: ReactOS Portable Systems Group + */ -/* INCLUDES ******************************************************************/ +/* INCLUDES *******************************************************************/ #include "npfs.h" -#define NDEBUG -#include +// File ID number for NPFS bugchecking support +#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_CREATE) -//#define USING_PROPER_NPFS_WAIT_SEMANTICS - -/* FUNCTIONS *****************************************************************/ +/* FUNCTIONS ******************************************************************/ VOID -NpfsDereferenceFcb(PNPFS_FCB Fcb) +NTAPI +NpCheckForNotify(IN PNP_DCB Dcb, + IN BOOLEAN SecondList, + IN PLIST_ENTRY List) { - PNPFS_VCB Vcb = Fcb->Vcb; - - KeLockMutex(&Vcb->PipeListLock); - if (InterlockedDecrement(&Fcb->RefCount) == 0) - { - DPRINT("NpfsDereferenceFcb. Deleting %p\n", Fcb); - RemoveEntryList(&Fcb->PipeListEntry); - RtlFreeUnicodeString(&Fcb->PipeName); - ExFreePoolWithTag(Fcb, TAG_NPFS_FCB); - } - KeUnlockMutex(&Vcb->PipeListLock); -} - -static -PNPFS_CCB -NpfsAllocateCcb(CCB_TYPE Type, PNPFS_FCB Fcb) -{ - PNPFS_CCB Ccb; - - Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_CCB), TAG_NPFS_CCB); - if (!Ccb) - { - return NULL; - } - - RtlZeroMemory(Ccb, sizeof(NPFS_CCB)); - - Ccb->RefCount = 1; - Ccb->Type = Type; - // FIXME: why does this function not reference Fcb? - Ccb->Fcb = Fcb; - Ccb->OtherSide = NULL; - - return Ccb; -} - -static -VOID -NpfsReferenceCcb(PNPFS_CCB Ccb) -{ - ASSERT(Ccb->RefCount > 0); - InterlockedIncrement(&Ccb->RefCount); -} - -static -VOID -NpfsDereferenceCcb(PNPFS_CCB Ccb) -{ - /* Decrement reference count */ - ASSERT(Ccb->RefCount > 0); - if (InterlockedDecrement(&Ccb->RefCount) == 0) - { - /* Its zero, delete CCB */ - ExFreePoolWithTag(Ccb, TAG_NPFS_CCB); - } -} - -static -VOID -NpfsCcbSetOtherSide(PNPFS_CCB Ccb, PNPFS_CCB OtherSide) -{ - /* Dereference old other side */ - if (Ccb->OtherSide) NpfsDereferenceCcb(Ccb->OtherSide); - - /* Reference the new other side */ - if (OtherSide) NpfsReferenceCcb(OtherSide); - - /* Set new value */ - Ccb->OtherSide = OtherSide; -} - -PNPFS_FCB -NpfsFindPipe(PNPFS_VCB Vcb, - PUNICODE_STRING PipeName) -{ - PLIST_ENTRY CurrentEntry; - PNPFS_FCB Fcb; - - CurrentEntry = Vcb->PipeListHead.Flink; - while (CurrentEntry != &Vcb->PipeListHead) - { - Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, PipeListEntry); - if (RtlCompareUnicodeString(PipeName, - &Fcb->PipeName, - TRUE) == 0) - { - DPRINT("<%wZ> = <%wZ>\n", PipeName, &Fcb->PipeName); - (VOID)InterlockedIncrement(&Fcb->RefCount); - return Fcb; - } - - CurrentEntry = CurrentEntry->Flink; - } - - return NULL; -} - - -static PNPFS_CCB -NpfsFindListeningServerInstance(PNPFS_FCB Fcb) -{ - PLIST_ENTRY CurrentEntry; - PNPFS_WAITER_ENTRY Waiter; - KIRQL oldIrql; + PLIST_ENTRY NextEntry, ListHead; PIRP Irp; - - CurrentEntry = Fcb->WaiterListHead.Flink; - while (CurrentEntry != &Fcb->WaiterListHead) + ULONG i; + PAGED_CODE(); + + ListHead = &Dcb->NotifyList; + for (i = 0; i < 2; i++) { - Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry); - Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext); - if (Waiter->Ccb->PipeState == FILE_PIPE_LISTENING_STATE) + ASSERT(IsListEmpty(ListHead)); + while (!IsListEmpty(ListHead)) { - DPRINT("Server found! CCB %p\n", Waiter->Ccb); + NextEntry = RemoveHeadList(ListHead); - IoAcquireCancelSpinLock(&oldIrql); - if (!Irp->Cancel) + Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry); + + if (IoSetCancelRoutine(Irp, NULL)) { - if (IoSetCancelRoutine(Irp, NULL) != NULL) - { - IoReleaseCancelSpinLock(oldIrql); - return Waiter->Ccb; - } + Irp->IoStatus.Status = STATUS_SUCCESS; + InsertTailList(List, NextEntry); + } + else + { + InitializeListHead(NextEntry); } - IoReleaseCancelSpinLock(oldIrql); } - CurrentEntry = CurrentEntry->Flink; + if (!SecondList) break; + ListHead = &Dcb->NotifyList2; } - - return NULL; } - -static VOID -NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb, - PNPFS_CCB Ccb) +IO_STATUS_BLOCK +NTAPI +NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject, + IN ACCESS_MASK DesiredAccess) { - PLIST_ENTRY CurrentEntry; - PNPFS_WAITER_ENTRY Waiter; - PIRP Irp; + IO_STATUS_BLOCK Status; + PAGED_CODE(); - CurrentEntry = Fcb->WaiterListHead.Flink; - while (CurrentEntry != &Fcb->WaiterListHead) - { - Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry); - if (Waiter->Ccb == Ccb) - { - DPRINT("Server found! CCB %p\n", Waiter->Ccb); + NpSetFileObject(FileObject, NpVcb, NULL, FALSE); + ++NpVcb->ReferenceCount; - RemoveEntryList(&Waiter->Entry); - Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext); - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - break; - } - CurrentEntry = CurrentEntry->Flink; - } + Status.Information = FILE_OPENED; + Status.Status = STATUS_SUCCESS; + return Status; } - -static VOID -NpfsOpenFileSystem(PNPFS_FCB Fcb, - PFILE_OBJECT FileObject, - PIO_STATUS_BLOCK IoStatus) +IO_STATUS_BLOCK +NTAPI +NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb, + IN PFILE_OBJECT FileObject, + IN ACCESS_MASK DesiredAccess, + IN PLIST_ENTRY List) { - PNPFS_CCB Ccb; + IO_STATUS_BLOCK IoStatus; + PNP_ROOT_DCB_FCB Ccb; + PAGED_CODE(); - DPRINT("NpfsOpenFileSystem()\n"); - - Ccb = NpfsAllocateCcb(CCB_DEVICE, Fcb); - if (Ccb == NULL) + IoStatus.Status = NpCreateRootDcbCcb(&Ccb); + if (NT_SUCCESS(IoStatus.Status)) { - IoStatus->Status = STATUS_NO_MEMORY; - return; + NpSetFileObject(FileObject, Dcb, Ccb, FALSE); + ++Dcb->CurrentInstances; + + IoStatus.Information = FILE_OPENED; + IoStatus.Status = STATUS_SUCCESS; + } + else + { + IoStatus.Information = 0; } - Ccb->FileObject = FileObject; - - FileObject->FsContext = Fcb; - FileObject->FsContext2 = Ccb; - - IoStatus->Information = FILE_OPENED; - IoStatus->Status = STATUS_SUCCESS; - - return; + return IoStatus; } - -static VOID -NpfsOpenRootDirectory(PNPFS_FCB Fcb, - PFILE_OBJECT FileObject, - PIO_STATUS_BLOCK IoStatus) +IO_STATUS_BLOCK +NTAPI +NpCreateClientEnd(IN PNP_FCB Fcb, + IN PFILE_OBJECT FileObject, + IN ACCESS_MASK DesiredAccess, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, + IN PACCESS_STATE AccessState, + IN KPROCESSOR_MODE PreviousMode, + IN PETHREAD Thread, + IN PLIST_ENTRY List) { - PNPFS_CCB Ccb; + PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext; + BOOLEAN AccessGranted; + ACCESS_MASK GrantedAccess; + PPRIVILEGE_SET Privileges; + UNICODE_STRING ObjectTypeName; + IO_STATUS_BLOCK IoStatus; + USHORT NamedPipeConfiguration; + PLIST_ENTRY NextEntry, ListHead; + PNP_CCB Ccb = NULL; - DPRINT("NpfsOpenRootDirectory()\n"); + IoStatus.Status = STATUS_SUCCESS; + IoStatus.Information = 0; + Privileges = NULL; - Ccb = NpfsAllocateCcb(CCB_DIRECTORY, Fcb); - if (Ccb == NULL) + NamedPipeConfiguration = Fcb->NamedPipeConfiguration; + + SubjectSecurityContext = &AccessState->SubjectSecurityContext; + SeLockSubjectContext(SubjectSecurityContext); + + AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor, + SubjectSecurityContext, + TRUE, + DesiredAccess & ~4, + 0, + &Privileges, + IoGetFileObjectGenericMapping(), + PreviousMode, + &GrantedAccess, + &IoStatus.Status); + + if (Privileges) { - IoStatus->Status = STATUS_NO_MEMORY; - return; + SeAppendPrivileges(AccessState, Privileges); + SeFreePrivileges(Privileges); } - Ccb->FileObject = FileObject; + if (AccessGranted) + { + AccessState->PreviouslyGrantedAccess |= GrantedAccess; + AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED); + } - FileObject->FsContext = Fcb; - FileObject->FsContext2 = Ccb; + ObjectTypeName.Buffer = L"NamedPipe"; + ObjectTypeName.Length = 18; + SeOpenObjectAuditAlarm(&ObjectTypeName, + NULL, + &FileObject->FileName, + Fcb->SecurityDescriptor, + AccessState, + FALSE, + AccessGranted, + PreviousMode, + &AccessState->GenerateOnClose); + SeUnlockSubjectContext(SubjectSecurityContext); + if (!AccessGranted) return IoStatus; - IoStatus->Information = FILE_OPENED; - IoStatus->Status = STATUS_SUCCESS; + if (((GrantedAccess & FILE_READ_DATA) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) || + ((GrantedAccess & FILE_WRITE_DATA) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND))) + { + IoStatus.Status = STATUS_ACCESS_DENIED; + return IoStatus; + } - return; + if (!(GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA))) SecurityQos = NULL; + + ListHead = &Fcb->CcbList; + NextEntry = ListHead->Flink; + while (NextEntry != ListHead) + { + Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry); + if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break; + + NextEntry = NextEntry->Flink; + } + + if (NextEntry == ListHead) + { + IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE; + return IoStatus; + } + + IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread); + if (!NT_SUCCESS(IoStatus.Status)) return IoStatus; + + IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List); + if (!NT_SUCCESS(IoStatus.Status)) + { + NpUninitializeSecurity(Ccb); + return IoStatus; + } + + Ccb->ClientSession = NULL; + Ccb->Process = IoThreadToProcess(Thread); + + IoStatus.Information = FILE_OPENED; + IoStatus.Status = STATUS_SUCCESS; + return IoStatus; } - -NTSTATUS NTAPI -NpfsCreate(PDEVICE_OBJECT DeviceObject, - PIRP Irp) +NTSTATUS +NTAPI +NpFsdCreate(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { PEXTENDED_IO_STACK_LOCATION IoStack; - PUNICODE_STRING FileName; + UNICODE_STRING FileName; PFILE_OBJECT FileObject; PFILE_OBJECT RelatedFileObject; - PNPFS_FCB Fcb; - PNPFS_CCB ClientCcb; - PNPFS_CCB ServerCcb = NULL; - PNPFS_VCB Vcb; - NTSTATUS Status; -#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS + NODE_TYPE_CODE Type; + PNP_CCB Ccb; + PNP_FCB Fcb; + PNP_DCB Dcb; ACCESS_MASK DesiredAccess; - BOOLEAN SpecialAccess; -#endif + LIST_ENTRY DeferredList; + UNICODE_STRING Prefix; - DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp); - - Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension; + InitializeListHead(&DeferredList); IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp); FileObject = IoStack->FileObject; RelatedFileObject = FileObject->RelatedFileObject; - FileName = &FileObject->FileName; -#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS + FileName = FileObject->FileName; DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess; -#endif - DPRINT("FileObject %p\n", FileObject); - DPRINT("FileName %wZ\n", &FileObject->FileName); + FsRtlEnterFileSystem(); + ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE); - Irp->IoStatus.Information = 0; - -#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS - SpecialAccess = ((DesiredAccess & SPECIFIC_RIGHTS_ALL) == FILE_READ_ATTRIBUTES); - if (SpecialAccess) + if (RelatedFileObject) { - DPRINT("NpfsCreate() open client end for special use!\n"); + Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE); } -#endif - - DPRINT("FileName->Length: %hu RelatedFileObject: %p\n", FileName->Length, RelatedFileObject); - - /* Open the file system */ - if (FileName->Length == 0 && - (RelatedFileObject == NULL || ((PNPFS_CCB)RelatedFileObject->FsContext2)->Type == CCB_DEVICE)) + else { - DPRINT("Open the file system\n"); - - NpfsOpenFileSystem(Vcb->DeviceFcb, - FileObject, - &Irp->IoStatus); - - Status = Irp->IoStatus.Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; + Type = 0; + Fcb = NULL; + Ccb = NULL; } - /* Open the root directory */ - if ((FileName->Length == 2 && FileName->Buffer[0] == L'\\' && RelatedFileObject == NULL) || - (FileName->Length == 0 && ((PNPFS_CCB)RelatedFileObject->FsContext2)->Type == CCB_DIRECTORY)) + if (FileName.Length) { - DPRINT("Open the root directory\n"); - - NpfsOpenRootDirectory(Vcb->RootFcb, - FileObject, - &Irp->IoStatus); - - Status = Irp->IoStatus.Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - } - - - /* - * Step 1. Find the pipe we're trying to open. - */ - KeLockMutex(&Vcb->PipeListLock); - Fcb = NpfsFindPipe(Vcb, &FileObject->FileName); - if (Fcb == NULL) - { - /* Not found, bail out with error. */ - DPRINT("No pipe found!\n"); - KeUnlockMutex(&Vcb->PipeListLock); - Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_OBJECT_NAME_NOT_FOUND; - } - - KeUnlockMutex(&Vcb->PipeListLock); - - /* - * Acquire the lock for CCB lists. From now on no modifications to the - * CCB lists are allowed, because it can cause various misconsistencies. - */ - KeLockMutex(&Fcb->CcbListLock); - - /* - * Step 2. Create the client CCB. - */ - ClientCcb = NpfsAllocateCcb(CCB_PIPE, Fcb); - if (ClientCcb == NULL) - { - DPRINT("No memory!\n"); - KeUnlockMutex(&Fcb->CcbListLock); - NpfsDereferenceFcb(Fcb); - Irp->IoStatus.Status = STATUS_NO_MEMORY; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NO_MEMORY; - } - - ClientCcb->FileObject = FileObject; - ClientCcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread; - ClientCcb->PipeEnd = FILE_PIPE_CLIENT_END; -#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS - ClientCcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE; -#else - ClientCcb->PipeState = FILE_PIPE_DISCONNECTED_STATE; -#endif - InitializeListHead(&ClientCcb->ReadRequestListHead); - - DPRINT("CCB: %p\n", ClientCcb); - - /* Initialize data list. */ - if (Fcb->OutboundQuota) - { - ClientCcb->Data = ExAllocatePoolWithTag(PagedPool, - Fcb->OutboundQuota, - TAG_NPFS_CCB_DATA); - if (ClientCcb->Data == NULL) + if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) && + (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) && + !(RelatedFileObject)) { - DPRINT("No memory!\n"); - NpfsDereferenceCcb(ClientCcb); - KeUnlockMutex(&Fcb->CcbListLock); - NpfsDereferenceFcb(Fcb); - Irp->IoStatus.Status = STATUS_NO_MEMORY; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NO_MEMORY; + Irp->IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb, + FileObject, + DesiredAccess, + &DeferredList); + goto Quickie; + } + } + else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB)) + { + Irp->IoStatus = NpOpenNamedPipeFileSystem(FileObject, + DesiredAccess); + goto Quickie; + } + else if (Type == NPFS_NTC_ROOT_DCB) + { + Irp->IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb, + FileObject, + DesiredAccess, + &DeferredList); + goto Quickie; + } + + // Status = NpTranslateAlias(&FileName);; // ignore this for now + // if (!NT_SUCCESS(Status)) goto Quickie; + if (RelatedFileObject) + { + if (Type == NPFS_NTC_ROOT_DCB) + { + Dcb = (PNP_DCB)Ccb; + Irp->IoStatus.Status = NpFindRelativePrefix(Dcb, + &FileName, + 1, + &Prefix, + &Fcb); + if (!NT_SUCCESS(Irp->IoStatus.Status)) + { + goto Quickie; + } + } + else if ((Type != NPFS_NTC_CCB) || (FileName.Length)) + { + Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID; + goto Quickie; + } + else + { + Prefix.Length = 0; } } else { - ClientCcb->Data = NULL; - } - - ClientCcb->ReadPtr = ClientCcb->Data; - ClientCcb->WritePtr = ClientCcb->Data; - ClientCcb->ReadDataAvailable = 0; - ClientCcb->WriteQuotaAvailable = Fcb->OutboundQuota; - ClientCcb->MaxDataLength = Fcb->OutboundQuota; - ExInitializeFastMutex(&ClientCcb->DataListLock); - KeInitializeEvent(&ClientCcb->ConnectEvent, SynchronizationEvent, FALSE); - KeInitializeEvent(&ClientCcb->ReadEvent, NotificationEvent, FALSE); - KeInitializeEvent(&ClientCcb->WriteEvent, NotificationEvent, FALSE); - - - /* - * Step 3. Search for listening server CCB. - */ -#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS - if (!SpecialAccess) - { -#endif - /* - * WARNING: Point of no return! Once we get the server CCB it's - * possible that we completed a wait request and so we have to - * complete even this request. - */ - - ServerCcb = NpfsFindListeningServerInstance(Fcb); - if (ServerCcb == NULL) + if ((FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR)) || + (FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR)) { - PLIST_ENTRY CurrentEntry; - PNPFS_CCB Ccb; - - /* - * If no waiting server CCB was found then try to pick - * one of the listing server CCB on the pipe. - */ - - CurrentEntry = Fcb->ServerCcbListHead.Flink; - while (CurrentEntry != &Fcb->ServerCcbListHead) - { - Ccb = CONTAINING_RECORD(CurrentEntry, NPFS_CCB, CcbListEntry); - if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE) - { - ServerCcb = Ccb; - break; - } - CurrentEntry = CurrentEntry->Flink; - } - - /* - * No one is listening to me?! I'm so lonely... :( - */ - - if (ServerCcb == NULL) - { - /* Not found, bail out with error for FILE_OPEN requests. */ - DPRINT("No listening server CCB found!\n"); - if (ClientCcb->Data) - { - ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA); - } - - NpfsDereferenceCcb(ClientCcb); - KeUnlockMutex(&Fcb->CcbListLock); - NpfsDereferenceFcb(Fcb); - Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_OBJECT_NAME_NOT_FOUND; - } - } - else - { - /* Signal the server thread and remove it from the waiter list */ - /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */ - NpfsSignalAndRemoveListeningServerInstance(Fcb, ServerCcb); - } -#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS - } - else if (IsListEmpty(&Fcb->ServerCcbListHead)) - { - DPRINT("No server fcb found!\n"); - - if (ClientCcb->Data) - { - ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA); + Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID; + goto Quickie; } - NpfsDereferenceCcb(ClientCcb); - KeUnlockMutex(&Fcb->CcbListLock); - NpfsDereferenceFcb(Fcb); - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_UNSUCCESSFUL; + Fcb = NpFindPrefix(&FileName, TRUE, &Prefix); } -#endif - /* - * Step 4. Add the client CCB to a list and connect it if possible. - */ - - /* Add the client CCB to the pipe CCB list. */ - InsertTailList(&Fcb->ClientCcbListHead, &ClientCcb->CcbListEntry); - - /* Connect to listening server side */ - if (ServerCcb) + if (Prefix.Length) { - NpfsCcbSetOtherSide(ClientCcb, ServerCcb); - NpfsCcbSetOtherSide(ServerCcb, ClientCcb); - ClientCcb->PipeState = FILE_PIPE_CONNECTED_STATE; - ServerCcb->PipeState = FILE_PIPE_CONNECTED_STATE; - KeSetEvent(&ServerCcb->ConnectEvent, IO_NO_INCREMENT, FALSE); + Irp->IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ? + STATUS_OBJECT_NAME_NOT_FOUND : + STATUS_OBJECT_NAME_INVALID; + goto Quickie; } - KeUnlockMutex(&Fcb->CcbListLock); + if (Fcb->NodeType != NPFS_NTC_FCB) + { + Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID; + goto Quickie; + } - FileObject->FsContext = Fcb; - FileObject->FsContext2 = ClientCcb; - FileObject->Flags |= FO_NAMED_PIPE; + if (!Fcb->ServerOpenCount) + { + Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto Quickie; + } + + Irp->IoStatus = NpCreateClientEnd(Fcb, + FileObject, + DesiredAccess, + IoStack->Parameters.CreatePipe. + SecurityContext->SecurityQos, + IoStack->Parameters.CreatePipe. + SecurityContext->AccessState, + IoStack->Flags & + SL_FORCE_ACCESS_CHECK ? + UserMode : Irp->RequestorMode, + Irp->Tail.Overlay.Thread, + &DeferredList); + +Quickie: + ExReleaseResourceLite(&NpVcb->Lock); + NpCompleteDeferredIrps(&DeferredList); + FsRtlExitFileSystem(); - Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); - - DPRINT("Success!\n"); - - return STATUS_SUCCESS; + return Irp->IoStatus.Status; } +IO_STATUS_BLOCK +NTAPI +NpCreateExistingNamedPipe(IN PNP_FCB Fcb, + IN PFILE_OBJECT FileObject, + IN ACCESS_MASK DesiredAccess, + IN PACCESS_STATE AccessState, + IN KPROCESSOR_MODE PreviousMode, + IN ULONG Disposition, + IN ULONG ShareAccess, + IN PNAMED_PIPE_CREATE_PARAMETERS Parameters, + IN PEPROCESS Process, + OUT PLIST_ENTRY List) +{ + PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext; + IO_STATUS_BLOCK IoStatus; + UNICODE_STRING ObjectTypeName; + ACCESS_MASK GrantedAccess; + PNP_CCB Ccb; + PPRIVILEGE_SET Privileges; + USHORT NamedPipeConfiguration, CheckShareAccess; + BOOLEAN AccessGranted; + PAGED_CODE(); -NTSTATUS NTAPI -NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, - PIRP Irp) + Privileges = NULL; + + NamedPipeConfiguration = Fcb->NamedPipeConfiguration; + + SubjectSecurityContext = &AccessState->SubjectSecurityContext; + SeLockSubjectContext(SubjectSecurityContext); + + AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor, + SubjectSecurityContext, + TRUE, + DesiredAccess | 4, + 0, + &Privileges, + IoGetFileObjectGenericMapping(), + PreviousMode, + &GrantedAccess, + &IoStatus.Status); + + if (Privileges) + { + SeAppendPrivileges(AccessState, Privileges); + SeFreePrivileges(Privileges); + } + + if (AccessGranted) + { + AccessState->PreviouslyGrantedAccess |= GrantedAccess; + AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 0x2000000); + } + + ObjectTypeName.Buffer = L"NamedPipe"; + ObjectTypeName.Length = 18; + SeOpenObjectAuditAlarm(&ObjectTypeName, + NULL, + &FileObject->FileName, + Fcb->SecurityDescriptor, + AccessState, + FALSE, + AccessGranted, + PreviousMode, + &AccessState->GenerateOnClose); + + SeUnlockSubjectContext(SubjectSecurityContext); + if (!AccessGranted) return IoStatus; + + if (Fcb->CurrentInstances >= Fcb->MaximumInstances) + { + IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE; + return IoStatus; + } + + if (Disposition == FILE_CREATE) + { + IoStatus.Status = STATUS_ACCESS_DENIED; + return IoStatus; + } + + CheckShareAccess = 0; + if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX) + { + CheckShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; + } + else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND) + { + CheckShareAccess = FILE_SHARE_READ; + } + else if (NamedPipeConfiguration == FILE_PIPE_INBOUND) + { + CheckShareAccess = FILE_SHARE_WRITE; + } + + if (CheckShareAccess != ShareAccess) + { + IoStatus.Status = STATUS_ACCESS_DENIED; + return IoStatus; + } + + IoStatus.Status = NpCreateCcb(Fcb, + FileObject, + FILE_PIPE_LISTENING_STATE, + Parameters->ReadMode & 0xFF, + Parameters->CompletionMode & 0xFF, + Parameters->InboundQuota, + Parameters->OutboundQuota, + &Ccb); + if (!NT_SUCCESS(IoStatus.Status)) return IoStatus; + + IoStatus.Status = NpCancelWaiter(&NpVcb->WaitQueue, + &Fcb->FullName, + FALSE, + List); + if (!NT_SUCCESS(IoStatus.Status)) + { + --Ccb->Fcb->CurrentInstances; + NpDeleteCcb(Ccb, List); + return IoStatus; + } + + NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE); + Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject; + NpCheckForNotify(Fcb->ParentDcb, 0, List); + + IoStatus.Status = STATUS_SUCCESS; + IoStatus.Information = 1; + return IoStatus; +} + +NTSTATUS +NTAPI +NpCreateNewNamedPipe(IN PNP_DCB Dcb, + IN PFILE_OBJECT FileObject, + IN UNICODE_STRING PipeName, + IN ACCESS_MASK DesiredAccess, + IN PACCESS_STATE AccessState, + IN USHORT Disposition, + IN USHORT ShareAccess, + IN PNAMED_PIPE_CREATE_PARAMETERS Parameters, + IN PEPROCESS Process, + IN PLIST_ENTRY List, + IN PIO_STATUS_BLOCK IoStatus) +{ + NTSTATUS Status; + USHORT NamedPipeConfiguration; + PSECURITY_SUBJECT_CONTEXT SecurityContext; + PSECURITY_DESCRIPTOR SecurityDescriptor, CachedSecurityDescriptor; + PNP_CCB Ccb; + PNP_FCB Fcb; + PAGED_CODE(); + + if (!(Parameters->TimeoutSpecified) || + !(Parameters->MaximumInstances) || + (Parameters->DefaultTimeout.HighPart >= 0)) + { + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + if (Disposition == FILE_OPEN) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto Quickie; + } + + if (ShareAccess == (FILE_SHARE_READ | FILE_SHARE_WRITE)) + { + NamedPipeConfiguration = FILE_PIPE_FULL_DUPLEX; + } + else if (ShareAccess == FILE_SHARE_READ) + { + NamedPipeConfiguration = FILE_PIPE_OUTBOUND; + } + else if (ShareAccess == FILE_SHARE_WRITE) + { + NamedPipeConfiguration = FILE_PIPE_INBOUND; + } + else + { + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + if (!Parameters->NamedPipeType && Parameters->ReadMode == 1) + { + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + Status = NpCreateFcb(Dcb, + &PipeName, + Parameters->MaximumInstances, + Parameters->DefaultTimeout, + NamedPipeConfiguration, + Parameters->NamedPipeType & 0xFFFF, + &Fcb); + if (!NT_SUCCESS(Status)) goto Quickie; + + Status = NpCreateCcb(Fcb, + FileObject, + FILE_PIPE_LISTENING_STATE, + Parameters->ReadMode & 0xFF, + Parameters->CompletionMode & 0xFF, + Parameters->InboundQuota, + Parameters->OutboundQuota, + &Ccb); + if (!NT_SUCCESS(Status)) + { + NpDeleteFcb(Fcb, List); + goto Quickie; + } + + SecurityContext = &AccessState->SubjectSecurityContext; + SeLockSubjectContext(&AccessState->SubjectSecurityContext); + + Status = SeAssignSecurity(0, + AccessState->SecurityDescriptor, + &SecurityDescriptor, + 0, + SecurityContext, + IoGetFileObjectGenericMapping(), + PagedPool); + SeUnlockSubjectContext(SecurityContext); + if (!NT_SUCCESS(Status)) + { + NpDeleteCcb(Ccb, List); + NpDeleteFcb(Fcb, List); + goto Quickie; + } + + Status = ObLogSecurityDescriptor(SecurityDescriptor, + &CachedSecurityDescriptor, + 1); + ExFreePool(SecurityDescriptor); + + if (!NT_SUCCESS(Status)) + { + NpDeleteCcb(Ccb, List); + NpDeleteFcb(Fcb, List); + goto Quickie; + } + + Fcb->SecurityDescriptor = CachedSecurityDescriptor; + + NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE); + Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject; + + NpCheckForNotify(Dcb, TRUE, List); + + IoStatus->Status = STATUS_SUCCESS; + IoStatus->Information = FILE_CREATED; + + return STATUS_SUCCESS; + +Quickie: + IoStatus->Information = 0; + IoStatus->Status = Status; + return Status; +} + +NTSTATUS +NTAPI +NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { PEXTENDED_IO_STACK_LOCATION IoStack; PFILE_OBJECT FileObject; - PNPFS_VCB Vcb; - PNPFS_FCB Fcb; - PNPFS_CCB Ccb; - ULONG Disposition; - ULONG ShareAccess; + PFILE_OBJECT RelatedFileObject; + USHORT Disposition, ShareAccess; + PEPROCESS Process; + LIST_ENTRY DeferredList; + UNICODE_STRING FileName; + PNP_FCB Fcb; + UNICODE_STRING Prefix; PNAMED_PIPE_CREATE_PARAMETERS Parameters; + IO_STATUS_BLOCK IoStatus; - DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + InitializeListHead(&DeferredList); + Process = IoGetRequestorProcess(Irp); - Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension; - IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp); + IoStack = (PEXTENDED_IO_STACK_LOCATION) IoGetCurrentIrpStackLocation(Irp); FileObject = IoStack->FileObject; - DPRINT("FileObject %p\n", FileObject); - DPRINT("Pipe name %wZ\n", &FileObject->FileName); + RelatedFileObject = FileObject->RelatedFileObject; Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF; - ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess; + ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF; Parameters = IoStack->Parameters.CreatePipe.Parameters; - Irp->IoStatus.Information = 0; + FileName.Buffer = FileObject->FileName.Buffer; + FileName.Length = FileObject->FileName.Length; + FileName.MaximumLength = FileObject->FileName.MaximumLength; - if ((Disposition == FILE_OVERWRITE) || - (Disposition == FILE_OVERWRITE_IF) || - !(ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE)) || - (ShareAccess & ~(FILE_SHARE_READ|FILE_SHARE_WRITE))) + IoStatus.Status = STATUS_SUCCESS; + IoStatus.Information = 0; + + FsRtlEnterFileSystem(); + NpAcquireExclusiveVcb(); + + if (RelatedFileObject) { - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_INVALID_PARAMETER; - } - - KeLockMutex(&Vcb->PipeListLock); - - /* - * First search for existing Pipe with the same name. - */ - Fcb = NpfsFindPipe(Vcb, &FileObject->FileName); - if (Fcb != NULL) - { - /* - * Found Pipe with the same name. Check if we are - * allowed to use it. - */ - KeUnlockMutex(&Vcb->PipeListLock); - - if (Fcb->CurrentInstances >= Fcb->MaximumInstances) + Fcb = (PNP_FCB)((ULONG_PTR)RelatedFileObject->FsContext & ~1); + if (!(Fcb) || + (Fcb->NodeType != NPFS_NTC_ROOT_DCB) || + (FileName.Length < sizeof(WCHAR)) || + (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) { - DPRINT("Out of instances.\n"); - NpfsDereferenceFcb(Fcb); - Irp->IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_INSTANCE_NOT_AVAILABLE; + IoStatus.Status = STATUS_OBJECT_NAME_INVALID; + goto Quickie; } - if (Disposition == FILE_CREATE || - Fcb->MaximumInstances != Parameters->MaximumInstances || - Fcb->TimeOut.QuadPart != Parameters->DefaultTimeout.QuadPart || - Fcb->PipeType != Parameters->NamedPipeType) + IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext, + &FileName, + TRUE, + &Prefix, + &Fcb); + if (!NT_SUCCESS(IoStatus.Status)) { - DPRINT("Asked for invalid pipe mode.\n"); - NpfsDereferenceFcb(Fcb); - Irp->IoStatus.Status = STATUS_ACCESS_DENIED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_ACCESS_DENIED; + goto Quickie; } } else { - Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_FCB), TAG_NPFS_FCB); - if (Fcb == NULL) + if (FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR) || + FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR) { - KeUnlockMutex(&Vcb->PipeListLock); - Irp->IoStatus.Status = STATUS_NO_MEMORY; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NO_MEMORY; + IoStatus.Status = STATUS_OBJECT_NAME_INVALID; + goto Quickie; } - Fcb->Type = FCB_PIPE; - Fcb->Vcb = Vcb; - Fcb->RefCount = 1; - Fcb->PipeName.Length = FileObject->FileName.Length; - Fcb->PipeName.MaximumLength = Fcb->PipeName.Length + sizeof(UNICODE_NULL); - Fcb->PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool, - Fcb->PipeName.MaximumLength, - TAG_NPFS_NAMEBLOCK); - if (Fcb->PipeName.Buffer == NULL) + Fcb = NpFindPrefix(&FileName, TRUE, &Prefix); + } + + if (Prefix.Length) + { + if (Fcb->NodeType == NPFS_NTC_ROOT_DCB) { - KeUnlockMutex(&Vcb->PipeListLock); - ExFreePoolWithTag(Fcb, TAG_NPFS_FCB); - Irp->IoStatus.Status = STATUS_NO_MEMORY; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NO_MEMORY; - } - - RtlCopyUnicodeString(&Fcb->PipeName, &FileObject->FileName); - - InitializeListHead(&Fcb->ServerCcbListHead); - InitializeListHead(&Fcb->ClientCcbListHead); - InitializeListHead(&Fcb->WaiterListHead); - KeInitializeMutex(&Fcb->CcbListLock, 0); - - Fcb->PipeType = Parameters->NamedPipeType; - Fcb->ServerReadMode = Parameters->ReadMode; - /* MSDN documentation reads that clients always start off in byte mode */ - Fcb->ClientReadMode = FILE_PIPE_BYTE_STREAM_MODE; - - Fcb->CompletionMode = Parameters->CompletionMode; - switch (ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE)) - { - case FILE_SHARE_READ: - Fcb->PipeConfiguration = FILE_PIPE_OUTBOUND; - break; - case FILE_SHARE_WRITE: - Fcb->PipeConfiguration = FILE_PIPE_INBOUND; - break; - case FILE_SHARE_READ|FILE_SHARE_WRITE: - Fcb->PipeConfiguration = FILE_PIPE_FULL_DUPLEX; - break; - } - Fcb->MaximumInstances = Parameters->MaximumInstances; - Fcb->CurrentInstances = 0; - Fcb->TimeOut = Parameters->DefaultTimeout; - if (!(Fcb->PipeConfiguration & FILE_PIPE_OUTBOUND) || - Fcb->PipeConfiguration & FILE_PIPE_FULL_DUPLEX) - { - if (Parameters->InboundQuota == 0) - { - Fcb->InboundQuota = Vcb->DefaultQuota; - } - else - { - Fcb->InboundQuota = PAGE_ROUND_UP(Parameters->InboundQuota); - if (Fcb->InboundQuota < Vcb->MinQuota) - { - Fcb->InboundQuota = Vcb->MinQuota; - } - else if (Fcb->InboundQuota > Vcb->MaxQuota) - { - Fcb->InboundQuota = Vcb->MaxQuota; - } - } + IoStatus.Status = NpCreateNewNamedPipe((PNP_DCB)Fcb, + FileObject, + FileName, + IoStack->Parameters.CreatePipe. + SecurityContext->DesiredAccess, + IoStack->Parameters.CreatePipe. + SecurityContext->AccessState, + Disposition, + ShareAccess, + Parameters, + Process, + &DeferredList, + &IoStatus); + goto Quickie; } else { - Fcb->InboundQuota = 0; - } - - if (Fcb->PipeConfiguration & (FILE_PIPE_FULL_DUPLEX|FILE_PIPE_OUTBOUND)) - { - if (Parameters->OutboundQuota == 0) - { - Fcb->OutboundQuota = Vcb->DefaultQuota; - } - else - { - Fcb->OutboundQuota = PAGE_ROUND_UP(Parameters->OutboundQuota); - if (Fcb->OutboundQuota < Vcb->MinQuota) - { - Fcb->OutboundQuota = Vcb->MinQuota; - } - else if (Fcb->OutboundQuota > Vcb->MaxQuota) - { - Fcb->OutboundQuota = Vcb->MaxQuota; - } - } - } - else - { - Fcb->OutboundQuota = 0; - } - - InsertTailList(&Vcb->PipeListHead, &Fcb->PipeListEntry); - KeUnlockMutex(&Vcb->PipeListLock); - } - - Ccb = NpfsAllocateCcb(CCB_PIPE, Fcb); - if (Ccb == NULL) - { - NpfsDereferenceFcb(Fcb); - Irp->IoStatus.Status = STATUS_NO_MEMORY; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NO_MEMORY; - } - - Ccb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread; - - if (Fcb->InboundQuota) - { - Ccb->Data = ExAllocatePoolWithTag(PagedPool, - Fcb->InboundQuota, - TAG_NPFS_CCB_DATA); - if (Ccb->Data == NULL) - { - NpfsDereferenceCcb(Ccb); - NpfsDereferenceFcb(Fcb); - - Irp->IoStatus.Status = STATUS_NO_MEMORY; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NO_MEMORY; + IoStatus.Status = STATUS_OBJECT_NAME_INVALID; + goto Quickie; } } - else + + if (Fcb->NodeType != NPFS_NTC_FCB) { - Ccb->Data = NULL; + IoStatus.Status = STATUS_OBJECT_NAME_INVALID; + goto Quickie; } - Ccb->ReadPtr = Ccb->Data; - Ccb->WritePtr = Ccb->Data; - Ccb->ReadDataAvailable = 0; - Ccb->WriteQuotaAvailable = Fcb->InboundQuota; - Ccb->MaxDataLength = Fcb->InboundQuota; - InitializeListHead(&Ccb->ReadRequestListHead); - ExInitializeFastMutex(&Ccb->DataListLock); + IoStatus = NpCreateExistingNamedPipe(Fcb, + FileObject, + IoStack->Parameters.CreatePipe. + SecurityContext->DesiredAccess, + IoStack->Parameters.CreatePipe. + SecurityContext->AccessState, + IoStack->Flags & + SL_FORCE_ACCESS_CHECK ? + UserMode : Irp->RequestorMode, + Disposition, + ShareAccess, + Parameters, + Process, + &DeferredList); - Fcb->CurrentInstances++; +Quickie: + NpReleaseVcb(); + NpCompleteDeferredIrps(&DeferredList); + FsRtlExitFileSystem(); - Ccb->Fcb = Fcb; - Ccb->FileObject = FileObject; - Ccb->PipeEnd = FILE_PIPE_SERVER_END; - Ccb->PipeState = FILE_PIPE_LISTENING_STATE; - - DPRINT("CCB: %p\n", Ccb); - - KeInitializeEvent(&Ccb->ConnectEvent, SynchronizationEvent, FALSE); - KeInitializeEvent(&Ccb->ReadEvent, NotificationEvent, FALSE); - KeInitializeEvent(&Ccb->WriteEvent, NotificationEvent, FALSE); - - KeLockMutex(&Fcb->CcbListLock); - InsertTailList(&Fcb->ServerCcbListHead, &Ccb->CcbListEntry); - KeUnlockMutex(&Fcb->CcbListLock); - - FileObject->FsContext = Fcb; - FileObject->FsContext2 = Ccb; - FileObject->Flags |= FO_NAMED_PIPE; - - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - DPRINT("Success!\n"); - - return STATUS_SUCCESS; -} - - -NTSTATUS NTAPI -NpfsCleanup(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - //PNPFS_VCB Vcb; - PIO_STACK_LOCATION IoStack; - PFILE_OBJECT FileObject; - PNPFS_CCB Ccb, OtherSide; - PNPFS_FCB Fcb; - BOOLEAN Server; - - DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp); - - IoStack = IoGetCurrentIrpStackLocation(Irp); - //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension; - FileObject = IoStack->FileObject; - Ccb = FileObject->FsContext2; - - if (Ccb == NULL) - { - DPRINT("Success!\n"); - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - - if (Ccb->Type == CCB_DEVICE) - { - DPRINT("Cleanup the file system!\n"); - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - - if (Ccb->Type == CCB_DIRECTORY) - { - DPRINT("Cleanup the root directory!\n"); - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - - DPRINT("CCB %p\n", Ccb); - Fcb = Ccb->Fcb; - - DPRINT("Cleaning pipe %wZ\n", &Fcb->PipeName); - - KeLockMutex(&Fcb->CcbListLock); - - Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END); - - if (Server) - { - /* FIXME: Clean up existing connections here ?? */ - DPRINT("Server\n"); - } - else - { - DPRINT("Client\n"); - } - if ((Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) && (Ccb->OtherSide)) - { - OtherSide = Ccb->OtherSide; - ASSERT(OtherSide->OtherSide == Ccb); - - /* Lock the server first */ - if (Server) - { - ExAcquireFastMutex(&Ccb->DataListLock); - ExAcquireFastMutex(&OtherSide->DataListLock); - } - else - { - ExAcquireFastMutex(&OtherSide->DataListLock); - ExAcquireFastMutex(&Ccb->DataListLock); - } - - /* Unlink FCBs */ - NpfsCcbSetOtherSide(OtherSide, NULL); - NpfsCcbSetOtherSide(Ccb, NULL); - - /* - * Signaling the write event. If is possible that an other - * thread waits for an empty buffer. - */ - KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE); - KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE); - if (Server) - { - ExReleaseFastMutex(&OtherSide->DataListLock); - ExReleaseFastMutex(&Ccb->DataListLock); - } - else - { - ExReleaseFastMutex(&Ccb->DataListLock); - ExReleaseFastMutex(&OtherSide->DataListLock); - } - } - else if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE) - { - PLIST_ENTRY Entry; - PNPFS_WAITER_ENTRY WaitEntry = NULL; - BOOLEAN Complete = FALSE; - KIRQL oldIrql; - PIRP tmpIrp; - - Entry = Ccb->Fcb->WaiterListHead.Flink; - while (Entry != &Ccb->Fcb->WaiterListHead) - { - WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry); - if (WaitEntry->Ccb == Ccb) - { - RemoveEntryList(Entry); - tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext); - IoAcquireCancelSpinLock(&oldIrql); - Complete = (NULL != IoSetCancelRoutine(tmpIrp, NULL)); - IoReleaseCancelSpinLock(oldIrql); - if (Complete) - { - tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN; - tmpIrp->IoStatus.Information = 0; - IoCompleteRequest(tmpIrp, IO_NO_INCREMENT); - } - break; - } - Entry = Entry->Flink; - } - - } - Ccb->PipeState = FILE_PIPE_CLOSING_STATE; - - KeUnlockMutex(&Fcb->CcbListLock); - - ExAcquireFastMutex(&Ccb->DataListLock); - if (Ccb->Data) - { - ExFreePoolWithTag(Ccb->Data, TAG_NPFS_CCB_DATA); - Ccb->Data = NULL; - Ccb->ReadPtr = NULL; - Ccb->WritePtr = NULL; - } - ExReleaseFastMutex(&Ccb->DataListLock); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - DPRINT("Success!\n"); - - return STATUS_SUCCESS; -} - -NTSTATUS NTAPI -NpfsClose(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - PFILE_OBJECT FileObject; - //PNPFS_VCB Vcb; - PNPFS_FCB Fcb; - PNPFS_CCB Ccb; - BOOLEAN Server; - - DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp); - - IoStack = IoGetCurrentIrpStackLocation(Irp); - //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension; - FileObject = IoStack->FileObject; - Ccb = FileObject->FsContext2; - - if (Ccb == NULL) - { - DPRINT("Success!\n"); - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - - if (Ccb->Type == CCB_DEVICE) - { - DPRINT("Closing the file system!\n"); - - NpfsDereferenceCcb(Ccb); - FileObject->FsContext = NULL; - FileObject->FsContext2 = NULL; - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - - if (Ccb->Type == CCB_DIRECTORY) - { - DPRINT("Closing the root directory!\n"); - - if (Ccb->u.Directory.SearchPattern.Buffer != NULL) - ExFreePoolWithTag(Ccb->u.Directory.SearchPattern.Buffer, - TAG_NPFS_NAMEBLOCK); - - NpfsDereferenceCcb(Ccb); - FileObject->FsContext = NULL; - FileObject->FsContext2 = NULL; - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; - } - - DPRINT("CCB %p\n", Ccb); - Fcb = Ccb->Fcb; - - DPRINT("Closing pipe %wZ\n", &Fcb->PipeName); - - KeLockMutex(&Fcb->CcbListLock); - - Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END); - - if (Server) - { - DPRINT("Server\n"); - Fcb->CurrentInstances--; - } - else - { - DPRINT("Client\n"); - } - - /* Disconnect the pipes */ - if (Ccb->OtherSide) - { - /* FIXME: Timo wants it rewritten */ - /*ASSERT(Ccb->OtherSide->OtherSide == Ccb);*/ - NpfsCcbSetOtherSide(Ccb->OtherSide, NULL); - NpfsCcbSetOtherSide(Ccb, NULL); - } - - ASSERT(Ccb->PipeState == FILE_PIPE_CLOSING_STATE); - - FileObject->FsContext2 = NULL; - - RemoveEntryList(&Ccb->CcbListEntry); - - NpfsDereferenceCcb(Ccb); - - KeUnlockMutex(&Fcb->CcbListLock); - - NpfsDereferenceFcb(Fcb); - FileObject->FsContext = NULL; - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - DPRINT("Success!\n"); - - return STATUS_SUCCESS; + Irp->IoStatus = IoStatus; + IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT); + return IoStatus.Status; } /* EOF */ diff --git a/reactos/drivers/filesystems/npfs_new/datasup.c b/reactos/drivers/filesystems/npfs/datasup.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/datasup.c rename to reactos/drivers/filesystems/npfs/datasup.c diff --git a/reactos/drivers/filesystems/npfs_new/fileinfo.c b/reactos/drivers/filesystems/npfs/fileinfo.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/fileinfo.c rename to reactos/drivers/filesystems/npfs/fileinfo.c diff --git a/reactos/drivers/filesystems/npfs_new/fileobsup.c b/reactos/drivers/filesystems/npfs/fileobsup.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/fileobsup.c rename to reactos/drivers/filesystems/npfs/fileobsup.c diff --git a/reactos/drivers/filesystems/npfs_new/flushbuf.c b/reactos/drivers/filesystems/npfs/flushbuf.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/flushbuf.c rename to reactos/drivers/filesystems/npfs/flushbuf.c diff --git a/reactos/drivers/filesystems/npfs/fsctrl.c b/reactos/drivers/filesystems/npfs/fsctrl.c index ce68432c920..10288a7d0d5 100644 --- a/reactos/drivers/filesystems/npfs/fsctrl.c +++ b/reactos/drivers/filesystems/npfs/fsctrl.c @@ -1,810 +1,741 @@ /* -* COPYRIGHT: See COPYING in the top level directory -* PROJECT: ReactOS kernel -* FILE: drivers/filesystems/npfs/fsctrl.c -* PURPOSE: Named pipe filesystem -* PROGRAMMER: David Welch -* Eric Kohl -* Michael Martin -*/ + * PROJECT: ReactOS Named Pipe FileSystem + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/filesystems/npfs/fsctrl.c + * PURPOSE: Named Pipe FileSystem I/O Controls + * PROGRAMMERS: ReactOS Portable Systems Group + */ -/* INCLUDES ******************************************************************/ +/* INCLUDES *******************************************************************/ #include "npfs.h" -#define NDEBUG -#include +// File ID number for NPFS bugchecking support +#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_FSCTRL) -//#define USING_PROPER_NPFS_WAIT_SEMANTICS +/* GLOBALS ********************************************************************/ -/* FUNCTIONS *****************************************************************/ +IO_STATUS_BLOCK NpUserIoStatusBlock; -static DRIVER_CANCEL NpfsListeningCancelRoutine; -static VOID NTAPI -NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) +/* FUNCTIONS ******************************************************************/ + +NTSTATUS +NTAPI +NpInternalTransceive(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PLIST_ENTRY List) { - PNPFS_WAITER_ENTRY Waiter; - - UNREFERENCED_PARAMETER(DeviceObject); - - Waiter = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext; - - DPRINT("NpfsListeningCancelRoutine() called for <%wZ>\n", - &Waiter->Ccb->Fcb->PipeName); - - IoReleaseCancelSpinLock(Irp->CancelIrql); - - - KeLockMutex(&Waiter->Ccb->Fcb->CcbListLock); - RemoveEntryList(&Waiter->Entry); - KeUnlockMutex(&Waiter->Ccb->Fcb->CcbListLock); - - Irp->IoStatus.Status = STATUS_CANCELLED; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } - -static NTSTATUS -NpfsAddListeningServerInstance(PIRP Irp, - PNPFS_CCB Ccb) +NTSTATUS +NTAPI +NpInternalRead(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN BOOLEAN Overflow, + IN PLIST_ENTRY List) { - PNPFS_WAITER_ENTRY Entry; - KIRQL oldIrql; - - Entry = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext; - - Entry->Ccb = Ccb; - - KeLockMutex(&Ccb->Fcb->CcbListLock); - - IoAcquireCancelSpinLock(&oldIrql); - if (!Irp->Cancel) - { - Ccb->PipeState = FILE_PIPE_LISTENING_STATE; - IoMarkIrpPending(Irp); - InsertTailList(&Ccb->Fcb->WaiterListHead, &Entry->Entry); - (void)IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine); - IoReleaseCancelSpinLock(oldIrql); - KeUnlockMutex(&Ccb->Fcb->CcbListLock); - return STATUS_PENDING; - } - IoReleaseCancelSpinLock(oldIrql); - - RemoveEntryList(&Entry->Entry); - - Irp->IoStatus.Status = STATUS_CANCELLED; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - KeUnlockMutex(&Ccb->Fcb->CcbListLock); - - return STATUS_CANCELLED; + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; } - -static NTSTATUS -NpfsConnectPipe(PIRP Irp, - PNPFS_CCB Ccb) +NTSTATUS +NTAPI +NpInternalWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PLIST_ENTRY List) { + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NpAssignEvent(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NpQueryEvent(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +NpImpersonate(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + ULONG NamedPipeEnd; + PNP_CCB Ccb; + NTSTATUS Status; + NODE_TYPE_CODE NodeTypeCode; PIO_STACK_LOCATION IoStack; - PFILE_OBJECT FileObject; - ULONG Flags; - PLIST_ENTRY current_entry; - PNPFS_FCB Fcb; - PNPFS_CCB ClientCcb; - NTSTATUS Status; - KPROCESSOR_MODE WaitMode; + PAGED_CODE(); - DPRINT("NpfsConnectPipe()\n"); - - /* Fail, if the CCB is not a pipe CCB */ - if (Ccb->Type != CCB_PIPE) - { - DPRINT("Not a pipe\n"); - return STATUS_ILLEGAL_FUNCTION; - } - - /* Fail, if the CCB is not a server end CCB */ - if (Ccb->PipeEnd != FILE_PIPE_SERVER_END) - { - DPRINT("Not the server end\n"); - return STATUS_ILLEGAL_FUNCTION; - } - - if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) - { - KeResetEvent(&Ccb->ConnectEvent); - return STATUS_PIPE_CONNECTED; - } - - if (Ccb->PipeState == FILE_PIPE_CLOSING_STATE) - return STATUS_PIPE_CLOSING; - - DPRINT("Waiting for connection...\n"); - - Fcb = Ccb->Fcb; IoStack = IoGetCurrentIrpStackLocation(Irp); - FileObject = IoStack->FileObject; - Flags = FileObject->Flags; - WaitMode = Irp->RequestorMode; - /* search for a listening client fcb */ - KeLockMutex(&Fcb->CcbListLock); - - current_entry = Fcb->ClientCcbListHead.Flink; - while (current_entry != &Fcb->ClientCcbListHead) + NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); + if (NodeTypeCode == NPFS_NTC_CCB) { - ClientCcb = CONTAINING_RECORD(current_entry, - NPFS_CCB, - CcbListEntry); - - if (ClientCcb->PipeState == 0) + if (NamedPipeEnd == FILE_PIPE_SERVER_END) { - /* found a passive (waiting) client CCB */ - DPRINT("Passive (waiting) client CCB found -- wake the client\n"); - KeSetEvent(&ClientCcb->ConnectEvent, IO_NO_INCREMENT, FALSE); - break; - } - -#if 0 - if (ClientCcb->PipeState == FILE_PIPE_LISTENING_STATE) - { - /* found a listening client CCB */ - DPRINT("Listening client CCB found -- connecting\n"); - - /* connect client and server CCBs */ - Ccb->OtherSide = ClientCcb; - ClientCcb->OtherSide = Ccb; - - /* set connected state */ - Ccb->PipeState = FILE_PIPE_CONNECTED_STATE; - ClientCcb->PipeState = FILE_PIPE_CONNECTED_STATE; - - KeUnlockMutex(&Fcb->CcbListLock); - - /* FIXME: create and initialize data queues */ - - /* signal client's connect event */ - DPRINT("Setting the ConnectEvent for %x\n", ClientCcb); - KeSetEvent(&ClientCcb->ConnectEvent, IO_NO_INCREMENT, FALSE); - - return STATUS_PIPE_CONNECTED; - } -#endif - - current_entry = current_entry->Flink; - } - - /* no listening client fcb found */ - DPRINT("No listening client fcb found -- waiting for client\n"); - - Status = NpfsAddListeningServerInstance(Irp, Ccb); - - KeUnlockMutex(&Fcb->CcbListLock); - - if ((Status == STATUS_PENDING) && (Flags & FO_SYNCHRONOUS_IO)) - { - KeWaitForSingleObject(&Ccb->ConnectEvent, - UserRequest, - WaitMode, - (Flags & FO_ALERTABLE_IO) != 0, - NULL); - } - - DPRINT("NpfsConnectPipe() done (Status %lx)\n", Status); - - return Status; -} - - -static NTSTATUS -NpfsDisconnectPipe(PNPFS_CCB Ccb) -{ - NTSTATUS Status; - PNPFS_FCB Fcb; - PNPFS_CCB OtherSide; - BOOLEAN Server; - - DPRINT("NpfsDisconnectPipe()\n"); - - /* Fail, if the CCB is not a pipe CCB */ - if (Ccb->Type != CCB_PIPE) - { - DPRINT("Not a pipe\n"); - return STATUS_ILLEGAL_FUNCTION; - } - - /* Fail, if the CCB is not a server end CCB */ - if (Ccb->PipeEnd != FILE_PIPE_SERVER_END) - { - DPRINT("Not the server end\n"); - return STATUS_ILLEGAL_FUNCTION; - } - - Fcb = Ccb->Fcb; - KeLockMutex(&Fcb->CcbListLock); - - if (Ccb->PipeState == FILE_PIPE_DISCONNECTED_STATE) - { - DPRINT("Pipe is already disconnected\n"); - Status = STATUS_PIPE_DISCONNECTED; - } - else if ((!Ccb->OtherSide) && (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)) - { - ExAcquireFastMutex(&Ccb->DataListLock); - Ccb->PipeState = FILE_PIPE_DISCONNECTED_STATE; - ExReleaseFastMutex(&Ccb->DataListLock); - Status = STATUS_SUCCESS; - } - else if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) - { - Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END); - OtherSide = Ccb->OtherSide; - //Ccb->OtherSide = NULL; - Ccb->PipeState = FILE_PIPE_DISCONNECTED_STATE; - /* Lock the server first */ - if (Server) - { - ExAcquireFastMutex(&Ccb->DataListLock); - ExAcquireFastMutex(&OtherSide->DataListLock); + Status = NpImpersonateClientContext(Ccb); } else { - ExAcquireFastMutex(&OtherSide->DataListLock); - ExAcquireFastMutex(&Ccb->DataListLock); - } - OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE; - //OtherSide->OtherSide = NULL; - /* - * Signaling the write event. If is possible that an other - * thread waits for an empty buffer. - */ - KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE); - KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE); - if (Server) - { - ExReleaseFastMutex(&OtherSide->DataListLock); - ExReleaseFastMutex(&Ccb->DataListLock); - } - else - { - ExReleaseFastMutex(&Ccb->DataListLock); - ExReleaseFastMutex(&OtherSide->DataListLock); - } - Status = STATUS_SUCCESS; - } - else if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE) - { - PLIST_ENTRY Entry; - PNPFS_WAITER_ENTRY WaitEntry = NULL; - BOOLEAN Complete = FALSE; - PIRP Irp = NULL; - - Entry = Ccb->Fcb->WaiterListHead.Flink; - while (Entry != &Ccb->Fcb->WaiterListHead) - { - WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry); - if (WaitEntry->Ccb == Ccb) - { - RemoveEntryList(Entry); - Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DriverContext); - Complete = (NULL != IoSetCancelRoutine(Irp, NULL)); - break; - } - Entry = Entry->Flink; - } - - if (Irp) - { - if (Complete) - { - Irp->IoStatus.Status = STATUS_PIPE_BROKEN; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } - } - Ccb->PipeState = FILE_PIPE_DISCONNECTED_STATE; - Status = STATUS_SUCCESS; - } - else if (Ccb->PipeState == FILE_PIPE_CLOSING_STATE) - { - Status = STATUS_PIPE_CLOSING; - } - else - { - Status = STATUS_UNSUCCESSFUL; - } - KeUnlockMutex(&Fcb->CcbListLock); - return Status; -} - -static NTSTATUS -NpfsWaitPipe(PIRP Irp, - PNPFS_CCB Ccb) -{ - PLIST_ENTRY current_entry; - PNPFS_FCB Fcb; - PNPFS_CCB ServerCcb; - PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe; - PLARGE_INTEGER TimeOut; - NTSTATUS Status; - PEXTENDED_IO_STACK_LOCATION IoStack; - PFILE_OBJECT FileObject; - PNPFS_VCB Vcb; - - IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp); - ASSERT(IoStack); - FileObject = IoStack->FileObject; - ASSERT(FileObject); - - DPRINT("Waiting on Pipe %wZ\n", &FileObject->FileName); - - WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer; - - ASSERT(Ccb->Fcb); - ASSERT(Ccb->Fcb->Vcb); - - /* Get the VCB */ - Vcb = Ccb->Fcb->Vcb; - - /* Lock the pipe list */ - KeLockMutex(&Vcb->PipeListLock); - - /* File a pipe with the given name */ - Fcb = NpfsFindPipe(Vcb, - &FileObject->FileName); - - /* Unlock the pipe list */ - KeUnlockMutex(&Vcb->PipeListLock); - - /* Fail if not pipe was found */ - if (Fcb == NULL) - { - DPRINT("No pipe found!\n"); - return STATUS_OBJECT_NAME_NOT_FOUND; - } - - /* search for listening server */ - current_entry = Fcb->ServerCcbListHead.Flink; - while (current_entry != &Fcb->ServerCcbListHead) - { - ServerCcb = CONTAINING_RECORD(current_entry, - NPFS_CCB, - CcbListEntry); - - if (ServerCcb->PipeState == FILE_PIPE_LISTENING_STATE) - { - /* found a listening server CCB */ - DPRINT("Listening server CCB found -- connecting\n"); - NpfsDereferenceFcb(Fcb); - return STATUS_SUCCESS; - } - - current_entry = current_entry->Flink; - } - - /* No listening server fcb found, so wait for one */ - - /* If a timeout specified */ - if (WaitPipe->TimeoutSpecified) - { - /* NMPWAIT_USE_DEFAULT_WAIT = 0 */ - if (WaitPipe->Timeout.QuadPart == 0) - { - TimeOut = &Fcb->TimeOut; - } - else - { - TimeOut = &WaitPipe->Timeout; + Status = STATUS_ILLEGAL_FUNCTION; } } - else - { - /* Wait forever */ - TimeOut = NULL; - } - NpfsDereferenceFcb(Fcb); - - Status = KeWaitForSingleObject(&Ccb->ConnectEvent, - UserRequest, - Irp->RequestorMode, - (Ccb->FileObject->Flags & FO_ALERTABLE_IO) != 0, - TimeOut); - if ((Status == STATUS_USER_APC) || (Status == STATUS_KERNEL_APC) || (Status == STATUS_ALERTED)) - Status = STATUS_CANCELLED; - - DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status); return Status; } NTSTATUS -NpfsWaitPipe2(PIRP Irp, - PNPFS_CCB Ccb) +NTAPI +NpDisconnect(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PLIST_ENTRY List) { - PLIST_ENTRY current_entry; - PNPFS_FCB Fcb; - PNPFS_CCB ServerCcb; - PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe; - LARGE_INTEGER TimeOut; + ULONG NamedPipeEnd; + PNP_CCB Ccb; NTSTATUS Status; -#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS - PNPFS_VCB Vcb; - UNICODE_STRING PipeName; -#endif + NODE_TYPE_CODE NodeTypeCode; + PIO_STACK_LOCATION IoStack; + PAGED_CODE(); - DPRINT("NpfsWaitPipe\n"); + IoStack = IoGetCurrentIrpStackLocation(Irp); - WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer; - -#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS - /* Fail, if the CCB does not represent the root directory */ - if (Ccb->Type != CCB_DIRECTORY) - return STATUS_ILLEGAL_FUNCTION; - - /* Calculate the pipe name length and allocate the buffer */ - PipeName.Length = WaitPipe->NameLength + sizeof(WCHAR); - PipeName.MaximumLength = PipeName.Length + sizeof(WCHAR); - PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool, - PipeName.MaximumLength, - TAG_NPFS_NAMEBLOCK); - if (PipeName.Buffer == NULL) + NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); + if (NodeTypeCode == NPFS_NTC_CCB) { - DPRINT1("Could not allocate memory for the pipe name!\n"); - return STATUS_NO_MEMORY; - } - - /* Copy the pipe name into the buffer, prepend a backslash and append a 0 character */ - PipeName.Buffer[0] = L'\\'; - RtlCopyMemory(&PipeName.Buffer[1], - &WaitPipe->Name[0], - WaitPipe->NameLength); - PipeName.Buffer[PipeName.Length / sizeof(WCHAR)] = 0; - - DPRINT("Waiting for Pipe %wZ\n", &PipeName); - - /* Get the VCB */ - Vcb = Ccb->Fcb->Vcb; - - /* Lock the pipe list */ - KeLockMutex(&Vcb->PipeListLock); - - /* File a pipe with the given name */ - Fcb = NpfsFindPipe(Vcb, - &PipeName); - - /* Unlock the pipe list */ - KeUnlockMutex(&Vcb->PipeListLock); - - /* Release the pipe name buffer */ - ExFreePoolWithTag(PipeName.Buffer, TAG_NPFS_NAMEBLOCK); - - /* Fail if not pipe was found */ - if (Fcb == NULL) - { - DPRINT("No pipe found!\n"); - return STATUS_OBJECT_NAME_NOT_FOUND; - } - - DPRINT("Fcb %p\n", Fcb); -#else - Fcb = Ccb->Fcb; - - if (Ccb->PipeState != 0) - { - DPRINT("Pipe is not in passive (waiting) state!\n"); - return STATUS_UNSUCCESSFUL; - } -#endif - - /* search for listening server */ - current_entry = Fcb->ServerCcbListHead.Flink; - while (current_entry != &Fcb->ServerCcbListHead) - { - ServerCcb = CONTAINING_RECORD(current_entry, - NPFS_CCB, - CcbListEntry); - - if (ServerCcb->PipeState == FILE_PIPE_LISTENING_STATE) + if (NamedPipeEnd == FILE_PIPE_SERVER_END) { - /* found a listening server CCB */ - DPRINT("Listening server CCB found -- connecting\n"); -#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS - NpfsDereferenceFcb(Fcb); -#endif - return STATUS_SUCCESS; + ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE); + + Status = NpSetDisconnectedPipeState(Ccb, List); + + NpUninitializeSecurity(Ccb); + + ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); + } + else + { + Status = STATUS_ILLEGAL_FUNCTION; } - - current_entry = current_entry->Flink; } - - /* No listening server fcb found */ - - /* If no timeout specified, use the default one */ - if (WaitPipe->TimeoutSpecified) - TimeOut = WaitPipe->Timeout; else - TimeOut = Fcb->TimeOut; -#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS - NpfsDereferenceFcb(Fcb); -#endif - - /* Wait for one */ - Status = KeWaitForSingleObject(&Ccb->ConnectEvent, - UserRequest, - Irp->RequestorMode, - (Ccb->FileObject->Flags & FO_ALERTABLE_IO) != 0, - &TimeOut); - if ((Status == STATUS_USER_APC) || (Status == STATUS_KERNEL_APC) || (Status == STATUS_ALERTED)) - Status = STATUS_CANCELLED; - - DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status); + { + Status = STATUS_PIPE_DISCONNECTED; + } return Status; } - -/* -* FUNCTION: Return current state of a pipe -* ARGUMENTS: -* Irp = Pointer to I/O request packet -* IrpSp = Pointer to current stack location of Irp -* RETURNS: -* Status of operation -*/ - -/* -* FUNCTION: Peek at a pipe (get information about messages) -* ARGUMENTS: -* Irp = Pointer to I/O request packet -* IoStack = Pointer to current stack location of Irp -* RETURNS: -* Status of operation -*/ -static NTSTATUS -NpfsPeekPipe(PIRP Irp, - PIO_STACK_LOCATION IoStack) +NTSTATUS +NTAPI +NpListen(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PLIST_ENTRY List) { - ULONG OutputBufferLength; - ULONG ReturnLength = 0; - PFILE_PIPE_PEEK_BUFFER Reply; - //PNPFS_FCB Fcb; - PNPFS_CCB Ccb; + ULONG NamedPipeEnd; + PNP_CCB Ccb; NTSTATUS Status; - ULONG MessageCount = 0; - ULONG MessageLength; - ULONG ReadDataAvailable; - PVOID BufferPtr; + NODE_TYPE_CODE NodeTypeCode; + PIO_STACK_LOCATION IoStack; + PAGED_CODE(); - DPRINT("NpfsPeekPipe\n"); + IoStack = IoGetCurrentIrpStackLocation(Irp); - OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; - DPRINT("OutputBufferLength: %lu\n", OutputBufferLength); - - /* Validate parameters */ - if (OutputBufferLength < (ULONG)FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0])) + NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); + if (NodeTypeCode == NPFS_NTC_CCB) + { + if (NamedPipeEnd == FILE_PIPE_SERVER_END) + { + ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE); + + Status = NpSetListeningPipeState(Ccb, Irp, List); + + NpUninitializeSecurity(Ccb); + + ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); + } + else + { + Status = STATUS_ILLEGAL_FUNCTION; + } + } + else + { + Status = STATUS_ILLEGAL_FUNCTION; + } + + return Status; +} + +NTSTATUS +NTAPI +NpPeek(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PLIST_ENTRY List) +{ + PIO_STACK_LOCATION IoStack; + NODE_TYPE_CODE Type; + ULONG OutputLength; + ULONG NamedPipeEnd; + PNP_CCB Ccb; + PFILE_PIPE_PEEK_BUFFER PeekBuffer; + PNP_DATA_QUEUE DataQueue; + ULONG_PTR BytesPeeked; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + PNP_DATA_QUEUE_ENTRY DataEntry; + PAGED_CODE(); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + OutputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength; + Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); + + if (!Type) + { + return STATUS_PIPE_DISCONNECTED; + } + + if ((Type != NPFS_NTC_CCB) && + (OutputLength < FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data))) { - DPRINT1("Buffer too small\n"); return STATUS_INVALID_PARAMETER; } - Ccb = IoStack->FileObject->FsContext2; - Reply = Irp->AssociatedIrp.SystemBuffer; - //Fcb = Ccb->Fcb; - - - Reply->NamedPipeState = Ccb->PipeState; - - Reply->ReadDataAvailable = Ccb->ReadDataAvailable; - DPRINT("ReadDataAvailable: %lu\n", Ccb->ReadDataAvailable); - - ExAcquireFastMutex(&Ccb->DataListLock); - BufferPtr = Ccb->ReadPtr; - DPRINT("BufferPtr = %p\n", BufferPtr); - if (Ccb->Fcb->PipeType == FILE_PIPE_BYTE_STREAM_TYPE) + PeekBuffer = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer; + if (NamedPipeEnd != FILE_PIPE_CLIENT_END) { - DPRINT("Byte Stream Mode\n"); - Reply->MessageLength = Ccb->ReadDataAvailable; - DPRINT("Reply->MessageLength %lu\n", Reply->MessageLength); - MessageCount = 1; - - if (OutputBufferLength >= (ULONG)FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[Ccb->ReadDataAvailable])) + if (NamedPipeEnd != FILE_PIPE_SERVER_END) { - RtlCopyMemory(Reply->Data, BufferPtr, Ccb->ReadDataAvailable); - ReturnLength = Ccb->ReadDataAvailable; + NpBugCheck(NamedPipeEnd, 0, 0); + } + + DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; + } + else + { + DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; + } + + if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE) + { + if (Ccb->NamedPipeState != FILE_PIPE_CLOSING_STATE) + { + return STATUS_INVALID_PIPE_STATE; + } + + if (DataQueue->QueueState != WriteEntries) + { + return STATUS_PIPE_BROKEN; + } + } + + PeekBuffer->NamedPipeState = 0; + PeekBuffer->ReadDataAvailable = 0; + PeekBuffer->NumberOfMessages = 0; + PeekBuffer->MessageLength = 0; + PeekBuffer->NamedPipeState = Ccb->NamedPipeState; + BytesPeeked = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data); + + if (DataQueue->QueueState == WriteEntries) + { + DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink, + NP_DATA_QUEUE_ENTRY, + QueueEntry); + ASSERT((DataEntry->DataEntryType == Buffered) || (DataEntry->DataEntryType == Unbuffered)); + + PeekBuffer->ReadDataAvailable = DataQueue->BytesInQueue - DataQueue->ByteOffset; + if (Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE) + { + PeekBuffer->NumberOfMessages = DataQueue->EntriesInQueue; + PeekBuffer->MessageLength = DataEntry->DataSize - DataQueue->ByteOffset; + } + + if (OutputLength == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data)) + { + Status = PeekBuffer->ReadDataAvailable ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS; + } + else + { + IoStatus = NpReadDataQueue(DataQueue, + TRUE, + FALSE, + PeekBuffer->Data, + OutputLength - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data), + Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE, + Ccb, + List); + Status = IoStatus.Status; + BytesPeeked += IoStatus.Information; } } else { - DPRINT("Message Mode\n"); - ReadDataAvailable = Ccb->ReadDataAvailable; + Status = STATUS_SUCCESS; + } - if (ReadDataAvailable > 0) + Irp->IoStatus.Information = BytesPeeked; + return Status; +} + +NTSTATUS +NTAPI +NpCompleteTransceiveIrp(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) +{ + PAGED_CODE(); + + if (Irp->AssociatedIrp.SystemBuffer) + { + ExFreePool(Irp->AssociatedIrp.SystemBuffer); + } + + IoFreeIrp(Irp); + return STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS +NTAPI +NpTransceive(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PLIST_ENTRY List) +{ + PIO_STACK_LOCATION IoStack; + PVOID InBuffer, OutBuffer; + ULONG InLength, OutLength, BytesWritten; + NODE_TYPE_CODE NodeTypeCode; + PNP_CCB Ccb; + ULONG NamedPipeEnd; + PNP_NONPAGED_CCB NonPagedCcb; + PNP_DATA_QUEUE ReadQueue, WriteQueue; + PNP_EVENT_BUFFER EventBuffer; + NTSTATUS Status; + PIRP NewIrp; + PAGED_CODE(); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + InLength = IoStack->Parameters.FileSystemControl.InputBufferLength; + InBuffer = IoStack->Parameters.FileSystemControl.Type3InputBuffer; + OutLength = IoStack->Parameters.FileSystemControl.OutputBufferLength; + OutBuffer = Irp->UserBuffer; + + if (Irp->RequestorMode == UserMode) + { + _SEH2_TRY { - RtlCopyMemory(&Reply->MessageLength, - BufferPtr, - sizeof(Reply->MessageLength)); + ProbeForRead(InBuffer, InLength, sizeof(CHAR)); + ProbeForWrite(OutBuffer, OutLength, sizeof(CHAR)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; + } - while ((ReadDataAvailable > 0) && (BufferPtr < Ccb->WritePtr)) + NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); + if (NodeTypeCode != NPFS_NTC_CCB) + { + return STATUS_PIPE_DISCONNECTED; + } + + NonPagedCcb = Ccb->NonPagedCcb; + ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE); + + if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE) + { + Status = STATUS_INVALID_PIPE_STATE; + goto Quickie; + } + + if (NamedPipeEnd != FILE_PIPE_CLIENT_END) + { + if (NamedPipeEnd != FILE_PIPE_SERVER_END) + { + NpBugCheck(NamedPipeEnd, 0, 0); + } + ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; + WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; + } + else + { + ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; + WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; + } + + EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd]; + + if (Ccb->Fcb->NamedPipeConfiguration != FILE_PIPE_FULL_DUPLEX || + Ccb->ReadMode[NamedPipeEnd] != FILE_PIPE_MESSAGE_MODE) + { + Status = STATUS_INVALID_PIPE_STATE; + goto Quickie; + } + + if (ReadQueue->QueueState != Empty) + { + Status = STATUS_PIPE_BUSY; + goto Quickie; + } + + Status = NpWriteDataQueue(WriteQueue, + 1, + InBuffer, + InLength, + Ccb->Fcb->NamedPipeType, + &BytesWritten, + Ccb, + NamedPipeEnd, + Irp->Tail.Overlay.Thread, + List); + if (Status == STATUS_MORE_PROCESSING_REQUIRED) + { + ASSERT(WriteQueue->QueueState != ReadEntries); + NewIrp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + if (!NewIrp) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + IoSetCompletionRoutine(Irp, NpCompleteTransceiveIrp, NULL, TRUE, TRUE, TRUE); + + if (BytesWritten) + { + NewIrp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, + BytesWritten, + NPFS_WRITE_BLOCK_TAG); + if (!NewIrp->AssociatedIrp.SystemBuffer) { - RtlCopyMemory(&MessageLength, BufferPtr, sizeof(MessageLength)); - - ASSERT(MessageLength > 0); - - DPRINT("MessageLength = %lu\n", MessageLength); - ReadDataAvailable -= MessageLength; - MessageCount++; - - /* If its the first message, copy the Message if the size of buffer is large enough */ - if (MessageCount == 1) - { - if (OutputBufferLength >= (ULONG)FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[MessageLength])) - { - RtlCopyMemory(Reply->Data, - (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength)), - MessageLength); - ReturnLength = MessageLength; - } - } - - BufferPtr = (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength) + MessageLength); - DPRINT("BufferPtr = %p\n", BufferPtr); - DPRINT("ReadDataAvailable: %lu\n", ReadDataAvailable); + IoFreeIrp(NewIrp); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; } - if (ReadDataAvailable != 0) + _SEH2_TRY { - DPRINT1("Possible memory corruption.\n"); - ASSERT(FALSE); + RtlCopyMemory(NewIrp->AssociatedIrp.SystemBuffer, + (PVOID)((ULONG_PTR)InBuffer + InLength - BytesWritten), + BytesWritten); } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(goto Quickie); + } + _SEH2_END; + } + else + { + NewIrp->AssociatedIrp.SystemBuffer = NULL; + } + + IoStack = IoGetNextIrpStackLocation(NewIrp); + IoSetNextIrpStackLocation(NewIrp); + + NewIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread; + NewIrp->IoStatus.Information = BytesWritten; + + IoStack->Parameters.Read.Length = BytesWritten; + IoStack->MajorFunction = IRP_MJ_WRITE; + + if (BytesWritten > 0) NewIrp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO; + NewIrp->UserIosb = &NpUserIoStatusBlock; + + Status = NpAddDataQueueEntry(NamedPipeEnd, + Ccb, + WriteQueue, + WriteEntries, + Unbuffered, + BytesWritten, + NewIrp, + NULL, + 0); + if (Status != STATUS_PENDING) + { + NewIrp->IoStatus.Status = Status; + InsertTailList(List, &NewIrp->Tail.Overlay.ListEntry); } } - ExReleaseFastMutex(&Ccb->DataListLock); - Reply->NumberOfMessages = MessageCount; + if (!NT_SUCCESS(Status)) goto Quickie; + + if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); + ASSERT(ReadQueue->QueueState == Empty); + Status = NpAddDataQueueEntry(NamedPipeEnd, + Ccb, + ReadQueue, + ReadEntries, + Buffered, + OutLength, + Irp, + NULL, + 0); + if (NT_SUCCESS(Status)) + { + if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); + } - Irp->IoStatus.Information = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[ReturnLength]); - Irp->IoStatus.Status = STATUS_SUCCESS; +Quickie: + ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); + return Status; +} + +NTSTATUS +NTAPI +NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + ULONG InLength, NameLength; + UNICODE_STRING SourceString, Prefix; + ULONG NamedPipeEnd; + PNP_CCB Ccb; + PFILE_PIPE_WAIT_FOR_BUFFER Buffer; + NTSTATUS Status; + NODE_TYPE_CODE NodeTypeCode; + PLIST_ENTRY NextEntry; + PNP_FCB Fcb; + PWCHAR OriginalBuffer; + PAGED_CODE(); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + InLength = IoStack->Parameters.FileSystemControl.InputBufferLength; + + SourceString.Buffer = NULL; + + if (NpDecodeFileObject(IoStack->FileObject, + NULL, + &Ccb, + &NamedPipeEnd) != NPFS_NTC_ROOT_DCB) + { + Status = STATUS_ILLEGAL_FUNCTION; + goto Quickie; + } + + Buffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer; + if (InLength < sizeof(*Buffer)) + { + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + NameLength = Buffer->NameLength; + if ((NameLength > (0xFFFF - sizeof(UNICODE_NULL))) || + ((NameLength + FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name)) > InLength)) + { + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + SourceString.Length = (USHORT)NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR); + SourceString.Buffer = ExAllocatePoolWithTag(PagedPool, + SourceString.Length, + NPFS_WRITE_BLOCK_TAG); + if (!SourceString.Buffer) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + SourceString.Buffer[0] = OBJ_NAME_PATH_SEPARATOR; + RtlCopyMemory(&SourceString.Buffer[1], Buffer->Name, Buffer->NameLength); Status = STATUS_SUCCESS; + OriginalBuffer = SourceString.Buffer; + //Status = NpTranslateAlias(&SourceString); + if (!NT_SUCCESS(Status)) goto Quickie; - DPRINT("NpfsPeekPipe done\n"); + Fcb = NpFindPrefix(&SourceString, TRUE, &Prefix); + Fcb = (PNP_FCB)((ULONG_PTR)Fcb & ~1); + + NodeTypeCode = Fcb ? Fcb->NodeType : 0; + if (NodeTypeCode != NPFS_NTC_FCB) + { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto Quickie; + } + + for (NextEntry = Fcb->CcbList.Flink; + NextEntry != &Fcb->CcbList; + NextEntry = NextEntry->Flink) + { + Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry); + if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break; + } + + if (NextEntry != &Fcb->CcbList) + { + Status = STATUS_SUCCESS; + } + else + { + Status = NpAddWaiter(&NpVcb->WaitQueue, + Fcb->Timeout, + Irp, + OriginalBuffer == SourceString.Buffer ? + NULL : &SourceString); + } + +Quickie: + if (SourceString.Buffer) ExFreePool(SourceString.Buffer); + return Status; +} + +NTSTATUS +NTAPI +NpCommonFileSystemControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + ULONG Fsctl; + BOOLEAN Overflow = FALSE; + LIST_ENTRY DeferredList; + NTSTATUS Status; + PAGED_CODE(); + + InitializeListHead(&DeferredList); + Fsctl = IoGetCurrentIrpStackLocation(Irp)->Parameters.FileSystemControl.FsControlCode; + + switch (Fsctl) + { + case FSCTL_PIPE_PEEK: + NpAcquireExclusiveVcb(); + Status = NpPeek(DeviceObject, Irp, &DeferredList); + break; + + case FSCTL_PIPE_INTERNAL_WRITE: + NpAcquireSharedVcb(); + Status = NpInternalWrite(DeviceObject, Irp, &DeferredList); + break; + + case FSCTL_PIPE_TRANSCEIVE: + NpAcquireSharedVcb(); + Status = NpTransceive(DeviceObject, Irp, &DeferredList); + break; + + case FSCTL_PIPE_INTERNAL_TRANSCEIVE: + NpAcquireSharedVcb(); + Status = NpInternalTransceive(DeviceObject, Irp, &DeferredList); + break; + + case FSCTL_PIPE_INTERNAL_READ_OVFLOW: + Overflow = TRUE; + // on purpose + + case FSCTL_PIPE_INTERNAL_READ: + NpAcquireSharedVcb(); + Status = NpInternalRead(DeviceObject, Irp, Overflow, &DeferredList); + break; + + case FSCTL_PIPE_QUERY_CLIENT_PROCESS: + + NpAcquireSharedVcb(); + Status = NpQueryClientProcess(DeviceObject, Irp); + break; + + case FSCTL_PIPE_ASSIGN_EVENT: + + NpAcquireExclusiveVcb(); + Status = NpAssignEvent(DeviceObject, Irp); + break; + + case FSCTL_PIPE_DISCONNECT: + + NpAcquireExclusiveVcb(); + Status = NpDisconnect(DeviceObject, Irp, &DeferredList); + break; + + case FSCTL_PIPE_LISTEN: + + NpAcquireSharedVcb(); + Status = NpListen(DeviceObject, Irp, &DeferredList); + break; + + case FSCTL_PIPE_QUERY_EVENT: + + NpAcquireExclusiveVcb(); + Status = NpQueryEvent(DeviceObject, Irp); + break; + + case FSCTL_PIPE_WAIT: + + NpAcquireExclusiveVcb(); + Status = NpWaitForNamedPipe(DeviceObject, Irp); + break; + + case FSCTL_PIPE_IMPERSONATE: + + NpAcquireExclusiveVcb(); + Status = NpImpersonate(DeviceObject, Irp); + break; + + case FSCTL_PIPE_SET_CLIENT_PROCESS: + NpAcquireExclusiveVcb(); + Status = NpSetClientProcess(DeviceObject, Irp); + break; + + default: + return STATUS_NOT_SUPPORTED; + } + + NpReleaseVcb(); + NpCompleteDeferredIrps(&DeferredList); return Status; } - -NTSTATUS NTAPI -NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, - PIRP Irp) +NTSTATUS +NTAPI +NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - PIO_STACK_LOCATION IoStack; - PFILE_OBJECT FileObject; NTSTATUS Status; - //PNPFS_VCB Vcb; - PNPFS_FCB Fcb; - PNPFS_CCB Ccb; + PAGED_CODE(); - DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp); + FsRtlEnterFileSystem(); - //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension; - IoStack = IoGetCurrentIrpStackLocation(Irp); - DPRINT("IoStack: %p\n", IoStack); - FileObject = IoStack->FileObject; - DPRINT("FileObject: %p\n", FileObject); - Ccb = FileObject->FsContext2; - DPRINT("CCB: %p\n", Ccb); - Fcb = Ccb->Fcb; - DPRINT("Pipe: %p\n", Fcb); - DPRINT("PipeName: %wZ\n", &Fcb->PipeName); + Status = NpCommonFileSystemControl(DeviceObject, Irp); - Irp->IoStatus.Information = 0; - - switch (IoStack->Parameters.FileSystemControl.FsControlCode) - { - case FSCTL_PIPE_ASSIGN_EVENT: - DPRINT1("Assign event not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - case FSCTL_PIPE_DISCONNECT: - DPRINT("Disconnecting pipe %wZ\n", &Fcb->PipeName); - Status = NpfsDisconnectPipe(Ccb); - break; - - case FSCTL_PIPE_LISTEN: - DPRINT("Connecting pipe %wZ\n", &Fcb->PipeName); - Status = NpfsConnectPipe(Irp, Ccb); - break; - - case FSCTL_PIPE_PEEK: - DPRINT("Peeking pipe %wZ\n", &Fcb->PipeName); - Status = NpfsPeekPipe(Irp, (PIO_STACK_LOCATION)IoStack); - break; - - case FSCTL_PIPE_QUERY_EVENT: - DPRINT1("Query event not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - case FSCTL_PIPE_TRANSCEIVE: - /* If you implement this, please remove the workaround in - lib/kernel32/file/npipe.c function TransactNamedPipe() */ - DPRINT1("Transceive not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - case FSCTL_PIPE_WAIT: - DPRINT("Waiting for pipe %wZ\n", &Fcb->PipeName); - Status = NpfsWaitPipe(Irp, Ccb); - break; - - case FSCTL_PIPE_IMPERSONATE: - DPRINT1("Impersonate not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - case FSCTL_PIPE_SET_CLIENT_PROCESS: - DPRINT1("Set client process not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - case FSCTL_PIPE_QUERY_CLIENT_PROCESS: - DPRINT1("Query client process not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - case FSCTL_PIPE_INTERNAL_READ: - DPRINT1("Internal read not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - case FSCTL_PIPE_INTERNAL_WRITE: - DPRINT1("Internal write not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - case FSCTL_PIPE_INTERNAL_TRANSCEIVE: - DPRINT1("Internal transceive not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - case FSCTL_PIPE_INTERNAL_READ_OVFLOW: - DPRINT1("Internal read overflow not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - - default: - DPRINT1("Unrecognized IoControlCode: %x\n", - IoStack->Parameters.FileSystemControl.FsControlCode); - Status = STATUS_UNSUCCESSFUL; - } + FsRtlExitFileSystem(); if (Status != STATUS_PENDING) { Irp->IoStatus.Status = Status; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); + IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT); } return Status; } - -NTSTATUS NTAPI -NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - /* FIXME: Implement */ - UNREFERENCED_PARAMETER(DeviceObject); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return STATUS_SUCCESS; -} - /* EOF */ diff --git a/reactos/drivers/filesystems/npfs_new/main.c b/reactos/drivers/filesystems/npfs/main.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/main.c rename to reactos/drivers/filesystems/npfs/main.c diff --git a/reactos/drivers/filesystems/npfs/npfs.h b/reactos/drivers/filesystems/npfs/npfs.h index 8cf4651b887..77c7fceb19d 100644 --- a/reactos/drivers/filesystems/npfs/npfs.h +++ b/reactos/drivers/filesystems/npfs/npfs.h @@ -1,208 +1,675 @@ -#ifndef __DRIVERS_FS_NP_NPFS_H -#define __DRIVERS_FS_NP_NPFS_H +/* + * PROJECT: ReactOS Named Pipe FileSystem + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/filesystems/npfs/npfs.h + * PURPOSE: Named Pipe FileSystem Header + * PROGRAMMERS: ReactOS Portable Systems Group + */ +/* INCLUDES *******************************************************************/ + +// +// System Headers +// #include -#include +#include #include +#define UNIMPLEMENTED +#define DPRINT1 DbgPrint -#define TAG_NPFS_CCB 'cFpN' -#define TAG_NPFS_CCB_DATA 'iFpN' /* correct? */ -#define TAG_NPFS_FCB 'FFpN' -#define TAG_NPFS_NAMEBLOCK 'nFpN' -#define TAG_NPFS_THREAD_CONTEXT 'tFpN' +// +// Allow Microsoft Extensions +// +#ifdef _MSC_VER +#pragma warning(disable:4201) +#pragma warning(disable:4214) +#pragma warning(disable:4100) +#endif -#define ROUND_DOWN(n, align) \ - (((ULONG)n) & ~((align) - 1l)) -#define ROUND_UP(n, align) \ - ROUND_DOWN(((ULONG)n) + (align) - 1, (align)) +/* TYPEDEFS & DEFINES *********************************************************/ -typedef enum _FCB_TYPE +// +// Pool Tags for NPFS (from pooltag.txt) +// +// Npf* -npfs.sys - Npfs Allocations +// NpFc - npfs.sys - CCB, client control block +// NpFf - npfs.sys - FCB, file control block +// NpFC - npfs.sys - ROOT_DCB CCB +// NpFD - npfs.sys - DCB, directory block +// NpFg - npfs.sys - Global storage +// NpFi - npfs.sys - NPFS client info buffer. +// NpFn - npfs.sys - Name block +// NpFq - npfs.sys - Query template buffer used for directory query +// NpFr - npfs.sys - DATA_ENTRY records(read / write buffers) +// NpFs - npfs.sys - Client security context +// NpFw - npfs.sys - Write block +// NpFW - npfs.sys - Write block +#define NPFS_CCB_TAG 'NpFc' +#define NPFS_ROOT_DCB_CCB_TAG 'NpFC' +#define NPFS_DCB_TAG 'NpFD' +#define NPFS_FCB_TAG 'NpFf' +#define NPFS_GLOBAL_TAG 'NpFg' +#define NPFS_CLIENT_INFO_TAG 'NpFi' +#define NPFS_NAME_BLOCK_TAG 'NpFn' +#define NPFS_QUERY_TEMPLATE_TAG 'NpFq' +#define NPFS_DATA_ENTRY_TAG 'NpFr' +#define NPFS_CLIENT_SEC_CTX_TAG 'NpFs' +#define NPFS_WAIT_BLOCK_TAG 'NpFt' +#define NPFS_WRITE_BLOCK_TAG 'NpFw' + +// +// NPFS bugchecking support +// +// We define the NpBugCheck macro which triggers a NPFS_FILE_SYSTEM bugcheck +// containing the source file ID number and the line where it was emitted, as +// described in the MSDN article "Bug Check 0x25: NPFS_FILE_SYSTEM". +// +// The bugcheck emits 4 ULONGs; the first one is made, in its high word, by +// the current source file ID and in its low word, by the line number; the +// three other ones are user-defined. +// +// In order to avoid redefinition of the same file ID in different source files, +// we gather all of them here, so that you will have to add (or remove) a new +// one as soon as you add (or remove) a source file from the NPFS driver code. +// +// To use the NpBugCheck macro in a source file, define at its beginning +// the constant NPFS_BUGCHECK_FILE_ID with one of the following file IDs, +// then use the bugcheck macro wherever you want. +// +#define NPFS_BUGCHECK_CLEANUP 0x0001 +#define NPFS_BUGCHECK_CLOSE 0x0002 +#define NPFS_BUGCHECK_CREATE 0x0003 +#define NPFS_BUGCHECK_DATASUP 0x0004 +#define NPFS_BUGCHECK_FILEINFO 0x0005 +#define NPFS_BUGCHECK_FILEOBSUP 0x0006 +#define NPFS_BUGCHECK_FLUSHBUF 0x0007 +#define NPFS_BUGCHECK_FSCTRL 0x0008 +#define NPFS_BUGCHECK_MAIN 0x0009 +#define NPFS_BUGCHECK_PREFXSUP 0x000a +#define NPFS_BUGCHECK_READ 0x000b +#define NPFS_BUGCHECK_READSUP 0x000c +#define NPFS_BUGCHECK_SECURSUP 0x000d +#define NPFS_BUGCHECK_SEINFO 0x000e +#define NPFS_BUGCHECK_STATESUP 0x000f +#define NPFS_BUGCHECK_STRUCSUP 0x0010 +#define NPFS_BUGCHECK_VOLINFO 0x0011 +#define NPFS_BUGCHECK_WAITSUP 0x0012 +#define NPFS_BUGCHECK_WRITE 0x0013 +#define NPFS_BUGCHECK_WRITESUP 0x0014 + +#define NpBugCheck(p1, p2, p3) \ + KeBugCheckEx(NPFS_FILE_SYSTEM, \ + (NPFS_BUGCHECK_FILE_ID << 16) | __LINE__, \ + (p1), (p2), (p3)) + +// +// Node Type Codes for NPFS +// +#define NPFS_NTC_VCB 1 +#define NPFS_NTC_ROOT_DCB 2 +#define NPFS_NTC_FCB 4 +#define NPFS_NTC_CCB 6 +#define NPFS_NTC_NONPAGED_CCB 7 +#define NPFS_NTC_ROOT_DCB_CCB 8 +typedef USHORT NODE_TYPE_CODE, *PNODE_TYPE_CODE; + +// +// Data Queue States +// +typedef enum _NP_DATA_QUEUE_STATE { - FCB_INVALID, - FCB_DEVICE, - FCB_DIRECTORY, - FCB_PIPE -} FCB_TYPE; + ReadEntries = 0, + WriteEntries = 1, + Empty = 2 +} NP_DATA_QUEUE_STATE; -typedef enum _CCB_TYPE +// +// Data Queue Entry Types +// +typedef enum _NP_DATA_QUEUE_ENTRY_TYPE { - CCB_INVALID, - CCB_DEVICE, - CCB_DIRECTORY, - CCB_PIPE -} CCB_TYPE; + Buffered = 0, + Unbuffered +} NP_DATA_QUEUE_ENTRY_TYPE; -/* Volume Control Block (VCB) aka Device Extension */ -typedef struct _NPFS_VCB +// +// An Input or Output Data Queue. Each CCB has two of these. +// +typedef struct _NP_DATA_QUEUE { - LIST_ENTRY PipeListHead; - LIST_ENTRY ThreadListHead; - KMUTEX PipeListLock; - ULONG EmptyWaiterCount; - ULONG MinQuota; - ULONG DefaultQuota; - ULONG MaxQuota; - struct _NPFS_FCB *DeviceFcb; - struct _NPFS_FCB *RootFcb; -} NPFS_VCB, *PNPFS_VCB; + LIST_ENTRY Queue; + ULONG QueueState; + ULONG BytesInQueue; + ULONG EntriesInQueue; + ULONG QuotaUsed; + ULONG ByteOffset; + ULONG Quota; +} NP_DATA_QUEUE, *PNP_DATA_QUEUE; -typedef struct _NPFS_FCB +// +// The Entries that go into the Queue +// +typedef struct _NP_DATA_QUEUE_ENTRY { - FCB_TYPE Type; - PNPFS_VCB Vcb; - volatile LONG RefCount; - UNICODE_STRING PipeName; - LIST_ENTRY PipeListEntry; - KMUTEX CcbListLock; - LIST_ENTRY ServerCcbListHead; - LIST_ENTRY ClientCcbListHead; - LIST_ENTRY WaiterListHead; - LIST_ENTRY EmptyBufferListHead; - ULONG PipeType; - ULONG ClientReadMode; - ULONG ServerReadMode; - ULONG CompletionMode; - ULONG PipeConfiguration; - ULONG MaximumInstances; - ULONG CurrentInstances; - ULONG InboundQuota; - ULONG OutboundQuota; - LARGE_INTEGER TimeOut; -} NPFS_FCB, *PNPFS_FCB; + LIST_ENTRY QueueEntry; + ULONG DataEntryType; + PIRP Irp; + ULONG QuotaInEntry; + PSECURITY_CLIENT_CONTEXT ClientSecurityContext; + ULONG DataSize; +} NP_DATA_QUEUE_ENTRY, *PNP_DATA_QUEUE_ENTRY; - -typedef struct _NPFS_CCB_DIRECTORY_DATA +// +// A Wait Queue. Only the VCB has one of these. +// +typedef struct _NP_WAIT_QUEUE { - UNICODE_STRING SearchPattern; - ULONG FileIndex; -} NPFS_CCB_DIRECTORY_DATA, *PNPFS_CCB_DIRECTORY_DATA; + LIST_ENTRY WaitList; + KSPIN_LOCK WaitLock; +} NP_WAIT_QUEUE, *PNP_WAIT_QUEUE; - -typedef struct _NPFS_CCB +// +// The Entries in the Queue above, one for each Waiter. +// +typedef struct _NP_WAIT_QUEUE_ENTRY { - LIST_ENTRY CcbListEntry; - CCB_TYPE Type; - PNPFS_FCB Fcb; + PIRP Irp; + KDPC Dpc; + KTIMER Timer; + PNP_WAIT_QUEUE WaitQueue; + UNICODE_STRING AliasName; PFILE_OBJECT FileObject; +} NP_WAIT_QUEUE_ENTRY, *PNP_WAIT_QUEUE_ENTRY; - struct _NPFS_CCB* OtherSide; - struct ETHREAD *Thread; - KEVENT ConnectEvent; - KEVENT ReadEvent; - KEVENT WriteEvent; - ULONG PipeEnd; - ULONG PipeState; - ULONG ReadDataAvailable; - ULONG WriteQuotaAvailable; - volatile LONG RefCount; +// +// The event buffer in the NonPaged CCB +// +typedef struct _NP_EVENT_BUFFER +{ + PKEVENT Event; +} NP_EVENT_BUFFER, *PNP_EVENT_BUFFER; - LIST_ENTRY ReadRequestListHead; +// +// The CCB for the Root DCB +// +typedef struct _NP_ROOT_DCB_CCB +{ + NODE_TYPE_CODE NodeType; + PVOID Unknown; + ULONG Unknown2; +} NP_ROOT_DCB_CCB, *PNP_ROOT_DCB_FCB; - PVOID Data; - PVOID ReadPtr; - PVOID WritePtr; - ULONG MaxDataLength; +// +// The header that both FCB and DCB share +// +typedef struct _NP_CB_HEADER +{ + NODE_TYPE_CODE NodeType; + LIST_ENTRY DcbEntry; + PVOID ParentDcb; + ULONG CurrentInstances; + ULONG ServerOpenCount; + PSECURITY_DESCRIPTOR SecurityDescriptor; +} NP_CB_HEADER, *PNP_CB_HEADER; - FAST_MUTEX DataListLock; /* Data queue lock */ +// +// The footer that both FCB and DCB share +// +typedef struct _NP_CB_FOOTER +{ + UNICODE_STRING FullName; + UNICODE_STRING ShortName; + UNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry; +} NP_CB_FOOTER; - union +// +// A Directory Control Block (DCB) +// +typedef struct _NP_DCB +{ + // + // Common Header + // + NP_CB_HEADER; + + // + // DCB-specific data + // + LIST_ENTRY NotifyList; + LIST_ENTRY NotifyList2; + LIST_ENTRY FcbList; +#ifndef _WIN64 + ULONG Pad; +#endif + + // + // Common Footer + // + NP_CB_FOOTER; +} NP_DCB, *PNP_DCB; + +// +// A File Control BLock (FCB) +// +typedef struct _NP_FCB +{ + // + // Common Header + // + NP_CB_HEADER; + + // + // FCB-specific fields + // + ULONG MaximumInstances; + USHORT NamedPipeConfiguration; + USHORT NamedPipeType; + LARGE_INTEGER Timeout; + LIST_ENTRY CcbList; +#ifdef _WIN64 + PVOID Pad[2]; +#endif + + // + // Common Footer + // + NP_CB_FOOTER; +} NP_FCB, *PNP_FCB; + +C_ASSERT(FIELD_OFFSET(NP_FCB, PrefixTableEntry) == FIELD_OFFSET(NP_DCB, PrefixTableEntry)); + +// +// The nonpaged portion of the CCB +// +typedef struct _NP_NONPAGED_CCB +{ + NODE_TYPE_CODE NodeType; + PNP_EVENT_BUFFER EventBuffer[2]; + ERESOURCE Lock; +} NP_NONPAGED_CCB, *PNP_NONPAGED_CCB; + +// +// A Client Control Block (CCB) +// +typedef struct _NP_CCB +{ + NODE_TYPE_CODE NodeType; + UCHAR NamedPipeState; + UCHAR ReadMode[2]; + UCHAR CompletionMode[2]; + SECURITY_QUALITY_OF_SERVICE ClientQos; + LIST_ENTRY CcbEntry; + PNP_FCB Fcb; + PFILE_OBJECT FileObject[2]; + PEPROCESS Process; + PVOID ClientSession; + PNP_NONPAGED_CCB NonPagedCcb; + NP_DATA_QUEUE DataQueue[2]; + PSECURITY_CLIENT_CONTEXT ClientContext; + LIST_ENTRY IrpList; +} NP_CCB, *PNP_CCB; + +// +// A Volume Control Block (VCB) +// +typedef struct _NP_VCB +{ + NODE_TYPE_CODE NodeType; + ULONG ReferenceCount; + PNP_DCB RootDcb; + UNICODE_PREFIX_TABLE PrefixTable; + ERESOURCE Lock; + RTL_GENERIC_TABLE EventTable; + NP_WAIT_QUEUE WaitQueue; +} NP_VCB, *PNP_VCB; + +extern PNP_VCB NpVcb; + + +/* FUNCTIONS ******************************************************************/ + +// +// Functions to lock/unlock the global VCB lock +// +FORCEINLINE +VOID +NpAcquireSharedVcb(VOID) +{ + /* Acquire the lock in shared mode */ + ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE); +} + +FORCEINLINE +VOID +NpAcquireExclusiveVcb(VOID) +{ + /* Acquire the lock in exclusive mode */ + ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE); +} + +FORCEINLINE +VOID +NpReleaseVcb(VOID) +{ + /* Release the lock */ + ExReleaseResourceLite(&NpVcb->Lock); +} + + + +// +// Function to process deferred IRPs outside the VCB lock but still within the +// critical region +// +VOID +FORCEINLINE +NpCompleteDeferredIrps(IN PLIST_ENTRY DeferredList) +{ + PLIST_ENTRY ThisEntry, NextEntry; + PIRP Irp; + + /* Loop the list */ + ThisEntry = DeferredList->Flink; + while (ThisEntry != DeferredList) { - NPFS_CCB_DIRECTORY_DATA Directory; - } u; + /* Remember the next entry, but don't switch to it yet */ + NextEntry = ThisEntry->Flink; -} NPFS_CCB, *PNPFS_CCB; + /* Complete the IRP for this entry */ + Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry); + IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT); -typedef struct _NPFS_CONTEXT -{ - LIST_ENTRY ListEntry; - PKEVENT WaitEvent; -} NPFS_CONTEXT, *PNPFS_CONTEXT; + /* And now switch to the next one */ + ThisEntry = NextEntry; + } +} -typedef struct _NPFS_THREAD_CONTEXT -{ - ULONG Count; - KEVENT Event; - PNPFS_VCB Vcb; - LIST_ENTRY ListEntry; - PVOID WaitObjectArray[MAXIMUM_WAIT_OBJECTS]; - KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS]; - PIRP WaitIrpArray[MAXIMUM_WAIT_OBJECTS]; -} NPFS_THREAD_CONTEXT, *PNPFS_THREAD_CONTEXT; - -typedef struct _NPFS_WAITER_ENTRY -{ - LIST_ENTRY Entry; - PNPFS_CCB Ccb; -} NPFS_WAITER_ENTRY, *PNPFS_WAITER_ENTRY; - - -extern NPAGED_LOOKASIDE_LIST NpfsPipeDataLookasideList; - - -#define KeLockMutex(x) KeWaitForSingleObject(x, \ - UserRequest, \ - KernelMode, \ - FALSE, \ - NULL); - -#define KeUnlockMutex(x) KeReleaseMutex(x, FALSE); - -#define PAGE_ROUND_UP(x) ( (((ULONG_PTR)x)%PAGE_SIZE) ? ((((ULONG_PTR)x)&(~(PAGE_SIZE-1)))+PAGE_SIZE) : ((ULONG_PTR)x) ) - -DRIVER_DISPATCH NpfsCreate; -NTSTATUS NTAPI NpfsCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsCreateNamedPipe; -NTSTATUS NTAPI NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsCleanup; -NTSTATUS NTAPI NpfsCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsClose; -NTSTATUS NTAPI NpfsClose(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsDirectoryControl; -NTSTATUS NTAPI NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsRead; -NTSTATUS NTAPI NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsWrite; -NTSTATUS NTAPI NpfsWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsFlushBuffers; -NTSTATUS NTAPI NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsFileSystemControl; -NTSTATUS NTAPI NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsQueryInformation; -NTSTATUS NTAPI NpfsQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsSetInformation; -NTSTATUS NTAPI NpfsSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -DRIVER_DISPATCH NpfsQueryVolumeInformation; -NTSTATUS NTAPI NpfsQueryVolumeInformation (PDEVICE_OBJECT DeviceObject, PIRP Irp); - -NTSTATUS NTAPI -DriverEntry(PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath); +BOOLEAN +NTAPI +NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table, + IN PVOID Buffer); VOID -NpfsDereferenceFcb(PNPFS_FCB Fcb); +NTAPI +NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue); -PNPFS_FCB -NpfsFindPipe(PNPFS_VCB Vcb, - PUNICODE_STRING PipeName); -FCB_TYPE -NpfsGetFcb(PFILE_OBJECT FileObject, - PNPFS_FCB *Fcb); +NTSTATUS +NTAPI +NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue); -CCB_TYPE -NpfsGetCcb(PFILE_OBJECT FileObject, - PNPFS_CCB *Ccb); +PLIST_ENTRY +NTAPI +NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue, + IN PLIST_ENTRY List); -#endif /* __DRIVERS_FS_NP_NPFS_H */ +PIRP +NTAPI +NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue, + IN BOOLEAN Flag, + IN PLIST_ENTRY List); + +NTSTATUS +NTAPI +NpAddDataQueueEntry(IN ULONG NamedPipeEnd, + IN PNP_CCB Ccb, + IN PNP_DATA_QUEUE DataQueue, + IN ULONG Who, + IN ULONG Type, + IN ULONG DataSize, + IN PIRP Irp, + IN PVOID Buffer, + IN ULONG ByteOffset); + +VOID +NTAPI +NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue, + IN PLIST_ENTRY List); + +NTSTATUS +NTAPI +NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue, + IN ULONG Quota); + +NTSTATUS +NTAPI +NpCreateCcb(IN PNP_FCB Fcb, + IN PFILE_OBJECT FileObject, + IN UCHAR State, + IN UCHAR ReadMode, + IN UCHAR CompletionMode, + IN ULONG InQuota, + IN ULONG OutQuota, + OUT PNP_CCB *NewCcb); + +NTSTATUS +NTAPI +NpCreateFcb(IN PNP_DCB Dcb, + IN PUNICODE_STRING PipeName, + IN ULONG MaximumInstances, + IN LARGE_INTEGER Timeout, + IN USHORT NamedPipeConfiguration, + IN USHORT NamedPipeType, + OUT PNP_FCB *NewFcb); + +NTSTATUS +NTAPI +NpCreateRootDcb(VOID); + +NTSTATUS +NTAPI +NpCreateRootDcbCcb(IN PNP_ROOT_DCB_FCB *NewRootCcb); + +VOID +NTAPI +NpInitializeVcb(VOID); + +VOID +NTAPI +NpDeleteCcb(IN PNP_CCB Ccb, + IN PLIST_ENTRY ListEntry); + +VOID +NTAPI +NpDeleteFcb(IN PNP_FCB Fcb, + IN PLIST_ENTRY ListEntry); + +NTSTATUS +NTAPI +NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +NpFsdCreate(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +NpFsdClose(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + +NTSTATUS +NTAPI +NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +NpSetConnectedPipeState(IN PNP_CCB Ccb, + IN PFILE_OBJECT FileObject, + IN PLIST_ENTRY List); + +NTSTATUS +NTAPI +NpSetListeningPipeState(IN PNP_CCB Ccb, + IN PIRP Irp, + IN PLIST_ENTRY List); + + +NTSTATUS +NTAPI +NpSetDisconnectedPipeState(IN PNP_CCB Ccb, + IN PLIST_ENTRY List); + +NTSTATUS +NTAPI +NpSetClosingPipeState(IN PNP_CCB Ccb, + IN PIRP Irp, + IN ULONG NamedPipeEnd, + IN PLIST_ENTRY List); + +VOID +NTAPI +NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext); + +NTSTATUS +NTAPI +NpImpersonateClientContext(IN PNP_CCB Ccb); + +VOID +NTAPI +NpCopyClientContext(IN PNP_CCB Ccb, + IN PNP_DATA_QUEUE_ENTRY DataQueueEntry); + +VOID +NTAPI +NpUninitializeSecurity(IN PNP_CCB Ccb); + +NTSTATUS +NTAPI +NpInitializeSecurity(IN PNP_CCB Ccb, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, + IN PETHREAD Thread); + +NTSTATUS +NTAPI +NpGetClientSecurityContext(IN ULONG NamedPipeEnd, + IN PNP_CCB Ccb, + IN PETHREAD Thread, + IN PSECURITY_CLIENT_CONTEXT *Context); + +VOID +NTAPI +NpSetFileObject(IN PFILE_OBJECT FileObject, + IN PVOID PrimaryContext, + IN PVOID Ccb, + IN ULONG NamedPipeEnd); + +NODE_TYPE_CODE +NTAPI +NpDecodeFileObject(IN PFILE_OBJECT FileObject, + OUT PVOID *PrimaryContext OPTIONAL, + OUT PNP_CCB *Ccb, + OUT PULONG NamedPipeEnd OPTIONAL); + +PNP_FCB +NTAPI +NpFindPrefix(IN PUNICODE_STRING Name, + IN ULONG CaseInsensitiveIndex, + IN PUNICODE_STRING Prefix); + +NTSTATUS +NTAPI +NpFindRelativePrefix(IN PNP_DCB Dcb, + IN PUNICODE_STRING Name, + IN ULONG CaseInsensitiveIndex, + IN PUNICODE_STRING Prefix, + OUT PNP_FCB *FoundFcb); + +VOID +NTAPI +NpCheckForNotify(IN PNP_DCB Dcb, + IN BOOLEAN SecondList, + IN PLIST_ENTRY List); + +NTSTATUS +NTAPI +NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue, + IN LARGE_INTEGER WaitTime, + IN PIRP Irp, + IN PUNICODE_STRING AliasName); + +NTSTATUS +NTAPI +NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue, + IN PUNICODE_STRING PipeName, + IN NTSTATUS Status, + IN PLIST_ENTRY ListEntry); + + +IO_STATUS_BLOCK +NTAPI +NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue, + IN BOOLEAN Peek, + IN BOOLEAN ReadOverflowOperation, + IN PVOID Buffer, + IN ULONG BufferSize, + IN ULONG Mode, + IN PNP_CCB Ccb, + IN PLIST_ENTRY List); + + +NTSTATUS +NTAPI +NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue, + IN ULONG Mode, + IN PVOID OutBuffer, + IN ULONG OutBufferSize, + IN ULONG PipeType, + OUT PULONG BytesWritten, + IN PNP_CCB Ccb, + IN ULONG NamedPipeEnd, + IN PETHREAD Thread, + IN PLIST_ENTRY List); + +NTSTATUS +NTAPI +NpFsdRead(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + +NTSTATUS +NTAPI +NpFsdWrite(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + +NTSTATUS +NTAPI +NpFsdQuerySecurityInfo(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +NpFsdSetSecurityInfo(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +NpFsdQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +/* EOF */ diff --git a/reactos/drivers/filesystems/npfs_new/prefxsup.c b/reactos/drivers/filesystems/npfs/prefxsup.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/prefxsup.c rename to reactos/drivers/filesystems/npfs/prefxsup.c diff --git a/reactos/drivers/filesystems/npfs_new/read.c b/reactos/drivers/filesystems/npfs/read.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/read.c rename to reactos/drivers/filesystems/npfs/read.c diff --git a/reactos/drivers/filesystems/npfs_new/readsup.c b/reactos/drivers/filesystems/npfs/readsup.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/readsup.c rename to reactos/drivers/filesystems/npfs/readsup.c diff --git a/reactos/drivers/filesystems/npfs_new/secursup.c b/reactos/drivers/filesystems/npfs/secursup.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/secursup.c rename to reactos/drivers/filesystems/npfs/secursup.c diff --git a/reactos/drivers/filesystems/npfs_new/seinfo.c b/reactos/drivers/filesystems/npfs/seinfo.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/seinfo.c rename to reactos/drivers/filesystems/npfs/seinfo.c diff --git a/reactos/drivers/filesystems/npfs_new/statesup.c b/reactos/drivers/filesystems/npfs/statesup.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/statesup.c rename to reactos/drivers/filesystems/npfs/statesup.c diff --git a/reactos/drivers/filesystems/npfs_new/strucsup.c b/reactos/drivers/filesystems/npfs/strucsup.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/strucsup.c rename to reactos/drivers/filesystems/npfs/strucsup.c diff --git a/reactos/drivers/filesystems/npfs_new/volinfo.c b/reactos/drivers/filesystems/npfs/volinfo.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/volinfo.c rename to reactos/drivers/filesystems/npfs/volinfo.c diff --git a/reactos/drivers/filesystems/npfs_new/waitsup.c b/reactos/drivers/filesystems/npfs/waitsup.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/waitsup.c rename to reactos/drivers/filesystems/npfs/waitsup.c diff --git a/reactos/drivers/filesystems/npfs_new/write.c b/reactos/drivers/filesystems/npfs/write.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/write.c rename to reactos/drivers/filesystems/npfs/write.c diff --git a/reactos/drivers/filesystems/npfs_new/writesup.c b/reactos/drivers/filesystems/npfs/writesup.c similarity index 100% rename from reactos/drivers/filesystems/npfs_new/writesup.c rename to reactos/drivers/filesystems/npfs/writesup.c diff --git a/reactos/drivers/filesystems/npfs_new/CMakeLists.txt b/reactos/drivers/filesystems/npfs_new/CMakeLists.txt deleted file mode 100644 index 079709320ca..00000000000 --- a/reactos/drivers/filesystems/npfs_new/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ - -list(APPEND SOURCE - cleanup.c - close.c - create.c - datasup.c - fileinfo.c - fileobsup.c - flushbuf.c - fsctrl.c - main.c - prefxsup.c - read.c - readsup.c - secursup.c - seinfo.c - statesup.c - strucsup.c - volinfo.c - waitsup.c - write.c - writesup.c) - -add_library(npfs SHARED ${SOURCE}) -set_module_type(npfs kernelmodedriver) -target_link_libraries(npfs ${PSEH_LIB}) -add_importlibs(npfs ntoskrnl hal) -add_pch(npfs npfs.h) -add_cd_file(TARGET npfs DESTINATION reactos/system32/drivers FOR all) diff --git a/reactos/drivers/filesystems/npfs_new/create.c b/reactos/drivers/filesystems/npfs_new/create.c deleted file mode 100644 index 4e46e5b5ad2..00000000000 --- a/reactos/drivers/filesystems/npfs_new/create.c +++ /dev/null @@ -1,746 +0,0 @@ -/* - * PROJECT: ReactOS Named Pipe FileSystem - * LICENSE: BSD - See COPYING.ARM in the top level directory - * FILE: drivers/filesystems/npfs/create.c - * PURPOSE: Pipes Creation - * PROGRAMMERS: ReactOS Portable Systems Group - */ - -/* INCLUDES *******************************************************************/ - -#include "npfs.h" - -// File ID number for NPFS bugchecking support -#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_CREATE) - -/* FUNCTIONS ******************************************************************/ - -VOID -NTAPI -NpCheckForNotify(IN PNP_DCB Dcb, - IN BOOLEAN SecondList, - IN PLIST_ENTRY List) -{ - PLIST_ENTRY NextEntry, ListHead; - PIRP Irp; - ULONG i; - PAGED_CODE(); - - ListHead = &Dcb->NotifyList; - for (i = 0; i < 2; i++) - { - ASSERT(IsListEmpty(ListHead)); - while (!IsListEmpty(ListHead)) - { - NextEntry = RemoveHeadList(ListHead); - - Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry); - - if (IoSetCancelRoutine(Irp, NULL)) - { - Irp->IoStatus.Status = STATUS_SUCCESS; - InsertTailList(List, NextEntry); - } - else - { - InitializeListHead(NextEntry); - } - } - - if (!SecondList) break; - ListHead = &Dcb->NotifyList2; - } -} - -IO_STATUS_BLOCK -NTAPI -NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject, - IN ACCESS_MASK DesiredAccess) -{ - IO_STATUS_BLOCK Status; - PAGED_CODE(); - - NpSetFileObject(FileObject, NpVcb, NULL, FALSE); - ++NpVcb->ReferenceCount; - - Status.Information = FILE_OPENED; - Status.Status = STATUS_SUCCESS; - return Status; -} - -IO_STATUS_BLOCK -NTAPI -NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb, - IN PFILE_OBJECT FileObject, - IN ACCESS_MASK DesiredAccess, - IN PLIST_ENTRY List) -{ - IO_STATUS_BLOCK IoStatus; - PNP_ROOT_DCB_FCB Ccb; - PAGED_CODE(); - - IoStatus.Status = NpCreateRootDcbCcb(&Ccb); - if (NT_SUCCESS(IoStatus.Status)) - { - NpSetFileObject(FileObject, Dcb, Ccb, FALSE); - ++Dcb->CurrentInstances; - - IoStatus.Information = FILE_OPENED; - IoStatus.Status = STATUS_SUCCESS; - } - else - { - IoStatus.Information = 0; - } - - return IoStatus; -} - -IO_STATUS_BLOCK -NTAPI -NpCreateClientEnd(IN PNP_FCB Fcb, - IN PFILE_OBJECT FileObject, - IN ACCESS_MASK DesiredAccess, - IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, - IN PACCESS_STATE AccessState, - IN KPROCESSOR_MODE PreviousMode, - IN PETHREAD Thread, - IN PLIST_ENTRY List) -{ - PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext; - BOOLEAN AccessGranted; - ACCESS_MASK GrantedAccess; - PPRIVILEGE_SET Privileges; - UNICODE_STRING ObjectTypeName; - IO_STATUS_BLOCK IoStatus; - USHORT NamedPipeConfiguration; - PLIST_ENTRY NextEntry, ListHead; - PNP_CCB Ccb = NULL; - - IoStatus.Status = STATUS_SUCCESS; - IoStatus.Information = 0; - Privileges = NULL; - - NamedPipeConfiguration = Fcb->NamedPipeConfiguration; - - SubjectSecurityContext = &AccessState->SubjectSecurityContext; - SeLockSubjectContext(SubjectSecurityContext); - - AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor, - SubjectSecurityContext, - TRUE, - DesiredAccess & ~4, - 0, - &Privileges, - IoGetFileObjectGenericMapping(), - PreviousMode, - &GrantedAccess, - &IoStatus.Status); - - if (Privileges) - { - SeAppendPrivileges(AccessState, Privileges); - SeFreePrivileges(Privileges); - } - - if (AccessGranted) - { - AccessState->PreviouslyGrantedAccess |= GrantedAccess; - AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED); - } - - ObjectTypeName.Buffer = L"NamedPipe"; - ObjectTypeName.Length = 18; - SeOpenObjectAuditAlarm(&ObjectTypeName, - NULL, - &FileObject->FileName, - Fcb->SecurityDescriptor, - AccessState, - FALSE, - AccessGranted, - PreviousMode, - &AccessState->GenerateOnClose); - SeUnlockSubjectContext(SubjectSecurityContext); - if (!AccessGranted) return IoStatus; - - if (((GrantedAccess & FILE_READ_DATA) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) || - ((GrantedAccess & FILE_WRITE_DATA) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND))) - { - IoStatus.Status = STATUS_ACCESS_DENIED; - return IoStatus; - } - - if (!(GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA))) SecurityQos = NULL; - - ListHead = &Fcb->CcbList; - NextEntry = ListHead->Flink; - while (NextEntry != ListHead) - { - Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry); - if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break; - - NextEntry = NextEntry->Flink; - } - - if (NextEntry == ListHead) - { - IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE; - return IoStatus; - } - - IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread); - if (!NT_SUCCESS(IoStatus.Status)) return IoStatus; - - IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List); - if (!NT_SUCCESS(IoStatus.Status)) - { - NpUninitializeSecurity(Ccb); - return IoStatus; - } - - Ccb->ClientSession = NULL; - Ccb->Process = IoThreadToProcess(Thread); - - IoStatus.Information = FILE_OPENED; - IoStatus.Status = STATUS_SUCCESS; - return IoStatus; -} - -NTSTATUS -NTAPI -NpFsdCreate(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PEXTENDED_IO_STACK_LOCATION IoStack; - UNICODE_STRING FileName; - PFILE_OBJECT FileObject; - PFILE_OBJECT RelatedFileObject; - NODE_TYPE_CODE Type; - PNP_CCB Ccb; - PNP_FCB Fcb; - PNP_DCB Dcb; - ACCESS_MASK DesiredAccess; - LIST_ENTRY DeferredList; - UNICODE_STRING Prefix; - - InitializeListHead(&DeferredList); - IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp); - FileObject = IoStack->FileObject; - RelatedFileObject = FileObject->RelatedFileObject; - FileName = FileObject->FileName; - DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess; - - FsRtlEnterFileSystem(); - ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE); - - if (RelatedFileObject) - { - Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE); - } - else - { - Type = 0; - Fcb = NULL; - Ccb = NULL; - } - - if (FileName.Length) - { - if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) && - (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) && - !(RelatedFileObject)) - { - Irp->IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb, - FileObject, - DesiredAccess, - &DeferredList); - goto Quickie; - } - } - else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB)) - { - Irp->IoStatus = NpOpenNamedPipeFileSystem(FileObject, - DesiredAccess); - goto Quickie; - } - else if (Type == NPFS_NTC_ROOT_DCB) - { - Irp->IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb, - FileObject, - DesiredAccess, - &DeferredList); - goto Quickie; - } - - // Status = NpTranslateAlias(&FileName);; // ignore this for now - // if (!NT_SUCCESS(Status)) goto Quickie; - if (RelatedFileObject) - { - if (Type == NPFS_NTC_ROOT_DCB) - { - Dcb = (PNP_DCB)Ccb; - Irp->IoStatus.Status = NpFindRelativePrefix(Dcb, - &FileName, - 1, - &Prefix, - &Fcb); - if (!NT_SUCCESS(Irp->IoStatus.Status)) - { - goto Quickie; - } - } - else if ((Type != NPFS_NTC_CCB) || (FileName.Length)) - { - Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID; - goto Quickie; - } - else - { - Prefix.Length = 0; - } - } - else - { - if ((FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR)) || - (FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR)) - { - Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID; - goto Quickie; - } - - Fcb = NpFindPrefix(&FileName, TRUE, &Prefix); - } - - if (Prefix.Length) - { - Irp->IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ? - STATUS_OBJECT_NAME_NOT_FOUND : - STATUS_OBJECT_NAME_INVALID; - goto Quickie; - } - - if (Fcb->NodeType != NPFS_NTC_FCB) - { - Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID; - goto Quickie; - } - - if (!Fcb->ServerOpenCount) - { - Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND; - goto Quickie; - } - - Irp->IoStatus = NpCreateClientEnd(Fcb, - FileObject, - DesiredAccess, - IoStack->Parameters.CreatePipe. - SecurityContext->SecurityQos, - IoStack->Parameters.CreatePipe. - SecurityContext->AccessState, - IoStack->Flags & - SL_FORCE_ACCESS_CHECK ? - UserMode : Irp->RequestorMode, - Irp->Tail.Overlay.Thread, - &DeferredList); - -Quickie: - ExReleaseResourceLite(&NpVcb->Lock); - NpCompleteDeferredIrps(&DeferredList); - FsRtlExitFileSystem(); - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Irp->IoStatus.Status; -} - -IO_STATUS_BLOCK -NTAPI -NpCreateExistingNamedPipe(IN PNP_FCB Fcb, - IN PFILE_OBJECT FileObject, - IN ACCESS_MASK DesiredAccess, - IN PACCESS_STATE AccessState, - IN KPROCESSOR_MODE PreviousMode, - IN ULONG Disposition, - IN ULONG ShareAccess, - IN PNAMED_PIPE_CREATE_PARAMETERS Parameters, - IN PEPROCESS Process, - OUT PLIST_ENTRY List) -{ - PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext; - IO_STATUS_BLOCK IoStatus; - UNICODE_STRING ObjectTypeName; - ACCESS_MASK GrantedAccess; - PNP_CCB Ccb; - PPRIVILEGE_SET Privileges; - USHORT NamedPipeConfiguration, CheckShareAccess; - BOOLEAN AccessGranted; - PAGED_CODE(); - - Privileges = NULL; - - NamedPipeConfiguration = Fcb->NamedPipeConfiguration; - - SubjectSecurityContext = &AccessState->SubjectSecurityContext; - SeLockSubjectContext(SubjectSecurityContext); - - AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor, - SubjectSecurityContext, - TRUE, - DesiredAccess | 4, - 0, - &Privileges, - IoGetFileObjectGenericMapping(), - PreviousMode, - &GrantedAccess, - &IoStatus.Status); - - if (Privileges) - { - SeAppendPrivileges(AccessState, Privileges); - SeFreePrivileges(Privileges); - } - - if (AccessGranted) - { - AccessState->PreviouslyGrantedAccess |= GrantedAccess; - AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 0x2000000); - } - - ObjectTypeName.Buffer = L"NamedPipe"; - ObjectTypeName.Length = 18; - SeOpenObjectAuditAlarm(&ObjectTypeName, - NULL, - &FileObject->FileName, - Fcb->SecurityDescriptor, - AccessState, - FALSE, - AccessGranted, - PreviousMode, - &AccessState->GenerateOnClose); - - SeUnlockSubjectContext(SubjectSecurityContext); - if (!AccessGranted) return IoStatus; - - if (Fcb->CurrentInstances >= Fcb->MaximumInstances) - { - IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE; - return IoStatus; - } - - if (Disposition == FILE_CREATE) - { - IoStatus.Status = STATUS_ACCESS_DENIED; - return IoStatus; - } - - CheckShareAccess = 0; - if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX) - { - CheckShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; - } - else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND) - { - CheckShareAccess = FILE_SHARE_READ; - } - else if (NamedPipeConfiguration == FILE_PIPE_INBOUND) - { - CheckShareAccess = FILE_SHARE_WRITE; - } - - if (CheckShareAccess != ShareAccess) - { - IoStatus.Status = STATUS_ACCESS_DENIED; - return IoStatus; - } - - IoStatus.Status = NpCreateCcb(Fcb, - FileObject, - FILE_PIPE_LISTENING_STATE, - Parameters->ReadMode & 0xFF, - Parameters->CompletionMode & 0xFF, - Parameters->InboundQuota, - Parameters->OutboundQuota, - &Ccb); - if (!NT_SUCCESS(IoStatus.Status)) return IoStatus; - - IoStatus.Status = NpCancelWaiter(&NpVcb->WaitQueue, - &Fcb->FullName, - FALSE, - List); - if (!NT_SUCCESS(IoStatus.Status)) - { - --Ccb->Fcb->CurrentInstances; - NpDeleteCcb(Ccb, List); - return IoStatus; - } - - NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE); - Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject; - NpCheckForNotify(Fcb->ParentDcb, 0, List); - - IoStatus.Status = STATUS_SUCCESS; - IoStatus.Information = 1; - return IoStatus; -} - -NTSTATUS -NTAPI -NpCreateNewNamedPipe(IN PNP_DCB Dcb, - IN PFILE_OBJECT FileObject, - IN UNICODE_STRING PipeName, - IN ACCESS_MASK DesiredAccess, - IN PACCESS_STATE AccessState, - IN USHORT Disposition, - IN USHORT ShareAccess, - IN PNAMED_PIPE_CREATE_PARAMETERS Parameters, - IN PEPROCESS Process, - IN PLIST_ENTRY List, - IN PIO_STATUS_BLOCK IoStatus) -{ - NTSTATUS Status; - USHORT NamedPipeConfiguration; - PSECURITY_SUBJECT_CONTEXT SecurityContext; - PSECURITY_DESCRIPTOR SecurityDescriptor, CachedSecurityDescriptor; - PNP_CCB Ccb; - PNP_FCB Fcb; - PAGED_CODE(); - - if (!(Parameters->TimeoutSpecified) || - !(Parameters->MaximumInstances) || - (Parameters->DefaultTimeout.HighPart >= 0)) - { - Status = STATUS_INVALID_PARAMETER; - goto Quickie; - } - - if (Disposition == FILE_OPEN) - { - Status = STATUS_OBJECT_NAME_NOT_FOUND; - goto Quickie; - } - - if (ShareAccess == (FILE_SHARE_READ | FILE_SHARE_WRITE)) - { - NamedPipeConfiguration = FILE_PIPE_FULL_DUPLEX; - } - else if (ShareAccess == FILE_SHARE_READ) - { - NamedPipeConfiguration = FILE_PIPE_OUTBOUND; - } - else if (ShareAccess == FILE_SHARE_WRITE) - { - NamedPipeConfiguration = FILE_PIPE_INBOUND; - } - else - { - Status = STATUS_INVALID_PARAMETER; - goto Quickie; - } - - if (!Parameters->NamedPipeType && Parameters->ReadMode == 1) - { - Status = STATUS_INVALID_PARAMETER; - goto Quickie; - } - - Status = NpCreateFcb(Dcb, - &PipeName, - Parameters->MaximumInstances, - Parameters->DefaultTimeout, - NamedPipeConfiguration, - Parameters->NamedPipeType & 0xFFFF, - &Fcb); - if (!NT_SUCCESS(Status)) goto Quickie; - - Status = NpCreateCcb(Fcb, - FileObject, - FILE_PIPE_LISTENING_STATE, - Parameters->ReadMode & 0xFF, - Parameters->CompletionMode & 0xFF, - Parameters->InboundQuota, - Parameters->OutboundQuota, - &Ccb); - if (!NT_SUCCESS(Status)) - { - NpDeleteFcb(Fcb, List); - goto Quickie; - } - - SecurityContext = &AccessState->SubjectSecurityContext; - SeLockSubjectContext(&AccessState->SubjectSecurityContext); - - Status = SeAssignSecurity(0, - AccessState->SecurityDescriptor, - &SecurityDescriptor, - 0, - SecurityContext, - IoGetFileObjectGenericMapping(), - PagedPool); - SeUnlockSubjectContext(SecurityContext); - if (!NT_SUCCESS(Status)) - { - NpDeleteCcb(Ccb, List); - NpDeleteFcb(Fcb, List); - goto Quickie; - } - - Status = ObLogSecurityDescriptor(SecurityDescriptor, - &CachedSecurityDescriptor, - 1); - ExFreePool(SecurityDescriptor); - - if (!NT_SUCCESS(Status)) - { - NpDeleteCcb(Ccb, List); - NpDeleteFcb(Fcb, List); - goto Quickie; - } - - Fcb->SecurityDescriptor = CachedSecurityDescriptor; - - NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE); - Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject; - - NpCheckForNotify(Dcb, TRUE, List); - - IoStatus->Status = STATUS_SUCCESS; - IoStatus->Information = FILE_CREATED; - - return STATUS_SUCCESS; - -Quickie: - IoStatus->Information = 0; - IoStatus->Status = Status; - return Status; -} - -NTSTATUS -NTAPI -NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PEXTENDED_IO_STACK_LOCATION IoStack; - PFILE_OBJECT FileObject; - PFILE_OBJECT RelatedFileObject; - USHORT Disposition, ShareAccess; - PEPROCESS Process; - LIST_ENTRY DeferredList; - UNICODE_STRING FileName; - PNP_FCB Fcb; - UNICODE_STRING Prefix; - PNAMED_PIPE_CREATE_PARAMETERS Parameters; - IO_STATUS_BLOCK IoStatus; - - InitializeListHead(&DeferredList); - Process = IoGetRequestorProcess(Irp); - - IoStack = (PEXTENDED_IO_STACK_LOCATION) IoGetCurrentIrpStackLocation(Irp); - FileObject = IoStack->FileObject; - RelatedFileObject = FileObject->RelatedFileObject; - - Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF; - ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF; - Parameters = IoStack->Parameters.CreatePipe.Parameters; - - FileName.Buffer = FileObject->FileName.Buffer; - FileName.Length = FileObject->FileName.Length; - FileName.MaximumLength = FileObject->FileName.MaximumLength; - - IoStatus.Status = STATUS_SUCCESS; - IoStatus.Information = 0; - - FsRtlEnterFileSystem(); - NpAcquireExclusiveVcb(); - - if (RelatedFileObject) - { - Fcb = (PNP_FCB)((ULONG_PTR)RelatedFileObject->FsContext & ~1); - if (!(Fcb) || - (Fcb->NodeType != NPFS_NTC_ROOT_DCB) || - (FileName.Length < sizeof(WCHAR)) || - (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) - { - IoStatus.Status = STATUS_OBJECT_NAME_INVALID; - goto Quickie; - } - - IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext, - &FileName, - TRUE, - &Prefix, - &Fcb); - if (!NT_SUCCESS(IoStatus.Status)) - { - goto Quickie; - } - } - else - { - if (FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR) || - FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR) - { - IoStatus.Status = STATUS_OBJECT_NAME_INVALID; - goto Quickie; - } - - Fcb = NpFindPrefix(&FileName, TRUE, &Prefix); - } - - if (Prefix.Length) - { - if (Fcb->NodeType == NPFS_NTC_ROOT_DCB) - { - IoStatus.Status = NpCreateNewNamedPipe((PNP_DCB)Fcb, - FileObject, - FileName, - IoStack->Parameters.CreatePipe. - SecurityContext->DesiredAccess, - IoStack->Parameters.CreatePipe. - SecurityContext->AccessState, - Disposition, - ShareAccess, - Parameters, - Process, - &DeferredList, - &IoStatus); - goto Quickie; - } - else - { - IoStatus.Status = STATUS_OBJECT_NAME_INVALID; - goto Quickie; - } - } - - if (Fcb->NodeType != NPFS_NTC_FCB) - { - IoStatus.Status = STATUS_OBJECT_NAME_INVALID; - goto Quickie; - } - - IoStatus = NpCreateExistingNamedPipe(Fcb, - FileObject, - IoStack->Parameters.CreatePipe. - SecurityContext->DesiredAccess, - IoStack->Parameters.CreatePipe. - SecurityContext->AccessState, - IoStack->Flags & - SL_FORCE_ACCESS_CHECK ? - UserMode : Irp->RequestorMode, - Disposition, - ShareAccess, - Parameters, - Process, - &DeferredList); - -Quickie: - NpReleaseVcb(); - NpCompleteDeferredIrps(&DeferredList); - FsRtlExitFileSystem(); - - Irp->IoStatus = IoStatus; - IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT); - return IoStatus.Status; -} - -/* EOF */ diff --git a/reactos/drivers/filesystems/npfs_new/fsctrl.c b/reactos/drivers/filesystems/npfs_new/fsctrl.c deleted file mode 100644 index 10288a7d0d5..00000000000 --- a/reactos/drivers/filesystems/npfs_new/fsctrl.c +++ /dev/null @@ -1,741 +0,0 @@ -/* - * PROJECT: ReactOS Named Pipe FileSystem - * LICENSE: BSD - See COPYING.ARM in the top level directory - * FILE: drivers/filesystems/npfs/fsctrl.c - * PURPOSE: Named Pipe FileSystem I/O Controls - * PROGRAMMERS: ReactOS Portable Systems Group - */ - -/* INCLUDES *******************************************************************/ - -#include "npfs.h" - -// File ID number for NPFS bugchecking support -#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_FSCTRL) - -/* GLOBALS ********************************************************************/ - -IO_STATUS_BLOCK NpUserIoStatusBlock; - -/* FUNCTIONS ******************************************************************/ - -NTSTATUS -NTAPI -NpInternalTransceive(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PLIST_ENTRY List) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NpInternalRead(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN BOOLEAN Overflow, - IN PLIST_ENTRY List) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NpInternalWrite(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PLIST_ENTRY List) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NpAssignEvent(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NpQueryEvent(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -NTAPI -NpImpersonate(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - ULONG NamedPipeEnd; - PNP_CCB Ccb; - NTSTATUS Status; - NODE_TYPE_CODE NodeTypeCode; - PIO_STACK_LOCATION IoStack; - PAGED_CODE(); - - IoStack = IoGetCurrentIrpStackLocation(Irp); - - NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); - if (NodeTypeCode == NPFS_NTC_CCB) - { - if (NamedPipeEnd == FILE_PIPE_SERVER_END) - { - Status = NpImpersonateClientContext(Ccb); - } - else - { - Status = STATUS_ILLEGAL_FUNCTION; - } - } - - return Status; -} - -NTSTATUS -NTAPI -NpDisconnect(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PLIST_ENTRY List) -{ - ULONG NamedPipeEnd; - PNP_CCB Ccb; - NTSTATUS Status; - NODE_TYPE_CODE NodeTypeCode; - PIO_STACK_LOCATION IoStack; - PAGED_CODE(); - - IoStack = IoGetCurrentIrpStackLocation(Irp); - - NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); - if (NodeTypeCode == NPFS_NTC_CCB) - { - if (NamedPipeEnd == FILE_PIPE_SERVER_END) - { - ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE); - - Status = NpSetDisconnectedPipeState(Ccb, List); - - NpUninitializeSecurity(Ccb); - - ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); - } - else - { - Status = STATUS_ILLEGAL_FUNCTION; - } - } - else - { - Status = STATUS_PIPE_DISCONNECTED; - } - - return Status; -} - -NTSTATUS -NTAPI -NpListen(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PLIST_ENTRY List) -{ - ULONG NamedPipeEnd; - PNP_CCB Ccb; - NTSTATUS Status; - NODE_TYPE_CODE NodeTypeCode; - PIO_STACK_LOCATION IoStack; - PAGED_CODE(); - - IoStack = IoGetCurrentIrpStackLocation(Irp); - - NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); - if (NodeTypeCode == NPFS_NTC_CCB) - { - if (NamedPipeEnd == FILE_PIPE_SERVER_END) - { - ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE); - - Status = NpSetListeningPipeState(Ccb, Irp, List); - - NpUninitializeSecurity(Ccb); - - ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); - } - else - { - Status = STATUS_ILLEGAL_FUNCTION; - } - } - else - { - Status = STATUS_ILLEGAL_FUNCTION; - } - - return Status; -} - -NTSTATUS -NTAPI -NpPeek(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PLIST_ENTRY List) -{ - PIO_STACK_LOCATION IoStack; - NODE_TYPE_CODE Type; - ULONG OutputLength; - ULONG NamedPipeEnd; - PNP_CCB Ccb; - PFILE_PIPE_PEEK_BUFFER PeekBuffer; - PNP_DATA_QUEUE DataQueue; - ULONG_PTR BytesPeeked; - IO_STATUS_BLOCK IoStatus; - NTSTATUS Status; - PNP_DATA_QUEUE_ENTRY DataEntry; - PAGED_CODE(); - - IoStack = IoGetCurrentIrpStackLocation(Irp); - OutputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength; - Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); - - if (!Type) - { - return STATUS_PIPE_DISCONNECTED; - } - - if ((Type != NPFS_NTC_CCB) && - (OutputLength < FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data))) - { - return STATUS_INVALID_PARAMETER; - } - - PeekBuffer = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer; - if (NamedPipeEnd != FILE_PIPE_CLIENT_END) - { - if (NamedPipeEnd != FILE_PIPE_SERVER_END) - { - NpBugCheck(NamedPipeEnd, 0, 0); - } - - DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; - } - else - { - DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; - } - - if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE) - { - if (Ccb->NamedPipeState != FILE_PIPE_CLOSING_STATE) - { - return STATUS_INVALID_PIPE_STATE; - } - - if (DataQueue->QueueState != WriteEntries) - { - return STATUS_PIPE_BROKEN; - } - } - - PeekBuffer->NamedPipeState = 0; - PeekBuffer->ReadDataAvailable = 0; - PeekBuffer->NumberOfMessages = 0; - PeekBuffer->MessageLength = 0; - PeekBuffer->NamedPipeState = Ccb->NamedPipeState; - BytesPeeked = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data); - - if (DataQueue->QueueState == WriteEntries) - { - DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink, - NP_DATA_QUEUE_ENTRY, - QueueEntry); - ASSERT((DataEntry->DataEntryType == Buffered) || (DataEntry->DataEntryType == Unbuffered)); - - PeekBuffer->ReadDataAvailable = DataQueue->BytesInQueue - DataQueue->ByteOffset; - if (Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE) - { - PeekBuffer->NumberOfMessages = DataQueue->EntriesInQueue; - PeekBuffer->MessageLength = DataEntry->DataSize - DataQueue->ByteOffset; - } - - if (OutputLength == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data)) - { - Status = PeekBuffer->ReadDataAvailable ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS; - } - else - { - IoStatus = NpReadDataQueue(DataQueue, - TRUE, - FALSE, - PeekBuffer->Data, - OutputLength - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data), - Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE, - Ccb, - List); - Status = IoStatus.Status; - BytesPeeked += IoStatus.Information; - } - } - else - { - Status = STATUS_SUCCESS; - } - - Irp->IoStatus.Information = BytesPeeked; - return Status; -} - -NTSTATUS -NTAPI -NpCompleteTransceiveIrp(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context) -{ - PAGED_CODE(); - - if (Irp->AssociatedIrp.SystemBuffer) - { - ExFreePool(Irp->AssociatedIrp.SystemBuffer); - } - - IoFreeIrp(Irp); - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -NTAPI -NpTransceive(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PLIST_ENTRY List) -{ - PIO_STACK_LOCATION IoStack; - PVOID InBuffer, OutBuffer; - ULONG InLength, OutLength, BytesWritten; - NODE_TYPE_CODE NodeTypeCode; - PNP_CCB Ccb; - ULONG NamedPipeEnd; - PNP_NONPAGED_CCB NonPagedCcb; - PNP_DATA_QUEUE ReadQueue, WriteQueue; - PNP_EVENT_BUFFER EventBuffer; - NTSTATUS Status; - PIRP NewIrp; - PAGED_CODE(); - - IoStack = IoGetCurrentIrpStackLocation(Irp); - InLength = IoStack->Parameters.FileSystemControl.InputBufferLength; - InBuffer = IoStack->Parameters.FileSystemControl.Type3InputBuffer; - OutLength = IoStack->Parameters.FileSystemControl.OutputBufferLength; - OutBuffer = Irp->UserBuffer; - - if (Irp->RequestorMode == UserMode) - { - _SEH2_TRY - { - ProbeForRead(InBuffer, InLength, sizeof(CHAR)); - ProbeForWrite(OutBuffer, OutLength, sizeof(CHAR)); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - _SEH2_YIELD(return _SEH2_GetExceptionCode()); - } - _SEH2_END; - } - - NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); - if (NodeTypeCode != NPFS_NTC_CCB) - { - return STATUS_PIPE_DISCONNECTED; - } - - NonPagedCcb = Ccb->NonPagedCcb; - ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE); - - if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE) - { - Status = STATUS_INVALID_PIPE_STATE; - goto Quickie; - } - - if (NamedPipeEnd != FILE_PIPE_CLIENT_END) - { - if (NamedPipeEnd != FILE_PIPE_SERVER_END) - { - NpBugCheck(NamedPipeEnd, 0, 0); - } - ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; - WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; - } - else - { - ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; - WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; - } - - EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd]; - - if (Ccb->Fcb->NamedPipeConfiguration != FILE_PIPE_FULL_DUPLEX || - Ccb->ReadMode[NamedPipeEnd] != FILE_PIPE_MESSAGE_MODE) - { - Status = STATUS_INVALID_PIPE_STATE; - goto Quickie; - } - - if (ReadQueue->QueueState != Empty) - { - Status = STATUS_PIPE_BUSY; - goto Quickie; - } - - Status = NpWriteDataQueue(WriteQueue, - 1, - InBuffer, - InLength, - Ccb->Fcb->NamedPipeType, - &BytesWritten, - Ccb, - NamedPipeEnd, - Irp->Tail.Overlay.Thread, - List); - if (Status == STATUS_MORE_PROCESSING_REQUIRED) - { - ASSERT(WriteQueue->QueueState != ReadEntries); - NewIrp = IoAllocateIrp(DeviceObject->StackSize, TRUE); - if (!NewIrp) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - IoSetCompletionRoutine(Irp, NpCompleteTransceiveIrp, NULL, TRUE, TRUE, TRUE); - - if (BytesWritten) - { - NewIrp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, - BytesWritten, - NPFS_WRITE_BLOCK_TAG); - if (!NewIrp->AssociatedIrp.SystemBuffer) - { - IoFreeIrp(NewIrp); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - _SEH2_TRY - { - RtlCopyMemory(NewIrp->AssociatedIrp.SystemBuffer, - (PVOID)((ULONG_PTR)InBuffer + InLength - BytesWritten), - BytesWritten); - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - _SEH2_YIELD(goto Quickie); - } - _SEH2_END; - } - else - { - NewIrp->AssociatedIrp.SystemBuffer = NULL; - } - - IoStack = IoGetNextIrpStackLocation(NewIrp); - IoSetNextIrpStackLocation(NewIrp); - - NewIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread; - NewIrp->IoStatus.Information = BytesWritten; - - IoStack->Parameters.Read.Length = BytesWritten; - IoStack->MajorFunction = IRP_MJ_WRITE; - - if (BytesWritten > 0) NewIrp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO; - NewIrp->UserIosb = &NpUserIoStatusBlock; - - Status = NpAddDataQueueEntry(NamedPipeEnd, - Ccb, - WriteQueue, - WriteEntries, - Unbuffered, - BytesWritten, - NewIrp, - NULL, - 0); - if (Status != STATUS_PENDING) - { - NewIrp->IoStatus.Status = Status; - InsertTailList(List, &NewIrp->Tail.Overlay.ListEntry); - } - } - - if (!NT_SUCCESS(Status)) goto Quickie; - - if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); - ASSERT(ReadQueue->QueueState == Empty); - Status = NpAddDataQueueEntry(NamedPipeEnd, - Ccb, - ReadQueue, - ReadEntries, - Buffered, - OutLength, - Irp, - NULL, - 0); - if (NT_SUCCESS(Status)) - { - if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); - } - -Quickie: - ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); - return Status; -} - -NTSTATUS -NTAPI -NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - ULONG InLength, NameLength; - UNICODE_STRING SourceString, Prefix; - ULONG NamedPipeEnd; - PNP_CCB Ccb; - PFILE_PIPE_WAIT_FOR_BUFFER Buffer; - NTSTATUS Status; - NODE_TYPE_CODE NodeTypeCode; - PLIST_ENTRY NextEntry; - PNP_FCB Fcb; - PWCHAR OriginalBuffer; - PAGED_CODE(); - - IoStack = IoGetCurrentIrpStackLocation(Irp); - InLength = IoStack->Parameters.FileSystemControl.InputBufferLength; - - SourceString.Buffer = NULL; - - if (NpDecodeFileObject(IoStack->FileObject, - NULL, - &Ccb, - &NamedPipeEnd) != NPFS_NTC_ROOT_DCB) - { - Status = STATUS_ILLEGAL_FUNCTION; - goto Quickie; - } - - Buffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer; - if (InLength < sizeof(*Buffer)) - { - Status = STATUS_INVALID_PARAMETER; - goto Quickie; - } - - NameLength = Buffer->NameLength; - if ((NameLength > (0xFFFF - sizeof(UNICODE_NULL))) || - ((NameLength + FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name)) > InLength)) - { - Status = STATUS_INVALID_PARAMETER; - goto Quickie; - } - - SourceString.Length = (USHORT)NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR); - SourceString.Buffer = ExAllocatePoolWithTag(PagedPool, - SourceString.Length, - NPFS_WRITE_BLOCK_TAG); - if (!SourceString.Buffer) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - SourceString.Buffer[0] = OBJ_NAME_PATH_SEPARATOR; - RtlCopyMemory(&SourceString.Buffer[1], Buffer->Name, Buffer->NameLength); - - Status = STATUS_SUCCESS; - OriginalBuffer = SourceString.Buffer; - //Status = NpTranslateAlias(&SourceString); - if (!NT_SUCCESS(Status)) goto Quickie; - - Fcb = NpFindPrefix(&SourceString, TRUE, &Prefix); - Fcb = (PNP_FCB)((ULONG_PTR)Fcb & ~1); - - NodeTypeCode = Fcb ? Fcb->NodeType : 0; - if (NodeTypeCode != NPFS_NTC_FCB) - { - Status = STATUS_OBJECT_NAME_NOT_FOUND; - goto Quickie; - } - - for (NextEntry = Fcb->CcbList.Flink; - NextEntry != &Fcb->CcbList; - NextEntry = NextEntry->Flink) - { - Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry); - if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break; - } - - if (NextEntry != &Fcb->CcbList) - { - Status = STATUS_SUCCESS; - } - else - { - Status = NpAddWaiter(&NpVcb->WaitQueue, - Fcb->Timeout, - Irp, - OriginalBuffer == SourceString.Buffer ? - NULL : &SourceString); - } - -Quickie: - if (SourceString.Buffer) ExFreePool(SourceString.Buffer); - return Status; -} - -NTSTATUS -NTAPI -NpCommonFileSystemControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - ULONG Fsctl; - BOOLEAN Overflow = FALSE; - LIST_ENTRY DeferredList; - NTSTATUS Status; - PAGED_CODE(); - - InitializeListHead(&DeferredList); - Fsctl = IoGetCurrentIrpStackLocation(Irp)->Parameters.FileSystemControl.FsControlCode; - - switch (Fsctl) - { - case FSCTL_PIPE_PEEK: - NpAcquireExclusiveVcb(); - Status = NpPeek(DeviceObject, Irp, &DeferredList); - break; - - case FSCTL_PIPE_INTERNAL_WRITE: - NpAcquireSharedVcb(); - Status = NpInternalWrite(DeviceObject, Irp, &DeferredList); - break; - - case FSCTL_PIPE_TRANSCEIVE: - NpAcquireSharedVcb(); - Status = NpTransceive(DeviceObject, Irp, &DeferredList); - break; - - case FSCTL_PIPE_INTERNAL_TRANSCEIVE: - NpAcquireSharedVcb(); - Status = NpInternalTransceive(DeviceObject, Irp, &DeferredList); - break; - - case FSCTL_PIPE_INTERNAL_READ_OVFLOW: - Overflow = TRUE; - // on purpose - - case FSCTL_PIPE_INTERNAL_READ: - NpAcquireSharedVcb(); - Status = NpInternalRead(DeviceObject, Irp, Overflow, &DeferredList); - break; - - case FSCTL_PIPE_QUERY_CLIENT_PROCESS: - - NpAcquireSharedVcb(); - Status = NpQueryClientProcess(DeviceObject, Irp); - break; - - case FSCTL_PIPE_ASSIGN_EVENT: - - NpAcquireExclusiveVcb(); - Status = NpAssignEvent(DeviceObject, Irp); - break; - - case FSCTL_PIPE_DISCONNECT: - - NpAcquireExclusiveVcb(); - Status = NpDisconnect(DeviceObject, Irp, &DeferredList); - break; - - case FSCTL_PIPE_LISTEN: - - NpAcquireSharedVcb(); - Status = NpListen(DeviceObject, Irp, &DeferredList); - break; - - case FSCTL_PIPE_QUERY_EVENT: - - NpAcquireExclusiveVcb(); - Status = NpQueryEvent(DeviceObject, Irp); - break; - - case FSCTL_PIPE_WAIT: - - NpAcquireExclusiveVcb(); - Status = NpWaitForNamedPipe(DeviceObject, Irp); - break; - - case FSCTL_PIPE_IMPERSONATE: - - NpAcquireExclusiveVcb(); - Status = NpImpersonate(DeviceObject, Irp); - break; - - case FSCTL_PIPE_SET_CLIENT_PROCESS: - NpAcquireExclusiveVcb(); - Status = NpSetClientProcess(DeviceObject, Irp); - break; - - default: - return STATUS_NOT_SUPPORTED; - } - - NpReleaseVcb(); - NpCompleteDeferredIrps(&DeferredList); - - return Status; -} - -NTSTATUS -NTAPI -NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - NTSTATUS Status; - PAGED_CODE(); - - FsRtlEnterFileSystem(); - - Status = NpCommonFileSystemControl(DeviceObject, Irp); - - FsRtlExitFileSystem(); - - if (Status != STATUS_PENDING) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT); - } - - return Status; -} - -/* EOF */ diff --git a/reactos/drivers/filesystems/npfs_new/npfs.h b/reactos/drivers/filesystems/npfs_new/npfs.h deleted file mode 100644 index 77c7fceb19d..00000000000 --- a/reactos/drivers/filesystems/npfs_new/npfs.h +++ /dev/null @@ -1,675 +0,0 @@ -/* - * PROJECT: ReactOS Named Pipe FileSystem - * LICENSE: BSD - See COPYING.ARM in the top level directory - * FILE: drivers/filesystems/npfs/npfs.h - * PURPOSE: Named Pipe FileSystem Header - * PROGRAMMERS: ReactOS Portable Systems Group - */ - -/* INCLUDES *******************************************************************/ - -// -// System Headers -// -#include -#include -#include -#define UNIMPLEMENTED -#define DPRINT1 DbgPrint - -// -// Allow Microsoft Extensions -// -#ifdef _MSC_VER -#pragma warning(disable:4201) -#pragma warning(disable:4214) -#pragma warning(disable:4100) -#endif - - -/* TYPEDEFS & DEFINES *********************************************************/ - -// -// Pool Tags for NPFS (from pooltag.txt) -// -// Npf* -npfs.sys - Npfs Allocations -// NpFc - npfs.sys - CCB, client control block -// NpFf - npfs.sys - FCB, file control block -// NpFC - npfs.sys - ROOT_DCB CCB -// NpFD - npfs.sys - DCB, directory block -// NpFg - npfs.sys - Global storage -// NpFi - npfs.sys - NPFS client info buffer. -// NpFn - npfs.sys - Name block -// NpFq - npfs.sys - Query template buffer used for directory query -// NpFr - npfs.sys - DATA_ENTRY records(read / write buffers) -// NpFs - npfs.sys - Client security context -// NpFw - npfs.sys - Write block -// NpFW - npfs.sys - Write block -#define NPFS_CCB_TAG 'NpFc' -#define NPFS_ROOT_DCB_CCB_TAG 'NpFC' -#define NPFS_DCB_TAG 'NpFD' -#define NPFS_FCB_TAG 'NpFf' -#define NPFS_GLOBAL_TAG 'NpFg' -#define NPFS_CLIENT_INFO_TAG 'NpFi' -#define NPFS_NAME_BLOCK_TAG 'NpFn' -#define NPFS_QUERY_TEMPLATE_TAG 'NpFq' -#define NPFS_DATA_ENTRY_TAG 'NpFr' -#define NPFS_CLIENT_SEC_CTX_TAG 'NpFs' -#define NPFS_WAIT_BLOCK_TAG 'NpFt' -#define NPFS_WRITE_BLOCK_TAG 'NpFw' - -// -// NPFS bugchecking support -// -// We define the NpBugCheck macro which triggers a NPFS_FILE_SYSTEM bugcheck -// containing the source file ID number and the line where it was emitted, as -// described in the MSDN article "Bug Check 0x25: NPFS_FILE_SYSTEM". -// -// The bugcheck emits 4 ULONGs; the first one is made, in its high word, by -// the current source file ID and in its low word, by the line number; the -// three other ones are user-defined. -// -// In order to avoid redefinition of the same file ID in different source files, -// we gather all of them here, so that you will have to add (or remove) a new -// one as soon as you add (or remove) a source file from the NPFS driver code. -// -// To use the NpBugCheck macro in a source file, define at its beginning -// the constant NPFS_BUGCHECK_FILE_ID with one of the following file IDs, -// then use the bugcheck macro wherever you want. -// -#define NPFS_BUGCHECK_CLEANUP 0x0001 -#define NPFS_BUGCHECK_CLOSE 0x0002 -#define NPFS_BUGCHECK_CREATE 0x0003 -#define NPFS_BUGCHECK_DATASUP 0x0004 -#define NPFS_BUGCHECK_FILEINFO 0x0005 -#define NPFS_BUGCHECK_FILEOBSUP 0x0006 -#define NPFS_BUGCHECK_FLUSHBUF 0x0007 -#define NPFS_BUGCHECK_FSCTRL 0x0008 -#define NPFS_BUGCHECK_MAIN 0x0009 -#define NPFS_BUGCHECK_PREFXSUP 0x000a -#define NPFS_BUGCHECK_READ 0x000b -#define NPFS_BUGCHECK_READSUP 0x000c -#define NPFS_BUGCHECK_SECURSUP 0x000d -#define NPFS_BUGCHECK_SEINFO 0x000e -#define NPFS_BUGCHECK_STATESUP 0x000f -#define NPFS_BUGCHECK_STRUCSUP 0x0010 -#define NPFS_BUGCHECK_VOLINFO 0x0011 -#define NPFS_BUGCHECK_WAITSUP 0x0012 -#define NPFS_BUGCHECK_WRITE 0x0013 -#define NPFS_BUGCHECK_WRITESUP 0x0014 - -#define NpBugCheck(p1, p2, p3) \ - KeBugCheckEx(NPFS_FILE_SYSTEM, \ - (NPFS_BUGCHECK_FILE_ID << 16) | __LINE__, \ - (p1), (p2), (p3)) - -// -// Node Type Codes for NPFS -// -#define NPFS_NTC_VCB 1 -#define NPFS_NTC_ROOT_DCB 2 -#define NPFS_NTC_FCB 4 -#define NPFS_NTC_CCB 6 -#define NPFS_NTC_NONPAGED_CCB 7 -#define NPFS_NTC_ROOT_DCB_CCB 8 -typedef USHORT NODE_TYPE_CODE, *PNODE_TYPE_CODE; - -// -// Data Queue States -// -typedef enum _NP_DATA_QUEUE_STATE -{ - ReadEntries = 0, - WriteEntries = 1, - Empty = 2 -} NP_DATA_QUEUE_STATE; - -// -// Data Queue Entry Types -// -typedef enum _NP_DATA_QUEUE_ENTRY_TYPE -{ - Buffered = 0, - Unbuffered -} NP_DATA_QUEUE_ENTRY_TYPE; - -// -// An Input or Output Data Queue. Each CCB has two of these. -// -typedef struct _NP_DATA_QUEUE -{ - LIST_ENTRY Queue; - ULONG QueueState; - ULONG BytesInQueue; - ULONG EntriesInQueue; - ULONG QuotaUsed; - ULONG ByteOffset; - ULONG Quota; -} NP_DATA_QUEUE, *PNP_DATA_QUEUE; - -// -// The Entries that go into the Queue -// -typedef struct _NP_DATA_QUEUE_ENTRY -{ - LIST_ENTRY QueueEntry; - ULONG DataEntryType; - PIRP Irp; - ULONG QuotaInEntry; - PSECURITY_CLIENT_CONTEXT ClientSecurityContext; - ULONG DataSize; -} NP_DATA_QUEUE_ENTRY, *PNP_DATA_QUEUE_ENTRY; - -// -// A Wait Queue. Only the VCB has one of these. -// -typedef struct _NP_WAIT_QUEUE -{ - LIST_ENTRY WaitList; - KSPIN_LOCK WaitLock; -} NP_WAIT_QUEUE, *PNP_WAIT_QUEUE; - -// -// The Entries in the Queue above, one for each Waiter. -// -typedef struct _NP_WAIT_QUEUE_ENTRY -{ - PIRP Irp; - KDPC Dpc; - KTIMER Timer; - PNP_WAIT_QUEUE WaitQueue; - UNICODE_STRING AliasName; - PFILE_OBJECT FileObject; -} NP_WAIT_QUEUE_ENTRY, *PNP_WAIT_QUEUE_ENTRY; - -// -// The event buffer in the NonPaged CCB -// -typedef struct _NP_EVENT_BUFFER -{ - PKEVENT Event; -} NP_EVENT_BUFFER, *PNP_EVENT_BUFFER; - -// -// The CCB for the Root DCB -// -typedef struct _NP_ROOT_DCB_CCB -{ - NODE_TYPE_CODE NodeType; - PVOID Unknown; - ULONG Unknown2; -} NP_ROOT_DCB_CCB, *PNP_ROOT_DCB_FCB; - -// -// The header that both FCB and DCB share -// -typedef struct _NP_CB_HEADER -{ - NODE_TYPE_CODE NodeType; - LIST_ENTRY DcbEntry; - PVOID ParentDcb; - ULONG CurrentInstances; - ULONG ServerOpenCount; - PSECURITY_DESCRIPTOR SecurityDescriptor; -} NP_CB_HEADER, *PNP_CB_HEADER; - -// -// The footer that both FCB and DCB share -// -typedef struct _NP_CB_FOOTER -{ - UNICODE_STRING FullName; - UNICODE_STRING ShortName; - UNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry; -} NP_CB_FOOTER; - -// -// A Directory Control Block (DCB) -// -typedef struct _NP_DCB -{ - // - // Common Header - // - NP_CB_HEADER; - - // - // DCB-specific data - // - LIST_ENTRY NotifyList; - LIST_ENTRY NotifyList2; - LIST_ENTRY FcbList; -#ifndef _WIN64 - ULONG Pad; -#endif - - // - // Common Footer - // - NP_CB_FOOTER; -} NP_DCB, *PNP_DCB; - -// -// A File Control BLock (FCB) -// -typedef struct _NP_FCB -{ - // - // Common Header - // - NP_CB_HEADER; - - // - // FCB-specific fields - // - ULONG MaximumInstances; - USHORT NamedPipeConfiguration; - USHORT NamedPipeType; - LARGE_INTEGER Timeout; - LIST_ENTRY CcbList; -#ifdef _WIN64 - PVOID Pad[2]; -#endif - - // - // Common Footer - // - NP_CB_FOOTER; -} NP_FCB, *PNP_FCB; - -C_ASSERT(FIELD_OFFSET(NP_FCB, PrefixTableEntry) == FIELD_OFFSET(NP_DCB, PrefixTableEntry)); - -// -// The nonpaged portion of the CCB -// -typedef struct _NP_NONPAGED_CCB -{ - NODE_TYPE_CODE NodeType; - PNP_EVENT_BUFFER EventBuffer[2]; - ERESOURCE Lock; -} NP_NONPAGED_CCB, *PNP_NONPAGED_CCB; - -// -// A Client Control Block (CCB) -// -typedef struct _NP_CCB -{ - NODE_TYPE_CODE NodeType; - UCHAR NamedPipeState; - UCHAR ReadMode[2]; - UCHAR CompletionMode[2]; - SECURITY_QUALITY_OF_SERVICE ClientQos; - LIST_ENTRY CcbEntry; - PNP_FCB Fcb; - PFILE_OBJECT FileObject[2]; - PEPROCESS Process; - PVOID ClientSession; - PNP_NONPAGED_CCB NonPagedCcb; - NP_DATA_QUEUE DataQueue[2]; - PSECURITY_CLIENT_CONTEXT ClientContext; - LIST_ENTRY IrpList; -} NP_CCB, *PNP_CCB; - -// -// A Volume Control Block (VCB) -// -typedef struct _NP_VCB -{ - NODE_TYPE_CODE NodeType; - ULONG ReferenceCount; - PNP_DCB RootDcb; - UNICODE_PREFIX_TABLE PrefixTable; - ERESOURCE Lock; - RTL_GENERIC_TABLE EventTable; - NP_WAIT_QUEUE WaitQueue; -} NP_VCB, *PNP_VCB; - -extern PNP_VCB NpVcb; - - -/* FUNCTIONS ******************************************************************/ - -// -// Functions to lock/unlock the global VCB lock -// -FORCEINLINE -VOID -NpAcquireSharedVcb(VOID) -{ - /* Acquire the lock in shared mode */ - ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE); -} - -FORCEINLINE -VOID -NpAcquireExclusiveVcb(VOID) -{ - /* Acquire the lock in exclusive mode */ - ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE); -} - -FORCEINLINE -VOID -NpReleaseVcb(VOID) -{ - /* Release the lock */ - ExReleaseResourceLite(&NpVcb->Lock); -} - - - -// -// Function to process deferred IRPs outside the VCB lock but still within the -// critical region -// -VOID -FORCEINLINE -NpCompleteDeferredIrps(IN PLIST_ENTRY DeferredList) -{ - PLIST_ENTRY ThisEntry, NextEntry; - PIRP Irp; - - /* Loop the list */ - ThisEntry = DeferredList->Flink; - while (ThisEntry != DeferredList) - { - /* Remember the next entry, but don't switch to it yet */ - NextEntry = ThisEntry->Flink; - - /* Complete the IRP for this entry */ - Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry); - IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT); - - /* And now switch to the next one */ - ThisEntry = NextEntry; - } -} - -BOOLEAN -NTAPI -NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table, - IN PVOID Buffer); - -VOID -NTAPI -NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue); - - -NTSTATUS -NTAPI -NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue); - -PLIST_ENTRY -NTAPI -NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue, - IN PLIST_ENTRY List); - -PIRP -NTAPI -NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue, - IN BOOLEAN Flag, - IN PLIST_ENTRY List); - -NTSTATUS -NTAPI -NpAddDataQueueEntry(IN ULONG NamedPipeEnd, - IN PNP_CCB Ccb, - IN PNP_DATA_QUEUE DataQueue, - IN ULONG Who, - IN ULONG Type, - IN ULONG DataSize, - IN PIRP Irp, - IN PVOID Buffer, - IN ULONG ByteOffset); - -VOID -NTAPI -NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue, - IN PLIST_ENTRY List); - -NTSTATUS -NTAPI -NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue, - IN ULONG Quota); - -NTSTATUS -NTAPI -NpCreateCcb(IN PNP_FCB Fcb, - IN PFILE_OBJECT FileObject, - IN UCHAR State, - IN UCHAR ReadMode, - IN UCHAR CompletionMode, - IN ULONG InQuota, - IN ULONG OutQuota, - OUT PNP_CCB *NewCcb); - -NTSTATUS -NTAPI -NpCreateFcb(IN PNP_DCB Dcb, - IN PUNICODE_STRING PipeName, - IN ULONG MaximumInstances, - IN LARGE_INTEGER Timeout, - IN USHORT NamedPipeConfiguration, - IN USHORT NamedPipeType, - OUT PNP_FCB *NewFcb); - -NTSTATUS -NTAPI -NpCreateRootDcb(VOID); - -NTSTATUS -NTAPI -NpCreateRootDcbCcb(IN PNP_ROOT_DCB_FCB *NewRootCcb); - -VOID -NTAPI -NpInitializeVcb(VOID); - -VOID -NTAPI -NpDeleteCcb(IN PNP_CCB Ccb, - IN PLIST_ENTRY ListEntry); - -VOID -NTAPI -NpDeleteFcb(IN PNP_FCB Fcb, - IN PLIST_ENTRY ListEntry); - -NTSTATUS -NTAPI -NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -NTAPI -NpFsdCreate(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -NTAPI -NpFsdClose(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - - -NTSTATUS -NTAPI -NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -NTAPI -NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -NTAPI -NpSetConnectedPipeState(IN PNP_CCB Ccb, - IN PFILE_OBJECT FileObject, - IN PLIST_ENTRY List); - -NTSTATUS -NTAPI -NpSetListeningPipeState(IN PNP_CCB Ccb, - IN PIRP Irp, - IN PLIST_ENTRY List); - - -NTSTATUS -NTAPI -NpSetDisconnectedPipeState(IN PNP_CCB Ccb, - IN PLIST_ENTRY List); - -NTSTATUS -NTAPI -NpSetClosingPipeState(IN PNP_CCB Ccb, - IN PIRP Irp, - IN ULONG NamedPipeEnd, - IN PLIST_ENTRY List); - -VOID -NTAPI -NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext); - -NTSTATUS -NTAPI -NpImpersonateClientContext(IN PNP_CCB Ccb); - -VOID -NTAPI -NpCopyClientContext(IN PNP_CCB Ccb, - IN PNP_DATA_QUEUE_ENTRY DataQueueEntry); - -VOID -NTAPI -NpUninitializeSecurity(IN PNP_CCB Ccb); - -NTSTATUS -NTAPI -NpInitializeSecurity(IN PNP_CCB Ccb, - IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, - IN PETHREAD Thread); - -NTSTATUS -NTAPI -NpGetClientSecurityContext(IN ULONG NamedPipeEnd, - IN PNP_CCB Ccb, - IN PETHREAD Thread, - IN PSECURITY_CLIENT_CONTEXT *Context); - -VOID -NTAPI -NpSetFileObject(IN PFILE_OBJECT FileObject, - IN PVOID PrimaryContext, - IN PVOID Ccb, - IN ULONG NamedPipeEnd); - -NODE_TYPE_CODE -NTAPI -NpDecodeFileObject(IN PFILE_OBJECT FileObject, - OUT PVOID *PrimaryContext OPTIONAL, - OUT PNP_CCB *Ccb, - OUT PULONG NamedPipeEnd OPTIONAL); - -PNP_FCB -NTAPI -NpFindPrefix(IN PUNICODE_STRING Name, - IN ULONG CaseInsensitiveIndex, - IN PUNICODE_STRING Prefix); - -NTSTATUS -NTAPI -NpFindRelativePrefix(IN PNP_DCB Dcb, - IN PUNICODE_STRING Name, - IN ULONG CaseInsensitiveIndex, - IN PUNICODE_STRING Prefix, - OUT PNP_FCB *FoundFcb); - -VOID -NTAPI -NpCheckForNotify(IN PNP_DCB Dcb, - IN BOOLEAN SecondList, - IN PLIST_ENTRY List); - -NTSTATUS -NTAPI -NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue, - IN LARGE_INTEGER WaitTime, - IN PIRP Irp, - IN PUNICODE_STRING AliasName); - -NTSTATUS -NTAPI -NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue, - IN PUNICODE_STRING PipeName, - IN NTSTATUS Status, - IN PLIST_ENTRY ListEntry); - - -IO_STATUS_BLOCK -NTAPI -NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue, - IN BOOLEAN Peek, - IN BOOLEAN ReadOverflowOperation, - IN PVOID Buffer, - IN ULONG BufferSize, - IN ULONG Mode, - IN PNP_CCB Ccb, - IN PLIST_ENTRY List); - - -NTSTATUS -NTAPI -NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue, - IN ULONG Mode, - IN PVOID OutBuffer, - IN ULONG OutBufferSize, - IN ULONG PipeType, - OUT PULONG BytesWritten, - IN PNP_CCB Ccb, - IN ULONG NamedPipeEnd, - IN PETHREAD Thread, - IN PLIST_ENTRY List); - -NTSTATUS -NTAPI -NpFsdRead(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - - -NTSTATUS -NTAPI -NpFsdWrite(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -NTAPI -NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -NTAPI -NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -NTAPI -NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - - -NTSTATUS -NTAPI -NpFsdQuerySecurityInfo(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -NTAPI -NpFsdSetSecurityInfo(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -NTSTATUS -NTAPI -NpFsdQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -/* EOF */