NTSTATUS NTAPI NpInitializeSecurity(IN PNP_CCB Ccb, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, IN PETHREAD Thread) { PSECURITY_CLIENT_CONTEXT ClientContext; NTSTATUS Status; PAGED_CODE(); if (SecurityQos) { Ccb->ClientQos = *SecurityQos; } else { Ccb->ClientQos.Length = sizeof(Ccb->ClientQos); Ccb->ClientQos.ImpersonationLevel = SecurityImpersonation; Ccb->ClientQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; Ccb->ClientQos.EffectiveOnly = TRUE; } NpUninitializeSecurity(Ccb); if (Ccb->ClientQos.ContextTrackingMode == SECURITY_DYNAMIC_TRACKING) { Status = STATUS_SUCCESS; Ccb->ClientContext = NULL; return Status; } ClientContext = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, sizeof(*ClientContext), NPFS_CLIENT_SEC_CTX_TAG); Ccb->ClientContext = ClientContext; if (!ClientContext) return STATUS_INSUFFICIENT_RESOURCES; Status = SeCreateClientSecurity(Thread, &Ccb->ClientQos, 0, ClientContext); if (!NT_SUCCESS(Status)) { ExFreePool(Ccb->ClientContext); Ccb->ClientContext = NULL; } 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; }
VOID NTAPI NpDeleteCcb(IN PNP_CCB Ccb, IN PLIST_ENTRY ListEntry) { PNP_ROOT_DCB_FCB RootDcbCcb; PAGED_CODE(); RootDcbCcb = (PNP_ROOT_DCB_FCB)Ccb; if (Ccb->NodeType == NPFS_NTC_CCB) { RemoveEntryList(&Ccb->CcbEntry); --Ccb->Fcb->CurrentInstances; NpDeleteEventTableEntry(&NpVcb->EventTable, Ccb->NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END]); NpDeleteEventTableEntry(&NpVcb->EventTable, Ccb->NonPagedCcb->EventBuffer[FILE_PIPE_SERVER_END]); NpUninitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_INBOUND]); NpUninitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_OUTBOUND]); NpCheckForNotify(Ccb->Fcb->ParentDcb, FALSE, ListEntry); ExDeleteResourceLite(&Ccb->NonPagedCcb->Lock); NpUninitializeSecurity(Ccb); if (Ccb->ClientSession) { ExFreePool(Ccb->ClientSession); Ccb->ClientSession = NULL; } ExFreePool(Ccb->NonPagedCcb); } else if (RootDcbCcb->NodeType == NPFS_NTC_ROOT_DCB_CCB && RootDcbCcb->Unknown) { ExFreePool(RootDcbCcb->Unknown); } ExFreePool(Ccb); }
NTSTATUS NTAPI NpSetDisconnectedPipeState(IN PNP_CCB Ccb, IN PLIST_ENTRY List) { PIRP Irp; PNP_NONPAGED_CCB NonPagedCcb; NTSTATUS Status; PLIST_ENTRY NextEntry; PNP_EVENT_BUFFER EventBuffer; NonPagedCcb = Ccb->NonPagedCcb; switch (Ccb->NamedPipeState) { case FILE_PIPE_DISCONNECTED_STATE: Status = STATUS_PIPE_DISCONNECTED; break; case FILE_PIPE_LISTENING_STATE: while (!IsListEmpty(&Ccb->IrpList)) { NextEntry = RemoveHeadList(&Ccb->IrpList); Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry); if (IoSetCancelRoutine(Irp, NULL)) { Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED; InsertTailList(List, NextEntry); } else { InitializeListHead(NextEntry); } } Status = STATUS_SUCCESS; break; case FILE_PIPE_CONNECTED_STATE: EventBuffer = NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END]; while (Ccb->DataQueue[FILE_PIPE_INBOUND].QueueState != Empty) { Irp = NpRemoveDataQueueEntry(&Ccb->DataQueue[FILE_PIPE_INBOUND], FALSE, List); if (Irp) { Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED; InsertTailList(List, &Irp->Tail.Overlay.ListEntry); } } while (Ccb->DataQueue[FILE_PIPE_OUTBOUND].QueueState != Empty) { Irp = NpRemoveDataQueueEntry(&Ccb->DataQueue[FILE_PIPE_OUTBOUND], FALSE, List); if (Irp) { Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED; InsertTailList(List, &Irp->Tail.Overlay.ListEntry); } } if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); // drop down on purpose... queue will be empty so flush code is nop ASSERT(Ccb->DataQueue[FILE_PIPE_OUTBOUND].QueueState == Empty); case FILE_PIPE_CLOSING_STATE: EventBuffer = NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END]; while (Ccb->DataQueue[FILE_PIPE_INBOUND].QueueState != Empty) { Irp = NpRemoveDataQueueEntry(&Ccb->DataQueue[FILE_PIPE_INBOUND], FALSE, List); if (Irp) { Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED; InsertTailList(List, &Irp->Tail.Overlay.ListEntry); } } ASSERT(Ccb->DataQueue[FILE_PIPE_OUTBOUND].QueueState == Empty); NpDeleteEventTableEntry(&NpVcb->EventTable, EventBuffer); NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END] = NULL; NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE); Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL; NpUninitializeSecurity(Ccb); if (Ccb->ClientSession) { ExFreePool(Ccb->ClientSession); Ccb->ClientSession = NULL; } Status = STATUS_SUCCESS; break; default: NpBugCheck(Ccb->NamedPipeState, 0, 0); break; } Ccb->NamedPipeState = FILE_PIPE_DISCONNECTED_STATE; return Status; }
NTSTATUS NTAPI NpSetClosingPipeState(IN PNP_CCB Ccb, IN PIRP Irp, IN ULONG NamedPipeEnd, IN PLIST_ENTRY List) { PNP_NONPAGED_CCB NonPagedCcb; PNP_FCB Fcb; PLIST_ENTRY NextEntry; PNP_DATA_QUEUE ReadQueue, WriteQueue, DataQueue; PNP_EVENT_BUFFER EventBuffer; PIRP ListIrp; NonPagedCcb = Ccb->NonPagedCcb; Fcb = Ccb->Fcb; switch (Ccb->NamedPipeState) { case FILE_PIPE_LISTENING_STATE: ASSERT(NamedPipeEnd == FILE_PIPE_SERVER_END); while (!IsListEmpty(&Ccb->IrpList)) { NextEntry = RemoveHeadList(&Ccb->IrpList); ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry); if (IoSetCancelRoutine(ListIrp, NULL)) { ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN; InsertTailList(List, NextEntry); } else { InitializeListHead(NextEntry); } } // Drop on purpose case FILE_PIPE_DISCONNECTED_STATE: ASSERT(NamedPipeEnd == FILE_PIPE_SERVER_END); NpSetFileObject(Ccb->FileObject[FILE_PIPE_SERVER_END], NULL, NULL, TRUE); Ccb->FileObject[FILE_PIPE_SERVER_END] = NULL; NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE); Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL; NpDeleteCcb(Ccb, List); if (!Fcb->CurrentInstances) NpDeleteFcb(Fcb, List); break; case FILE_PIPE_CLOSING_STATE: if (NamedPipeEnd == FILE_PIPE_SERVER_END) { DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; } else { DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; } NpSetFileObject(Ccb->FileObject[FILE_PIPE_SERVER_END], NULL, NULL, TRUE); Ccb->FileObject[FILE_PIPE_SERVER_END] = NULL; NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE); Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL; while (DataQueue->QueueState != Empty) { ListIrp = NpRemoveDataQueueEntry(DataQueue, FALSE, List); if (ListIrp) { ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN; InsertTailList(List, &ListIrp->Tail.Overlay.ListEntry); } } NpUninitializeSecurity(Ccb); if (Ccb->ClientSession) { ExFreePool(Ccb->ClientSession); Ccb->ClientSession = NULL; } NpDeleteCcb(Ccb, List); if (!Fcb->CurrentInstances) NpDeleteFcb(Fcb, List); break; case FILE_PIPE_CONNECTED_STATE: if (NamedPipeEnd == FILE_PIPE_SERVER_END) { ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; NpSetFileObject(Ccb->FileObject[FILE_PIPE_SERVER_END], NULL, NULL, TRUE); Ccb->FileObject[FILE_PIPE_SERVER_END] = NULL; } else { ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE); Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL; } EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd]; Ccb->NamedPipeState = FILE_PIPE_CLOSING_STATE; while (ReadQueue->QueueState != Empty) { ListIrp = NpRemoveDataQueueEntry(ReadQueue, FALSE, List); if (ListIrp) { ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN; InsertTailList(List, &ListIrp->Tail.Overlay.ListEntry); } } while (WriteQueue->QueueState == ReadEntries) { ListIrp = NpRemoveDataQueueEntry(WriteQueue, FALSE, List); if (ListIrp) { ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN; InsertTailList(List, &ListIrp->Tail.Overlay.ListEntry); } } if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); break; default: NpBugCheck(Ccb->NamedPipeState, 0, 0); break; } return STATUS_SUCCESS; }