NTSTATUS NTAPI NpGetClientSecurityContext(IN ULONG NamedPipeEnd, IN PNP_CCB Ccb, IN PETHREAD Thread, IN PSECURITY_CLIENT_CONTEXT *Context) { PSECURITY_CLIENT_CONTEXT NewContext; NTSTATUS Status; PAGED_CODE(); if (NamedPipeEnd == FILE_PIPE_SERVER_END || Ccb->ClientQos.ContextTrackingMode != SECURITY_DYNAMIC_TRACKING) { NewContext = NULL; Status = STATUS_SUCCESS; } else { NewContext = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, sizeof(*NewContext), NPFS_CLIENT_SEC_CTX_TAG); if (!NewContext) return STATUS_INSUFFICIENT_RESOURCES; Status = SeCreateClientSecurity(Thread, &Ccb->ClientQos, 0, NewContext); if (!NT_SUCCESS(Status)) { ExFreePool(NewContext); NewContext = NULL; } } *Context = NewContext; return Status; }
/*++ * @name FsRtlAllocatePoolWithQuota * @implemented * * FILLME * * @param PoolType * FILLME * * @param NumberOfBytes * FILLME * * @return None * * @remarks The pool tag used is "FSrt". * *--*/ PVOID NTAPI FsRtlAllocatePoolWithQuota(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes) { PVOID Address; Address = ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, IFS_POOL_TAG); if (NULL == Address) { ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); } return Address; }
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 powerlinkCreate(PDEVICE_OBJECT pDeviceObject_p, PIRP pIrp_p) { NDIS_TIMER_CHARACTERISTICS timerChars; tFileContext* pFileContext; PIO_STACK_LOCATION irpStack; NDIS_STATUS status; UNUSED_PARAMETER(pDeviceObject_p); DEBUG_LVL_ALWAYS_TRACE("PLK: + %s() ...\n", __func__); if (pIrp_p == NULL) return NDIS_STATUS_RESOURCES; irpStack = IoGetCurrentIrpStackLocation(pIrp_p); pFileContext = ExAllocatePoolWithQuotaTag(NonPagedPool, sizeof(tFileContext), PLK_MEM_TAG); if (pFileContext == NULL) { DEBUG_LVL_ERROR_TRACE("PLK: Failed to create file context\n"); } IoInitializeRemoveLock(&pFileContext->driverAccessLock, PLK_MEM_TAG, 0, 0); irpStack->FileObject->FsContext = (void*)pFileContext; if (!plkDriverInstance_l.fInitialized) { NdisZeroMemory(&timerChars, sizeof(timerChars)); C_ASSERT(NDIS_SIZEOF_TIMER_CHARACTERISTICS_REVISION_1 <= sizeof(timerChars)); timerChars.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS; timerChars.Header.Size = NDIS_SIZEOF_TIMER_CHARACTERISTICS_REVISION_1; timerChars.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1; timerChars.TimerFunction = increaseHeartbeatCb; timerChars.FunctionContext = NULL; timerChars.AllocationTag = PLK_MEM_TAG; status = NdisAllocateTimerObject(plkDriverInstance_l.driverHandle, &timerChars, &heartbeatTimer_l); if (status != NDIS_STATUS_SUCCESS) { DEBUG_LVL_ERROR_TRACE("%s() Timer Creation Failed %x\n", __func__, status); return STATUS_SUCCESS; } if (ctrlk_init(NULL) != kErrorOk) { return NDIS_STATUS_RESOURCES; } startHeartbeatTimer(20); plkDriverInstance_l.fInitialized = TRUE; } // Increase the count for open instances plkDriverInstance_l.instanceCount++; pIrp_p->IoStatus.Information = 0; pIrp_p->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(pIrp_p, IO_NO_INCREMENT); DEBUG_LVL_ALWAYS_TRACE("PLK: + %s() - OK\n", __func__); return STATUS_SUCCESS; }
NTSYSAPI NTSTATUS NTAPI NtQueueApcThread( IN HANDLE ThreadHandle, IN PPS_APC_ROUTINE ApcRoutine, IN PVOID ApcArgument1, IN PVOID ApcArgument2, IN PVOID ApcArgument3 ) /*++ Routine Description: This function is used to queue a user-mode APC to the specified thread. The APC will fire when the specified thread does an alertable wait Arguments: ThreadHandle - Supplies a handle to a thread object. The caller must have THREAD_SET_CONTEXT access to the thread. ApcRoutine - Supplies the address of the APC routine to execute when the APC fires. ApcArgument1 - Supplies the first PVOID passed to the APC ApcArgument2 - Supplies the second PVOID passed to the APC ApcArgument3 - Supplies the third PVOID passed to the APC Return Value: Returns an NT Status code indicating success or failure of the API --*/ { PETHREAD Thread; NTSTATUS st; KPROCESSOR_MODE Mode; KIRQL Irql; PKAPC Apc; PAGED_CODE(); Mode = KeGetPreviousMode(); st = ObReferenceObjectByHandle( ThreadHandle, THREAD_SET_CONTEXT, PsThreadType, Mode, (PVOID *)&Thread, NULL ); if ( NT_SUCCESS(st) ) { st = STATUS_SUCCESS; if ( IS_SYSTEM_THREAD(Thread) ) { st = STATUS_INVALID_HANDLE; } else { Apc = ExAllocatePoolWithQuotaTag( (NonPagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE), sizeof(*Apc), 'pasP' ); if ( !Apc ) { st = STATUS_NO_MEMORY; } else { KeInitializeApc( Apc, &Thread->Tcb, OriginalApcEnvironment, PspQueueApcSpecialApc, NULL, (PKNORMAL_ROUTINE)ApcRoutine, UserMode, ApcArgument1 ); if ( !KeInsertQueueApc(Apc,ApcArgument2,ApcArgument3,0) ) { ExFreePool(Apc); st = STATUS_UNSUCCESSFUL; } } } ObDereferenceObject(Thread); } return st; }
// IRP_MJ_CREATE/IRP_MJ_CLOSE处理函数 NTSTATUS DispatchCreateClose( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { PIO_STACK_LOCATION irpStack; NTSTATUS status; PFILE_CONTEXT fileContext; UNREFERENCED_PARAMETER(DeviceObject); PAGED_CODE(); irpStack = IoGetCurrentIrpStackLocation(Irp); ASSERT(irpStack->FileObject != NULL); switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: { DebugPrint(("IRP_MJ_CREATE\n")); fileContext = (PFILE_CONTEXT)ExAllocatePoolWithQuotaTag( NonPagedPool, sizeof(FILE_CONTEXT), TAG); if (NULL == fileContext) { status = STATUS_INSUFFICIENT_RESOURCES; break; } IoInitializeRemoveLock(&fileContext->FileRundownLock, TAG, 0, 0); ASSERT(irpStack->FileObject->FsContext == NULL); irpStack->FileObject->FsContext = (PVOID) fileContext; status = STATUS_SUCCESS; break; } case IRP_MJ_CLOSE: { DebugPrint(("IRP_MJ_CLOSE\n")); fileContext = irpStack->FileObject->FsContext; IoAcquireRemoveLock(&fileContext->FileRundownLock, 0); IoReleaseRemoveLockAndWait(&fileContext->FileRundownLock, 0); ExFreePoolWithTag(fileContext, TAG); status = STATUS_SUCCESS; break; } default: ASSERT(FALSE); // should never hit this status = STATUS_NOT_IMPLEMENTED; break; } Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
NTSTATUS BowserConvertType3IoControlToType2IoControl ( IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp ) /*++ Routine Description: This routine does the work necessary to convert a type 3 IoCtl to a type 2 IoCtl. We do this when we have to pass a user IRP to the FSP. Arguments: IN PIRP Irp - Supplies an IRP to convert IN PIO_STACK_LOCATION IrpSp - Supplies an Irp Stack location for convenience Return Value: NTSTATUS - Status of operation Note: This must be called in the FSD. --*/ { NTSTATUS Status; PAGED_CODE(); if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength != 0) { Status = BowserLockUsersBuffer(Irp, IoWriteAccess, IrpSp->Parameters.DeviceIoControl.OutputBufferLength); // // If we were unable to lock the users output buffer, return now. // if (!NT_SUCCESS(Status)) { return Status; } } ASSERT (Irp->AssociatedIrp.SystemBuffer == NULL); try { if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != 0) { PCHAR InputBuffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; ULONG InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuotaTag(PagedPool, InputBufferLength, ' GD'); if (Irp->AssociatedIrp.SystemBuffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, InputBuffer, InputBufferLength); Irp->Flags |= (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER); } else { Irp->AssociatedIrp.SystemBuffer = NULL; } } except (EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } return STATUS_SUCCESS; }
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) { NTSTATUS Status; PNP_DATA_QUEUE_ENTRY DataEntry; SIZE_T EntrySize; ULONG QuotaInEntry; PSECURITY_CLIENT_CONTEXT ClientContext; BOOLEAN HasSpace; ClientContext = NULL; ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who)); Status = STATUS_SUCCESS; if ((Type != 2) && (Who == WriteEntries)) { Status = NpGetClientSecurityContext(NamedPipeEnd, Ccb, Irp ? Irp->Tail.Overlay.Thread : PsGetCurrentThread(), &ClientContext); if (!NT_SUCCESS(Status)) { return Status; } } switch (Type) { case Unbuffered: case 2: case 3: ASSERT(Irp != NULL); DataEntry = ExAllocatePoolWithQuotaTag(NonPagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, sizeof(*DataEntry), NPFS_DATA_ENTRY_TAG); if (!DataEntry) { NpFreeClientSecurityContext(ClientContext); return STATUS_INSUFFICIENT_RESOURCES; } DataEntry->DataEntryType = Type; DataEntry->QuotaInEntry = 0; DataEntry->Irp = Irp; DataEntry->DataSize = DataSize; DataEntry->ClientSecurityContext = ClientContext; ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who)); Status = STATUS_PENDING; break; case Buffered: EntrySize = sizeof(*DataEntry); if (Who != ReadEntries) { EntrySize += DataSize; if (EntrySize < DataSize) { NpFreeClientSecurityContext(ClientContext); return STATUS_INVALID_PARAMETER; } } QuotaInEntry = DataSize - ByteOffset; if (DataQueue->Quota - DataQueue->QuotaUsed < QuotaInEntry) { QuotaInEntry = DataQueue->Quota - DataQueue->QuotaUsed; HasSpace = TRUE; } else { HasSpace = FALSE; } DataEntry = ExAllocatePoolWithQuotaTag(NonPagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, EntrySize, NPFS_DATA_ENTRY_TAG); if (!DataEntry) { NpFreeClientSecurityContext(ClientContext); return STATUS_INSUFFICIENT_RESOURCES; } DataEntry->QuotaInEntry = QuotaInEntry; DataEntry->Irp = Irp; DataEntry->DataEntryType = Buffered; DataEntry->ClientSecurityContext = ClientContext; DataEntry->DataSize = DataSize; if (Who == ReadEntries) { ASSERT(Irp); Status = STATUS_PENDING; ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who)); } else { _SEH2_TRY { RtlCopyMemory(DataEntry + 1, Irp ? Irp->UserBuffer: Buffer, DataSize); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { NpFreeClientSecurityContext(ClientContext); _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; if (HasSpace && Irp) { Status = STATUS_PENDING; } else { DataEntry->Irp = NULL; Status = STATUS_SUCCESS; } ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who)); } break; default: ASSERT(FALSE); NpFreeClientSecurityContext(ClientContext); return STATUS_INVALID_PARAMETER; } ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who)); if (DataQueue->QueueState == Empty) { ASSERT(DataQueue->BytesInQueue == 0); ASSERT(DataQueue->EntriesInQueue == 0); ASSERT(IsListEmpty(&DataQueue->Queue)); } else { ASSERT(DataQueue->QueueState == Who); ASSERT(DataQueue->QueueState != Empty); ASSERT(DataQueue->EntriesInQueue != 0); } DataQueue->QuotaUsed += DataEntry->QuotaInEntry; DataQueue->QueueState = Who; DataQueue->BytesInQueue += DataEntry->DataSize; DataQueue->EntriesInQueue++; if (ByteOffset) { DataQueue->ByteOffset = ByteOffset; ASSERT(Who == WriteEntries); ASSERT(ByteOffset < DataEntry->DataSize); ASSERT(DataQueue->EntriesInQueue == 1); } InsertTailList(&DataQueue->Queue, &DataEntry->QueueEntry); if (Status == STATUS_PENDING) { IoMarkIrpPending(Irp); Irp->Tail.Overlay.DriverContext[2] = DataQueue; Irp->Tail.Overlay.DriverContext[3] = DataEntry; IoSetCancelRoutine(Irp, NpCancelDataQueueIrp); if ((Irp->Cancel) && (IoSetCancelRoutine(Irp, NULL))) { NpCancelDataQueueIrp(NULL, Irp); } } return Status; }
NTSTATUS CsampCreateClose( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) /*++ Routine Description: Process the Create and close IRPs sent to this device. Arguments: DeviceObject - pointer to a device object. Irp - pointer to an I/O Request Packet. Return Value: NT Status code --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status = STATUS_SUCCESS; PFILE_CONTEXT fileContext; UNREFERENCED_PARAMETER(DeviceObject); PAGED_CODE (); CSAMP_KDPRINT(("CsampCreateClose Enter\n")); irpStack = IoGetCurrentIrpStackLocation(Irp); ASSERT(irpStack->FileObject != NULL); switch(irpStack->MajorFunction) { case IRP_MJ_CREATE: // // The dispatch routine for IRP_MJ_CREATE is called when a // file object associated with the device is created. // This is typically because of a call to CreateFile() in // a user-mode program or because a another driver is // layering itself over a this driver. A driver is // required to supply a dispatch routine for IRP_MJ_CREATE. // fileContext = ExAllocatePoolWithQuotaTag(NonPagedPool, sizeof(FILE_CONTEXT), TAG); if (NULL == fileContext) { status = STATUS_INSUFFICIENT_RESOURCES; break; } IoInitializeRemoveLock(&fileContext->FileRundownLock, TAG, 0, 0); // // Make sure nobody is using the FsContext scratch area. // ASSERT(irpStack->FileObject->FsContext == NULL); // // Store the context in the FileObject's scratch area. // irpStack->FileObject->FsContext = (PVOID) fileContext; CSAMP_KDPRINT(("IRP_MJ_CREATE\n")); break; case IRP_MJ_CLOSE: // // The IRP_MJ_CLOSE dispatch routine is called when a file object // opened on the driver is being removed from the system; that is, // all file object handles have been closed and the reference count // of the file object is down to 0. // fileContext = irpStack->FileObject->FsContext; ExFreePoolWithTag(fileContext, TAG); CSAMP_KDPRINT(("IRP_MJ_CLOSE\n")); break; default: CSAMP_KDPRINT((" Invalid CreateClose Parameter\n")); status = STATUS_INVALID_PARAMETER; break; } // // Save Status for return and complete Irp // Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); CSAMP_KDPRINT((" CsampCreateClose Exit = %x\n", status)); 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; }