NTSTATUS NTAPI NpCommonQuerySecurityInfo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NODE_TYPE_CODE NodeTypeCode; PIO_STACK_LOCATION IoStack; NTSTATUS Status; PNP_FCB Fcb; PNP_CCB Ccb; ULONG NamedPipeEnd; PAGED_CODE(); IoStack = IoGetCurrentIrpStackLocation(Irp); NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, (PVOID*)&Fcb, &Ccb, &NamedPipeEnd); if (!NodeTypeCode) return STATUS_PIPE_DISCONNECTED; if (NodeTypeCode != NPFS_NTC_CCB) return STATUS_INVALID_PARAMETER; Status = SeQuerySecurityDescriptorInfo(&IoStack->Parameters.QuerySecurity.SecurityInformation, Irp->UserBuffer, &IoStack->Parameters.QuerySecurity.Length, &Fcb->SecurityDescriptor); if (Status == STATUS_BUFFER_TOO_SMALL) { Irp->IoStatus.Information = IoStack->Parameters.QuerySecurity.Length; Status = STATUS_BUFFER_OVERFLOW; } return Status; }
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 NpCommonFlushBuffers(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NODE_TYPE_CODE NodeTypeCode; PNP_CCB Ccb; ULONG NamedPipeEnd; NTSTATUS Status; PNP_DATA_QUEUE FlushQueue; PAGED_CODE(); NodeTypeCode = NpDecodeFileObject(IoGetCurrentIrpStackLocation(Irp)->FileObject, NULL, &Ccb, &NamedPipeEnd); if (NodeTypeCode != NPFS_NTC_CCB) return STATUS_PIPE_DISCONNECTED; ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE); if (NamedPipeEnd == FILE_PIPE_SERVER_END) { FlushQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; } else { FlushQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; } if (FlushQueue->QueueState == WriteEntries) { Status = NpAddDataQueueEntry(NamedPipeEnd, Ccb, FlushQueue, WriteEntries, 2, 0, Irp, NULL, 0); } else { Status = STATUS_SUCCESS; } ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); return Status; }
NTSTATUS NTAPI NpCommonSetSecurityInfo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NODE_TYPE_CODE NodeTypeCode; PIO_STACK_LOCATION IoStack; NTSTATUS Status; PNP_FCB Fcb; PNP_CCB Ccb; ULONG NamedPipeEnd; PSECURITY_DESCRIPTOR OldSecurityDescriptor; PSECURITY_DESCRIPTOR TempSecurityDescriptor; PSECURITY_DESCRIPTOR NewSecurityDescriptor; PAGED_CODE(); IoStack = IoGetCurrentIrpStackLocation(Irp); NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, (PVOID*)&Fcb, &Ccb, &NamedPipeEnd); if (!NodeTypeCode) return STATUS_PIPE_DISCONNECTED; if (NodeTypeCode != NPFS_NTC_CCB) return STATUS_INVALID_PARAMETER; OldSecurityDescriptor = TempSecurityDescriptor = Fcb->SecurityDescriptor; Status = SeSetSecurityDescriptorInfo(NULL, &IoStack->Parameters.SetSecurity.SecurityInformation, IoStack->Parameters.SetSecurity.SecurityDescriptor, &TempSecurityDescriptor, TRUE, IoGetFileObjectGenericMapping()); if (!NT_SUCCESS(Status)) return Status; Status = ObLogSecurityDescriptor(TempSecurityDescriptor, &NewSecurityDescriptor, 1); ASSERT(TempSecurityDescriptor != OldSecurityDescriptor); ExFreePoolWithTag(TempSecurityDescriptor, 0); if (!NT_SUCCESS(Status)) return Status; Fcb->SecurityDescriptor = NewSecurityDescriptor; ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1); 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; }
BOOLEAN NTAPI NpCommonRead(IN PFILE_OBJECT FileObject, IN PVOID Buffer, IN ULONG BufferSize, OUT PIO_STATUS_BLOCK IoStatus, IN PIRP Irp, IN PLIST_ENTRY List) { NODE_TYPE_CODE NodeType; PNP_DATA_QUEUE ReadQueue; PNP_EVENT_BUFFER EventBuffer; NTSTATUS Status; ULONG NamedPipeEnd; PNP_CCB Ccb; PNP_NONPAGED_CCB NonPagedCcb; BOOLEAN ReadOk; PAGED_CODE(); IoStatus->Information = 0; NodeType = NpDecodeFileObject(FileObject, NULL, &Ccb, &NamedPipeEnd); if (!NodeType) { IoStatus->Status = STATUS_PIPE_DISCONNECTED; return TRUE; } if (NodeType != NPFS_NTC_CCB) { IoStatus->Status = STATUS_INVALID_PARAMETER; return TRUE; } NonPagedCcb = Ccb->NonPagedCcb; ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE); if (Ccb->NamedPipeState == FILE_PIPE_DISCONNECTED_STATE || Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) { IoStatus->Status = Ccb->NamedPipeState != FILE_PIPE_DISCONNECTED_STATE ? STATUS_PIPE_LISTENING : STATUS_PIPE_DISCONNECTED; ReadOk = TRUE; goto Quickie; } ASSERT((Ccb->NamedPipeState == FILE_PIPE_CONNECTED_STATE) || (Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE)); if ((NamedPipeEnd == FILE_PIPE_SERVER_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND) || (NamedPipeEnd == FILE_PIPE_CLIENT_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND)) { IoStatus->Status = STATUS_INVALID_PARAMETER; ReadOk = TRUE; goto Quickie; } if (NamedPipeEnd == FILE_PIPE_SERVER_END) { ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; } else { ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; } EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd]; if (ReadQueue->QueueState == WriteEntries) { *IoStatus = NpReadDataQueue(ReadQueue, FALSE, FALSE, Buffer, BufferSize, Ccb->ReadMode[NamedPipeEnd], Ccb, List); if (!NT_SUCCESS(IoStatus->Status)) { ReadOk = TRUE; goto Quickie; } ReadOk = TRUE; if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); goto Quickie; } if (Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE) { IoStatus->Status = STATUS_PIPE_BROKEN; ReadOk = TRUE; if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); goto Quickie; } if (Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION) { IoStatus->Status = STATUS_PIPE_EMPTY; ReadOk = TRUE; if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); goto Quickie; } if (!Irp) { ReadOk = FALSE; goto Quickie; } Status = NpAddDataQueueEntry(NamedPipeEnd, Ccb, ReadQueue, ReadEntries, Buffered, BufferSize, Irp, NULL, 0); IoStatus->Status = Status; if (!NT_SUCCESS(Status)) { ReadOk = FALSE; } else { ReadOk = TRUE; if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); } Quickie: ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); return ReadOk; }
NTSTATUS NpCommonSetInformation ( IN PNPFS_DEVICE_OBJECT NpfsDeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the common routine for creating/opening a file. Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - the return status for the operation --*/ { PIO_STACK_LOCATION IrpSp; NTSTATUS Status; ULONG Length; FILE_INFORMATION_CLASS FileInformationClass; PVOID Buffer; NODE_TYPE_CODE NodeTypeCode; PFCB Fcb; PCCB Ccb; NAMED_PIPE_END NamedPipeEnd; PAGED_CODE(); // // Get the current Irp stack location // IrpSp = IoGetCurrentIrpStackLocation( Irp ); DebugTrace(+1, Dbg, "NpCommonSetInformation...\n", 0); DebugTrace( 0, Dbg, " Irp = %08lx\n", Irp); DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.SetFile.Length); DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", IrpSp->Parameters.SetFile.FileInformationClass); DebugTrace( 0, Dbg, " ->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer); // // Get the ccb and figure out who we are, and make sure we're not // disconnected. // if ((NodeTypeCode = NpDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb, &NamedPipeEnd )) == NTC_UNDEFINED) { DebugTrace(0, Dbg, "Pipe is disconnected from us\n", 0); NpCompleteRequest( Irp, STATUS_PIPE_DISCONNECTED ); Status = STATUS_PIPE_DISCONNECTED; DebugTrace(-1, Dbg, "NpCommonSetInformation -> %08lx\n", Status ); return Status; } // // Case on the type of the context, We can only query information // on an Fcb, Dcb, or Root Dcb. If we are not passed on of these // we immediately tell the caller that there is an invalid parameter. // if (NodeTypeCode != NPFS_NTC_CCB) { NpCompleteRequest( Irp, STATUS_INVALID_PARAMETER ); DebugTrace(-1, Dbg, "NpCommonQueryInformation -> STATUS_INVALID_PARAMETER\n", 0); return STATUS_INVALID_PARAMETER; } // // Reference our input parameter to make things easier // Length = IrpSp->Parameters.SetFile.Length; FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass; Buffer = Irp->AssociatedIrp.SystemBuffer; // // Based on the information class we'll do differnt actions. Each // procedure that we're calling will complete the request. // switch (FileInformationClass) { case FileBasicInformation: Status = NpSetBasicInfo( Ccb, Buffer ); break; case FilePipeInformation: Status = NpSetPipeInfo( Fcb, Ccb, Buffer, NamedPipeEnd ); break; default: Status = STATUS_INVALID_PARAMETER; break; } // // complete the request // NpCompleteRequest( Irp, Status ); DebugTrace(-1, Dbg, "NpCommonSetInformation -> %08lx\n", Status); return Status; }
NTSTATUS NpCommonQueryInformation ( IN PNPFS_DEVICE_OBJECT NpfsDeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the common routine for creating/opening a file. Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - the return status for the operation --*/ { PIO_STACK_LOCATION IrpSp; NTSTATUS Status; ULONG Length; FILE_INFORMATION_CLASS FileInformationClass; PVOID Buffer; NODE_TYPE_CODE NodeTypeCode; PFCB Fcb; PCCB Ccb; NAMED_PIPE_END NamedPipeEnd; PFILE_ALL_INFORMATION AllInfo; PAGED_CODE(); // // Get the current stack location // IrpSp = IoGetCurrentIrpStackLocation( Irp ); DebugTrace(+1, Dbg, "NpCommonQueryInformation...\n", 0); DebugTrace( 0, Dbg, " Irp = %08lx\n", Irp); DebugTrace( 0, Dbg, " ->Length = %08lx\n", IrpSp->Parameters.QueryFile.Length); DebugTrace( 0, Dbg, " ->FileInformationClass = %08lx\n", IrpSp->Parameters.QueryFile.FileInformationClass); DebugTrace( 0, Dbg, " ->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer); // // Get the ccb and figure out who we are, and make sure we're not // disconnected. // if ((NodeTypeCode = NpDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb, &NamedPipeEnd )) == NTC_UNDEFINED) { DebugTrace(0, Dbg, "Pipe is disconnected from us\n", 0); NpCompleteRequest( Irp, STATUS_PIPE_DISCONNECTED ); Status = STATUS_PIPE_DISCONNECTED; DebugTrace(-1, Dbg, "NpCommonQueryInformation -> %08lx\n", Status ); return Status; } // // Case on the type of the context, We can only query information // on an Fcb, Dcb, or Root Dcb. If we are not passed on of these // we immediately tell the caller that there is an invalid parameter. // if (NodeTypeCode != NPFS_NTC_CCB) { DebugTrace(0, Dbg, "Node type code is not ccb\n", 0); NpCompleteRequest( Irp, STATUS_INVALID_PARAMETER ); DebugTrace(-1, Dbg, "NpCommonQueryInformation -> STATUS_INVALID_PARAMETER\n", 0); return STATUS_INVALID_PARAMETER; } // // Reference our input parameter to make things easier // Length = IrpSp->Parameters.QueryFile.Length; FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass; Buffer = Irp->AssociatedIrp.SystemBuffer; // // Based on the information class we'll do different actions. Each // of the procedure that we're calling fill up as much of the // buffer as possible and return the remaining length, and status // This is done so that we can use them to build up the // FileAllInformation request. These procedures do not complete the // Irp, instead this procedure must complete the Irp. // switch (FileInformationClass) { case FileAllInformation: // // For the all information class we'll typecast a local // pointer to the output buffer and then call the // individual routines to fill in the buffer. // AllInfo = Buffer; Length -= (sizeof(FILE_ACCESS_INFORMATION) + sizeof(FILE_MODE_INFORMATION) + sizeof(FILE_ALIGNMENT_INFORMATION)); // // Only the QueryName call can return non-success // (VOID)NpQueryBasicInfo( Ccb, &AllInfo->BasicInformation, &Length ); (VOID)NpQueryStandardInfo( Ccb, &AllInfo->StandardInformation, &Length ); (VOID)NpQueryInternalInfo( Ccb, &AllInfo->InternalInformation, &Length ); (VOID)NpQueryEaInfo( Ccb, &AllInfo->EaInformation, &Length ); (VOID)NpQueryPositionInfo( Ccb, &AllInfo->PositionInformation, &Length, NamedPipeEnd ); Status = NpQueryNameInfo( Ccb, &AllInfo->NameInformation, &Length ); break; case FileBasicInformation: Status = NpQueryBasicInfo( Ccb, Buffer, &Length ); break; case FileStandardInformation: Status = NpQueryStandardInfo( Ccb, Buffer, &Length ); break; case FileInternalInformation: Status = NpQueryInternalInfo( Ccb, Buffer, &Length ); break; case FileEaInformation: Status = NpQueryEaInfo( Ccb, Buffer, &Length ); break; case FilePositionInformation: Status = NpQueryPositionInfo( Ccb, Buffer, &Length, NamedPipeEnd ); break; case FileNameInformation: Status = NpQueryNameInfo( Ccb, Buffer, &Length ); break; case FilePipeInformation: Status = NpQueryPipeInfo( Fcb, Ccb, Buffer, &Length, NamedPipeEnd ); break; case FilePipeLocalInformation: Status = NpQueryPipeLocalInfo( Fcb, Ccb, Buffer, &Length, NamedPipeEnd ); break; default: Status = STATUS_INVALID_PARAMETER; break; } // // Set the information field to the number of bytes actually filled in // and then complete the request // Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length; NpCompleteRequest( Irp, Status ); DebugTrace(-1, Dbg, "NpCommonQueryInformation -> %08lx\n", Status ); return Status; }
NTSTATUS NpCommonFlushBuffers ( IN PNPFS_DEVICE_OBJECT NpfsDeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the common routine for Flushing buffers for a file. Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - the return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; PCCB Ccb; NAMED_PIPE_END NamedPipeEnd; PDATA_QUEUE WriteQueue; // // Get the current stack location // PAGED_CODE(); IrpSp = IoGetCurrentIrpStackLocation( Irp ); DebugTrace(+1, Dbg, "NpCommonFlushBuffers\n", 0); DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp); DebugTrace( 0, Dbg, "FileObject = %08lx\n", IrpSp->FileObject); // // Decode the file object to figure out who we are. If the result // is not a ccb then the pipe has been disconnected. We don't need the // Fcb back from the call // if (NpDecodeFileObject( IrpSp->FileObject, NULL, &Ccb, &NamedPipeEnd ) != NPFS_NTC_CCB) { DebugTrace(0, Dbg, "Pipe is disconnected from us\n", 0); NpCompleteRequest( Irp, STATUS_PIPE_DISCONNECTED ); Status = STATUS_PIPE_DISCONNECTED; DebugTrace(-1, Dbg, "NpCommonFlushBuffers -> %08lx\n", Status ); return Status; } NpAcquireExclusiveCcb(Ccb); try { // // Figure out the data queue that the flush buffer is // targetted at. It is the queue that we do writes into // if (NamedPipeEnd == FILE_PIPE_SERVER_END) { WriteQueue = &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ]; } else { WriteQueue = &Ccb->DataQueue[ FILE_PIPE_INBOUND ]; } // // Now from the write queue check if contains write entries. If // it does not contain write entries then we immediately complete // this irp with success because there isn't anything to flush // if (!NpIsDataQueueWriters( WriteQueue )) { DebugTrace(0, Dbg, "Pipe does not contain write entries\n", 0); NpCompleteRequest( Irp, STATUS_SUCCESS ); try_return(Status = STATUS_SUCCESS); } // // Otherwise the queue is full of writes so we simply // enqueue this irp to the back to the queue and set our // return status to pending, also mark the irp pending // IoMarkIrpPending( Irp ); (VOID)NpAddDataQueueEntry( WriteQueue, WriteEntries, Flush, 0, Irp, NULL ); Status = STATUS_PENDING; try_exit: NOTHING; } finally { NpReleaseCcb(Ccb); } DebugTrace(-1, Dbg, "NpCommonFlushBuffers -> %08lx\n", Status); return Status; }
NTSTATUS NpCommonClose ( IN PNPFS_DEVICE_OBJECT NpfsDeviceObject, IN PIRP Irp ) /*++ Routine Description: This is the common routine for creating/opening a file. Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - the return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; NODE_TYPE_CODE NodeTypeCode; PFCB Fcb; PCCB Ccb; PAGED_CODE(); // // Get the current stack location // IrpSp = IoGetCurrentIrpStackLocation( Irp ); DebugTrace(+1, Dbg, "NpCommonClose...\n", 0); DebugTrace( 0, Dbg, " Irp = %08lx\n", Irp); // // Now acquire exclusive access to the vcb // NpAcquireExclusiveVcb(); try { // // Decode the file object to figure out who we are. If the result // is null then the pipe has been disconnected. // if ((NodeTypeCode = NpDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb, NULL )) == NTC_UNDEFINED) { DebugTrace(0, Dbg, "Pipe is disconnected from us\n", 0); NpCompleteRequest( Irp, STATUS_PIPE_DISCONNECTED ); try_return( Status = STATUS_PIPE_DISCONNECTED ); } // // Now case on the type of file object we're closing // switch (NodeTypeCode) { case NPFS_NTC_VCB: // // Decrement the Open count and clear our fields in the file object // NpVcb->OpenCount -= 1; NpSetFileObject( IrpSp->FileObject, NULL, NULL, FILE_PIPE_SERVER_END ); break; case NPFS_NTC_ROOT_DCB: // // Decrement the Open count and clear our fields in the file object // Fcb->OpenCount -= 1; NpSetFileObject( IrpSp->FileObject, NULL, NULL, FILE_PIPE_SERVER_END ); // // Remove the root dcb ccb. // NpDeleteCcb( Ccb ); break; case NPFS_NTC_CCB: break; } // // Complete the close irp // NpCompleteRequest( Irp, STATUS_SUCCESS ); Status = STATUS_SUCCESS; try_exit: NOTHING; } finally { NpReleaseVcb( ); } DebugTrace(-1, Dbg, "NpCommonClose -> %08lx\n", Status); return Status; }
NTSTATUS NTAPI NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStackLocation; NODE_TYPE_CODE NodeTypeCode; PNP_CCB Ccb; PNP_CLIENT_PROCESS ClientSession, QueryBuffer; ULONG Length; PAGED_CODE(); /* Get the current stack location */ IoStackLocation = IoGetCurrentIrpStackLocation(Irp); /* Decode the file object and check the node type */ NodeTypeCode = NpDecodeFileObject(IoStackLocation->FileObject, 0, &Ccb, 0); if (NodeTypeCode != NPFS_NTC_CCB) { return STATUS_PIPE_DISCONNECTED; } /* Get the length of the query buffer */ Length = IoStackLocation->Parameters.QueryFile.Length; if (Length < 8) { return STATUS_INVALID_PARAMETER; } QueryBuffer = Irp->AssociatedIrp.SystemBuffer; /* Lock the Ccb */ ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE); /* Get the CCBs client session and check if it's set */ ClientSession = Ccb->ClientSession; if (ClientSession != NULL) { /* Copy first 2 fields */ QueryBuffer->Unknown = ClientSession->Unknown; QueryBuffer->Process = ClientSession->Process; } else { /* Copy the process from the CCB */ QueryBuffer->Unknown = NULL; QueryBuffer->Process = Ccb->Process; } /* Does the caller provide a large enough buffer for the full data? */ if (Length >= sizeof(NP_CLIENT_PROCESS)) { Irp->IoStatus.Information = sizeof(NP_CLIENT_PROCESS); /* Do we have a ClientSession structure? */ if (ClientSession != NULL) { /* Copy length and the data */ QueryBuffer->DataLength = ClientSession->DataLength; RtlCopyMemory(QueryBuffer->Buffer, ClientSession->Buffer, ClientSession->DataLength); /* NULL terminate the buffer */ NT_ASSERT(QueryBuffer->DataLength <= 30); QueryBuffer->Buffer[QueryBuffer->DataLength / sizeof(WCHAR)] = 0; } else { /* No data */ QueryBuffer->DataLength = 0; QueryBuffer->Buffer[0] = 0; } } else { Irp->IoStatus.Information = FIELD_OFFSET(NP_CLIENT_PROCESS, DataLength); } /* Unlock the Ccb */ ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); return STATUS_SUCCESS; }
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 NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStackLocation; NODE_TYPE_CODE NodeTypeCode; PNP_CCB Ccb; ULONG Length; PNP_CLIENT_PROCESS InputBuffer, ClientSession, OldClientSession; PAGED_CODE(); /* Get the current stack location */ IoStackLocation = IoGetCurrentIrpStackLocation(Irp); /* Only kernel calls are allowed! */ if (IoStackLocation->MinorFunction != IRP_MN_KERNEL_CALL) { return STATUS_ACCESS_DENIED; } /* Decode the file object and check the node type */ NodeTypeCode = NpDecodeFileObject(IoStackLocation->FileObject, 0, &Ccb, 0); if (NodeTypeCode != NPFS_NTC_CCB) { return STATUS_PIPE_DISCONNECTED; } /* Get the length of the query buffer and check if it's valid */ Length = IoStackLocation->Parameters.QueryFile.Length; if (Length != sizeof(NP_CLIENT_PROCESS)) { return STATUS_INVALID_PARAMETER; } /* Get the buffer and check if the data Length is valid */ InputBuffer = Irp->AssociatedIrp.SystemBuffer; if (InputBuffer->DataLength > 30) { return STATUS_INVALID_PARAMETER; } /* Allocate a new structure */ ClientSession = ExAllocatePoolWithQuotaTag(PagedPool, sizeof(NP_CLIENT_PROCESS), 'iFpN'); /* Copy the full input buffer */ RtlCopyMemory(ClientSession, InputBuffer, sizeof(NP_CLIENT_PROCESS)); /* Lock the Ccb */ ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE); /* Get the old ClientSession and set the new */ OldClientSession = Ccb->ClientSession; Ccb->ClientSession = ClientSession; /* Copy the process to the CCB */ Ccb->Process = ClientSession->Process; /* Unlock the Ccb */ ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); /* Check if there was already a ClientSession */ if (OldClientSession != NULL) { /* Free it */ ExFreePoolWithTag(OldClientSession, 'iFpN'); } return STATUS_SUCCESS; }
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)
BOOLEAN NTAPI NpCommonWrite(IN PFILE_OBJECT FileObject, IN PVOID Buffer, IN ULONG DataSize, IN PETHREAD Thread, IN PIO_STATUS_BLOCK IoStatus, IN PIRP Irp, IN PLIST_ENTRY List) { NODE_TYPE_CODE NodeType; BOOLEAN WriteOk; PNP_CCB Ccb; PNP_NONPAGED_CCB NonPagedCcb; PNP_DATA_QUEUE WriteQueue; NTSTATUS Status; PNP_EVENT_BUFFER EventBuffer; ULONG BytesWritten, NamedPipeEnd, ReadMode; PAGED_CODE(); IoStatus->Information = 0; NodeType = NpDecodeFileObject(FileObject, NULL, &Ccb, &NamedPipeEnd); if (!NodeType) { IoStatus->Status = STATUS_PIPE_DISCONNECTED; return TRUE; } if (NodeType != NPFS_NTC_CCB) { IoStatus->Status = STATUS_INVALID_PARAMETER; return TRUE; } NonPagedCcb = Ccb->NonPagedCcb; ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE); if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE) { if (Ccb->NamedPipeState == FILE_PIPE_DISCONNECTED_STATE) { IoStatus->Status = STATUS_PIPE_DISCONNECTED; } else if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) { IoStatus->Status = STATUS_PIPE_LISTENING; } else { ASSERT(Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE); IoStatus->Status = STATUS_PIPE_CLOSING; } WriteOk = TRUE; goto Quickie; } if ((NamedPipeEnd == FILE_PIPE_SERVER_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND) || (NamedPipeEnd == FILE_PIPE_CLIENT_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND)) { IoStatus->Status = STATUS_INVALID_PARAMETER; WriteOk = TRUE; goto Quickie; } IoStatus->Status = STATUS_SUCCESS; IoStatus->Information = DataSize; if (NamedPipeEnd == FILE_PIPE_SERVER_END) { WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; ReadMode = Ccb->ReadMode[FILE_PIPE_CLIENT_END]; } else { WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; ReadMode = Ccb->ReadMode[FILE_PIPE_SERVER_END]; } EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd]; if ((WriteQueue->QueueState == ReadEntries && WriteQueue->BytesInQueue < DataSize && WriteQueue->Quota < DataSize - WriteQueue->BytesInQueue) || (WriteQueue->QueueState == ReadEntries && WriteQueue->Quota - WriteQueue->QuotaUsed < DataSize)) { if (Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE && Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION) { IoStatus->Information = 0; IoStatus->Status = STATUS_SUCCESS; WriteOk = TRUE; goto Quickie; } if (!Irp) { WriteOk = FALSE; goto Quickie; } } Status = NpWriteDataQueue(WriteQueue, ReadMode, Buffer, DataSize, Ccb->Fcb->NamedPipeType, &BytesWritten, Ccb, NamedPipeEnd, Thread, List); IoStatus->Status = Status; if (Status == STATUS_MORE_PROCESSING_REQUIRED) { ASSERT(WriteQueue->QueueState != ReadEntries); if ((Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION || !Irp) && ((WriteQueue->Quota - WriteQueue->QuotaUsed) < BytesWritten)) { IoStatus->Information = DataSize - BytesWritten; IoStatus->Status = STATUS_SUCCESS; } else { ASSERT(WriteQueue->QueueState != ReadEntries); IoStatus->Status = NpAddDataQueueEntry(NamedPipeEnd, Ccb, WriteQueue, WriteEntries, Buffered, DataSize, Irp, Buffer, DataSize - BytesWritten); } } if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); WriteOk = TRUE; Quickie: ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); return WriteOk; }
NTSTATUS NpCommonDirectoryControl ( IN PNPFS_DEVICE_OBJECT NpfsDeviceObject, IN PIRP Irp ) /*++ Routine Description: This routine does the common code for directory control functions. Arguments: NpfsDeviceObject - Supplies the named pipe device object Irp - Supplies the Irp being processed Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp; PFCB Fcb; PROOT_DCB_CCB Ccb; PAGED_CODE(); // // Get the current stack location // IrpSp = IoGetCurrentIrpStackLocation( Irp ); DebugTrace(+1, Dbg, "NpCommonDirectoryControl...\n", 0); DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp); // // Decode the file object to figure out who we are. If the result // is not the root dcb then its an illegal parameter. // if (NpDecodeFileObject( IrpSp->FileObject, &Fcb, (PCCB *)&Ccb, NULL ) != NPFS_NTC_ROOT_DCB) { DebugTrace(0, Dbg, "Not a directory\n", 0); NpCompleteRequest( Irp, STATUS_INVALID_PARAMETER ); Status = STATUS_INVALID_PARAMETER; DebugTrace(-1, Dbg, "NpCommonDirectoryControl -> %08lx\n", Status ); return Status; } // // We know this is a directory control so we'll case on the // minor function, and call the appropriate work routines. // switch (IrpSp->MinorFunction) { case IRP_MN_QUERY_DIRECTORY: Status = NpQueryDirectory( Fcb, Ccb, Irp ); break; case IRP_MN_NOTIFY_CHANGE_DIRECTORY: Status = NpNotifyChangeDirectory( Fcb, Ccb, Irp ); break; default: // // For all other minor function codes we say they're invalid // and complete the request. // DebugTrace(0, DEBUG_TRACE_ERROR, "Invalid FS Control Minor Function Code %08lx\n", IrpSp->MinorFunction); NpCompleteRequest( Irp, STATUS_INVALID_DEVICE_REQUEST ); Status = STATUS_INVALID_DEVICE_REQUEST; break; } DebugTrace(-1, Dbg, "NpCommonDirectoryControl -> %08lx\n", Status); return Status; }