NTSTATUS OpenDeviceReparseIndex( IN PUNICODE_STRING DeviceName, OUT PHANDLE Handle ) /*++ Routine Description: This routine opens the reparse index on the given device. Arguments: DeviceName - Supplies the device name. Handle - Returns the handle. Return Value: NTSTATUS --*/ { NTSTATUS status; PFILE_OBJECT fileObject; PDEVICE_OBJECT deviceObject; UNICODE_STRING reparseSuffix, reparseName; OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK ioStatus; status = IoGetDeviceObjectPointer(DeviceName, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject); if (!NT_SUCCESS(status)) { return status; } deviceObject = fileObject->DeviceObject; if (!deviceObject->Vpb || !(deviceObject->Vpb->Flags&VPB_MOUNTED)) { ObDereferenceObject(fileObject); return STATUS_UNSUCCESSFUL; } ObDereferenceObject(fileObject); RtlInitUnicodeString(&reparseSuffix, L"\\$Extend\\$Reparse:$R:$INDEX_ALLOCATION"); reparseName.Length = DeviceName->Length + reparseSuffix.Length; reparseName.MaximumLength = reparseName.Length + sizeof(WCHAR); reparseName.Buffer = ExAllocatePool(PagedPool, reparseName.MaximumLength); if (!reparseName.Buffer) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(reparseName.Buffer, DeviceName->Buffer, DeviceName->Length); RtlCopyMemory((PCHAR) reparseName.Buffer + DeviceName->Length, reparseSuffix.Buffer, reparseSuffix.Length); reparseName.Buffer[reparseName.Length/sizeof(WCHAR)] = 0; InitializeObjectAttributes(&oa, &reparseName, OBJ_CASE_INSENSITIVE, 0, 0); status = ZwOpenFile(Handle, SYNCHRONIZE | FILE_LIST_DIRECTORY, &oa, &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT | FILE_OPEN_FOR_BACKUP_INTENT); ExFreePool(reparseName.Buffer); return status; }
/*++ * @name ExpCreateWorkerThread * * The ExpCreateWorkerThread routine creates a new worker thread for the * specified queue. ** * @param QueueType * Type of the queue to use for this thread. Valid values are: * - DelayedWorkQueue * - CriticalWorkQueue * - HyperCriticalWorkQueue * * @param Dynamic * Specifies whether or not this thread is a dynamic thread. * * @return None. * * @remarks HyperCritical work threads run at priority 7; Critical work threads * run at priority 5, and delayed work threads run at priority 4. * * This, worker threads cannot pre-empty a normal user-mode thread. * *--*/ VOID NTAPI ExpCreateWorkerThread(WORK_QUEUE_TYPE WorkQueueType, IN BOOLEAN Dynamic) { PETHREAD Thread; HANDLE hThread; ULONG Context; KPRIORITY Priority; /* Check if this is going to be a dynamic thread */ Context = WorkQueueType; /* Add the dynamic mask */ if (Dynamic) Context |= EX_DYNAMIC_WORK_THREAD; /* Create the System Thread */ PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, ExpWorkerThreadEntryPoint, UlongToPtr(Context)); /* If the thread is dynamic */ if (Dynamic) { /* Increase the count */ InterlockedIncrement(&ExWorkerQueue[WorkQueueType].DynamicThreadCount); } /* Set the priority */ if (WorkQueueType == DelayedWorkQueue) { /* Priority == 4 */ Priority = EX_DELAYED_QUEUE_PRIORITY_INCREMENT; } else if (WorkQueueType == CriticalWorkQueue) { /* Priority == 5 */ Priority = EX_CRITICAL_QUEUE_PRIORITY_INCREMENT; } else { /* Priority == 7 */ Priority = EX_HYPERCRITICAL_QUEUE_PRIORITY_INCREMENT; } /* Get the Thread */ ObReferenceObjectByHandle(hThread, THREAD_SET_INFORMATION, PsThreadType, KernelMode, (PVOID*)&Thread, NULL); /* Set the Priority */ KeSetBasePriorityThread(&Thread->Tcb, Priority); /* Dereference and close handle */ ObDereferenceObject(Thread); ObCloseHandle(hThread, KernelMode); }
VOID NTAPI PspExitProcess(IN BOOLEAN LastThread, IN PEPROCESS Process) { ULONG Actual; PAGED_CODE(); PSTRACE(PS_KILL_DEBUG, "LastThread: %u Process: %p\n", LastThread, Process); PSREFTRACE(Process); /* Set Process Exit flag */ InterlockedOr((PLONG)&Process->Flags, PSF_PROCESS_EXITING_BIT); /* Check if we are the last thread */ if (LastThread) { /* Notify the WMI Process Callback */ //WmiTraceProcess(Process, FALSE); /* Run the Notification Routines */ PspRunCreateProcessNotifyRoutines(Process, FALSE); } /* Cleanup the power state */ PopCleanupPowerState((PPOWER_STATE)&Process->Pcb.PowerState); /* Clear the security port */ if (!Process->SecurityPort) { /* So we don't double-dereference */ Process->SecurityPort = (PVOID)1; } else if (Process->SecurityPort != (PVOID)1) { /* Dereference it */ ObDereferenceObject(Process->SecurityPort); Process->SecurityPort = (PVOID)1; } /* Check if we are the last thread */ if (LastThread) { /* Check if we have to set the Timer Resolution */ if (Process->SetTimerResolution) { /* Set it to default */ ZwSetTimerResolution(KeMaximumIncrement, 0, &Actual); } /* Check if we are part of a Job that has a completion port */ if ((Process->Job) && (Process->Job->CompletionPort)) { /* FIXME: Check job status code and do I/O completion if needed */ } /* FIXME: Notify the Prefetcher */ } else { /* Clear process' address space here */ MmCleanProcessAddressSpace(Process); } }
NTSTATUS NtAlertResumeThread( IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL ) /*++ Routine Description: description-of-function. Arguments: argument-name - Supplies | Returns description of argument. . . Return Value: return-value - Description of conditions needed to return value. - or - None. --*/ { PETHREAD Thread; NTSTATUS st; ULONG LocalPreviousSuspendCount; KPROCESSOR_MODE Mode; PAGED_CODE(); try { Mode = KeGetPreviousMode(); if ( Mode != KernelMode ) { if (ARGUMENT_PRESENT(PreviousSuspendCount)) { ProbeForWriteUlong(PreviousSuspendCount); } } } except (EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } st = ObReferenceObjectByHandle( ThreadHandle, THREAD_SUSPEND_RESUME, PsThreadType, Mode, (PVOID *)&Thread, NULL ); if ( !NT_SUCCESS(st) ) { return st; } LocalPreviousSuspendCount = (ULONG) KeAlertResumeThread(&Thread->Tcb); ObDereferenceObject(Thread); try { if (ARGUMENT_PRESENT(PreviousSuspendCount)) *PreviousSuspendCount = LocalPreviousSuspendCount; } except (EXCEPTION_EXECUTE_HANDLER) { return STATUS_SUCCESS; } return STATUS_SUCCESS; }
NTSTATUS Bus_IoCtl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Handle user mode PlugIn, UnPlug and device Eject requests. 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; ULONG inlen, outlen; PFDO_DEVICE_DATA fdoData; PVOID buffer; PAGED_CODE (); // // It is not safe to call IOCTL in raised IRQL. // ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; // // We only take Device Control requests for the FDO. // That is the bus itself. // if (!fdoData->IsFDO) { // // These commands are only allowed to go to the FDO. // status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // // Check to see whether the bus is removed // if (fdoData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } Bus_IncIoCount (fdoData); irpStack = IoGetCurrentIrpStackLocation (Irp); buffer = Irp->AssociatedIrp.SystemBuffer; inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength; outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength; status = STATUS_INVALID_PARAMETER; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode)); switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_LANSCSI_ADD_TARGET: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen) && (sizeof(LANSCSI_ADD_TARGET_DATA) <= inlen)) { ULONG ulSize; PLANSCSI_ADD_TARGET_DATA addTargetData = buffer; BOOLEAN accepted; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_ADD_TARGET called\n")); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET Target Type %d\n", addTargetData->ucTargetType)); status = STATUS_SUCCESS; // // Check structure size // if(VerifySizeOfAddTargetData(addTargetData, &ulSize) == 0) { status = STATUS_INVALID_PARAMETER; break; } if(ulSize != inlen) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen)); status = STATUS_UNSUCCESSFUL; break; } // // Check to see if acceptable structure. // accepted = TRUE; switch(addTargetData->ucTargetType) { case NDASSCSI_TYPE_DISK_NORMAL: case NDASSCSI_TYPE_DVD: case NDASSCSI_TYPE_VDVD: case NDASSCSI_TYPE_MO: if(addTargetData->ulNumberOfUnitDiskList != 1) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_MIRROR: if(2 != addTargetData->ulNumberOfUnitDiskList) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_AGGREGATION: if (addTargetData->ulNumberOfUnitDiskList < 2 || addTargetData->ulNumberOfUnitDiskList > MAX_NR_TC_PER_TARGET) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_RAID0: switch(addTargetData->ulNumberOfUnitDiskList) { case 2: case 4: case 8: break; default: // do not accept accepted = FALSE; break; } break; case NDASSCSI_TYPE_DISK_RAID1R3: { ULONG ulDiskCount; ulDiskCount = addTargetData->ulNumberOfUnitDiskList - addTargetData->RAID_Info.nSpareDisk; if (2 != ulDiskCount) accepted = FALSE; } break; case NDASSCSI_TYPE_DISK_RAID4R3: { ULONG ulDiskCount; ulDiskCount = addTargetData->ulNumberOfUnitDiskList - addTargetData->RAID_Info.nSpareDisk; switch(ulDiskCount) { case 3: // 2 + 1 case 5: // 4 + 1 case 9: // 8 + 1 break; default: // do not accept accepted = FALSE; break; } break; } default: Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Bad Disk Type.\n")); accepted = FALSE; break; } if(accepted == FALSE) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Invaild type.\n")); status = STATUS_UNSUCCESSFUL; break; } #if DBG NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_TRY_TO_ADDTARGET, IOCTL_LANSCSI_ADD_TARGET, addTargetData->ulSlotNo); #endif // Find Pdo Data... pdoData = LookupPdoData(fdoData, addTargetData->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_LANSCSI_ADD_TARGET, addTargetData->ulSlotNo); break; } pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePool(NonPagedPool, inlen); if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; } else { RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, addTargetData, inlen); status = STATUS_SUCCESS; } pdoData->LanscsiAdapterPDO.AddDevInfoLength = inlen; // // Notify to NDASSCSI // Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET SetEvent AddTargetEvent!\n")); KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE); // // Register Target // if(pdoData->Persistent) { status = LSBus_RegisterTarget(fdoData, addTargetData); if(!NT_SUCCESS(status)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: LSBus_RegisterTarget() failed. STATUS=%08lx\n", status)); status = STATUS_INTERNAL_DB_ERROR; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_REGISTER_TARGET_FAIL, IOCTL_LANSCSI_ADD_TARGET, addTargetData->ulSlotNo); } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("ADD_TARGET: Successfully registered.\n")); } } ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET length mismatch!!!" " inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } } break; case IOCTL_LANSCSI_REMOVE_TARGET: { PPDO_DEVICE_DATA pdoData; PLANSCSI_REMOVE_TARGET_DATA removeTarget; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REMOVE_TARGET called\n")); if (sizeof (LANSCSI_REMOVE_TARGET_DATA) != inlen) break; removeTarget = (PLANSCSI_REMOVE_TARGET_DATA)buffer; pdoData = LookupPdoData(fdoData, removeTarget->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_LANSCSI_REMOVE_TARGET, removeTarget->ulSlotNo); break; } // // redirect to the NDAS SCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_REMOVE_TARGET, buffer, sizeof(LANSCSI_REMOVE_TARGET_DATA), NULL, 0 ); if(NT_SUCCESS(status) && pdoData->Persistent) { status = LSBus_UnregisterTarget(fdoData, removeTarget->ulSlotNo, removeTarget->ulTargetId); if(!NT_SUCCESS(status)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ( "REMOVE_TARGET: Removed Target instance," " but LSBus_UnregisterTarget() failed.\n")); status = STATUS_INTERNAL_DB_ERROR; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_UNREGISTER_TARGET_FAIL, IOCTL_LANSCSI_REMOVE_TARGET, removeTarget->ulSlotNo); } #if DBG else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("REMOVE_TARGET: LSBus_UnregisterTarget() succeeded.\n")); } #endif } ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = 0; break; } case IOCTL_LANSCSI_STARTSTOP_REGISTRARENUM:{ PULONG onOff = (PULONG)buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "STARTSTOP_REGISTRARENUM: inlen %d, outlen %d OnOff %u\n", inlen, outlen, *onOff)); KeEnterCriticalRegion(); ExAcquireFastMutexUnsafe(&fdoData->RegMutex); if(*onOff != 0) { // // Save old state. // Activate the registrar's enumeration // *onOff = fdoData->StartStopRegistrarEnum; fdoData->StartStopRegistrarEnum = TRUE; } else { // // Save old state. // Deactivate the registrar's enumeration // *onOff = fdoData->StartStopRegistrarEnum; fdoData->StartStopRegistrarEnum = FALSE; } // // Clean up non-enumerated entries. // LSBus_CleanupNDASDeviceRegistryUnsafe(fdoData); ExReleaseFastMutexUnsafe(&fdoData->RegMutex); KeLeaveCriticalRegion(); Irp->IoStatus.Information = sizeof(ULONG); status = STATUS_SUCCESS; break; } case IOCTL_LANSCSI_REGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_DEVICE: inlen %d, outlen %d," " sizeof(BUSENUM_PLUGIN_HARDWARE_EX2) %d\n", inlen, outlen, sizeof(BUSENUM_PLUGIN_HARDWARE_EX2))); if ((inlen == outlen)) { PBUSENUM_PLUGIN_HARDWARE_EX2 PlugIn = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_DEVICE: entered\n")); status = LSBus_RegisterDevice(fdoData, PlugIn); Irp->IoStatus.Information = 0; } else Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("REGISTER_DEVICE: length mismatch!!!" " inlen %d, outlen %d, sizeof(BUSENUM_PLUGIN_HARDWARE_EX2) %d\n", inlen, outlen, sizeof(BUSENUM_PLUGIN_HARDWARE_EX2))); } break; case IOCTL_LANSCSI_REGISTER_TARGET: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_TARGET: inlen %d, outlen %d," " sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen)) { PLANSCSI_ADD_TARGET_DATA AddTargetData = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_TARGET: entered\n")); status = LSBus_RegisterTarget(fdoData, AddTargetData); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_TARGET: length mismatch!!!" " inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } } break; case IOCTL_LANSCSI_UNREGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_DEVICE: inlen %d, outlen %d," " sizeof(LANSCSI_UNREGISTER_NDASDEV) %d\n", inlen, outlen, sizeof(LANSCSI_UNREGISTER_NDASDEV))); if ((inlen == outlen)) { PLANSCSI_UNREGISTER_NDASDEV UnregDev = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_DEVICE: entered\n")); status = LSBus_UnregisterDevice(fdoData, UnregDev->SlotNo); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_DEVICE: length mismatch!!!" " inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_UNREGISTER_NDASDEV))); } } break; case IOCTL_LANSCSI_UNREGISTER_TARGET: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_TARGET: inlen %d, outlen %d," " sizeof(LANSCSI_UNREGISTER_TARGET) %d\n", inlen, outlen, sizeof(LANSCSI_UNREGISTER_TARGET))); if ((inlen == outlen)) { PLANSCSI_UNREGISTER_TARGET UnregTarget = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_TARGET: entered\n")); status = LSBus_UnregisterTarget(fdoData, UnregTarget->SlotNo, UnregTarget->TargetId); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_TARGET: length mismatch!!!" " inlen %d, outlen %d, sizeof(LANSCSI_UNREGISTER_TARGET) %d\n", inlen, outlen, sizeof(LANSCSI_UNREGISTER_TARGET))); } } break; case IOCTL_LANSCSI_SETPDOINFO: { PPDO_DEVICE_DATA pdoData; PBUSENUM_SETPDOINFO SetPdoInfo; KIRQL oldIrql; PVOID sectionHandle; BOOLEAN acceptStatus; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_SETPDOINFO called\n")); if (sizeof (BUSENUM_SETPDOINFO) != inlen) break; acceptStatus = TRUE; SetPdoInfo = (PBUSENUM_SETPDOINFO)buffer; pdoData = LookupPdoData(fdoData, SetPdoInfo->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_LANSCSI_SETPDOINFO, SetPdoInfo->SlotNo); break; } // // lock the code section of this function to acquire spinlock in raised IRQL. // sectionHandle = MmLockPagableCodeSection(Bus_IoCtl); KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! SETPDOINFO: PDO %p: %08lx %08lx %08lx %08lx\n", pdoData->Self, SetPdoInfo->AdapterStatus, SetPdoInfo->DeviceMode, SetPdoInfo->SupportedFeatures, SetPdoInfo->EnabledFeatures)); // // Set status values to the corresponding physical device object. // if(ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPED)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'An event occured after 'Stopped' event\n")); if(ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_STATUSFLAG_RESETSTATUS)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Reset-status event accepted.\n")); } else { acceptStatus = FALSE; } } if(acceptStatus) { pdoData->LanscsiAdapterPDO.AdapterStatus = SetPdoInfo->AdapterStatus; pdoData->LanscsiAdapterPDO.DeviceMode = SetPdoInfo->DeviceMode; pdoData->LanscsiAdapterPDO.SupportedFeatures = SetPdoInfo->SupportedFeatures; pdoData->LanscsiAdapterPDO.EnabledFeatures = SetPdoInfo->EnabledFeatures; } // // Queue plugout worker if the NDAS SCSI stop abnormally. // if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPED) && ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_STATUSFLAG_ABNORMAL_TERMINAT)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Queueing Unplug worker!!!!!!!!\n")); status = QueueUnplugWorker(fdoData, SetPdoInfo->SlotNo); } KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); // // Release the code section. // MmUnlockPagableImageSection(sectionHandle); status = STATUS_SUCCESS; ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } break; case IOCTL_BUSENUM_QUERY_NODE_ALIVE: { PPDO_DEVICE_DATA pdoData; BOOLEAN bAlive; PBUSENUM_NODE_ALIVE_IN pNodeAliveIn; BUSENUM_NODE_ALIVE_OUT nodeAliveOut; // Check Parameter. if(inlen != sizeof(BUSENUM_NODE_ALIVE_IN) || outlen != sizeof(BUSENUM_NODE_ALIVE_OUT)) { status = STATUS_UNKNOWN_REVISION; break; } pNodeAliveIn = (PBUSENUM_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE, ("FDO: IOCTL_BUSENUM_QUERY_NODE_ALIVE SlotNumber = %d\n", pNodeAliveIn->SlotNo)); pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo); if(pdoData == NULL) { // Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, // ("[LanScsiBus]Bus_IoCtl: IOCTL_BUSENUM_QUERY_NODE_ALIVE No pdo\n")); bAlive = FALSE; } else { // // Check this PDO would be removed... // if(pdoData->Present == TRUE) bAlive = TRUE; else bAlive = FALSE; } // For Result... nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo; nodeAliveOut.bAlive = bAlive; // Get Adapter Status. if(bAlive == TRUE) { if( ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, NDASSCSI_ADAPTERINFO_STATUS_IN_ERROR) || ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPING) /*|| ADAPTERINFO_ISSTATUSFLAG(pdoData->LanscsiAdapterPDO.AdapterStatus, NDASSCSI_ADAPTERINFO_STATUSFLAG_MEMBER_FAULT) */ ) { nodeAliveOut.bHasError = TRUE; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_BUSENUM_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError)); } else { nodeAliveOut.bHasError = FALSE; } } if(pdoData) ObDereferenceObject(pdoData->Self); RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &nodeAliveOut, sizeof(BUSENUM_NODE_ALIVE_OUT) ); Irp->IoStatus.Information = sizeof(BUSENUM_NODE_ALIVE_OUT); status = STATUS_SUCCESS; } break; // // added by hootch 01172004 // case IOCTL_LANSCSI_UPGRADETOWRITE: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_UPGRADETOWRITE called\n")); // Check Parameter. if(inlen != sizeof(BUSENUM_UPGRADE_TO_WRITE)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_UPGRADETOWRITE: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_UPGRADETOWRITE: No pdo for Slotno:%d\n", ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo)); status = STATUS_NO_SUCH_DEVICE; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_LANSCSI_UPGRADETOWRITE, ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo); } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_UPGRADETOWRITE, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_LANSCSI_REDIRECT_NDASSCSI: { PPDO_DEVICE_DATA pdoData; PBUSENUM_REDIRECT_NDASSCSI redirectIoctl; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REDIRECT_NDASSCSI called\n")); // Check Parameter. if(inlen < sizeof(BUSENUM_REDIRECT_NDASSCSI)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_REDIRECT_NDASSCSI: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } redirectIoctl = (PBUSENUM_REDIRECT_NDASSCSI)buffer; pdoData = LookupPdoData(fdoData, redirectIoctl->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_REDIRECT_NDASSCSI: No pdo for Slotno:%d\n", redirectIoctl->SlotNo)); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, redirectIoctl->IoctlCode, redirectIoctl->IoctlData, redirectIoctl->IoctlDataSize, redirectIoctl->IoctlData, redirectIoctl->IoctlDataSize ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_NDASBUS_QUERY_NDASSCSIINFO: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO called\n")); // Check Parameter. if(inlen < FIELD_OFFSET(NDASSCSI_QUERY_INFO_DATA, QueryData) ) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO: Invalid input buffer length too small.\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PNDASSCSI_QUERY_INFO_DATA)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO No pdo\n")); status = STATUS_NO_SUCH_DEVICE; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_QUERY_NDASSCSIINFO, ((PNDASSCSI_QUERY_INFO_DATA)buffer)->SlotNo); } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_QUERYINFO_EX, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = outlen; } break; case IOCTL_BUSENUM_QUERY_INFORMATION: { // PPDO_DEVICE_DATA pdoData; BUSENUM_QUERY_INFORMATION Query; PBUSENUM_INFORMATION Information; LONG BufferLenNeeded; // Check Parameter. if( inlen < sizeof(BUSENUM_QUERY_INFORMATION) /*|| outlen < sizeof(BUSENUM_INFORMATION) */) { status = STATUS_UNKNOWN_REVISION; break; } RtlCopyMemory(&Query, buffer, sizeof(BUSENUM_QUERY_INFORMATION)); Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, ("FDO: IOCTL_BUSENUM_QUERY_INFORMATION QueryType : %d SlotNumber = %d\n", Query.InfoClass, Query.SlotNo)); Information = (PBUSENUM_INFORMATION)buffer; ASSERT(Information); Information->InfoClass = Query.InfoClass; status = LSBus_QueryInformation(fdoData, IoIs32bitProcess(Irp), &Query, Information, outlen, &BufferLenNeeded); if(NT_SUCCESS(status)) { Information->Size = BufferLenNeeded; Irp->IoStatus.Information = BufferLenNeeded; } else { Irp->IoStatus.Information = BufferLenNeeded; } } break; case IOCTL_BUSENUM_PLUGIN_HARDWARE_EX2: { ULONG structLen; // Without variable length field ULONG wholeStructLen; // With variable length field ULONG inputWholeStructLen; // // Check 32 bit thunking request // if(IoIs32bitProcess(Irp)) { structLen = FIELD_OFFSET(BUSENUM_PLUGIN_HARDWARE_EX2_32, HardwareIDs); wholeStructLen = sizeof(BUSENUM_PLUGIN_HARDWARE_EX2_32); inputWholeStructLen = ((PBUSENUM_PLUGIN_HARDWARE_EX2_32) buffer)->Size; } else { structLen = FIELD_OFFSET(BUSENUM_PLUGIN_HARDWARE_EX2, HardwareIDs); wholeStructLen = sizeof(BUSENUM_PLUGIN_HARDWARE_EX2); inputWholeStructLen = ((PBUSENUM_PLUGIN_HARDWARE_EX2) buffer)->Size; } if ((inlen == outlen) && // // Make sure it has at least two nulls and the size // field is set to the declared size of the struct // ((structLen + sizeof(UNICODE_NULL) * 2) <= inlen) && // // The size field should be set to the sizeof the struct as declared // and *not* the size of the struct plus the multi_sz // (wholeStructLen == inputWholeStructLen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n")); status= Bus_PlugInDeviceEx2((PBUSENUM_PLUGIN_HARDWARE_EX2)buffer, inlen, fdoData, IoIs32bitProcess(Irp), Irp->RequestorMode, FALSE); Irp->IoStatus.Information = outlen; } } break; case IOCTL_LANSCSI_GETVERSION: { if (outlen >= sizeof(BUSENUM_GET_VERSION)) { PBUSENUM_GET_VERSION version = (PBUSENUM_GET_VERSION)buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_GETVERSION: called\n")); try { version->VersionMajor = VER_FILEMAJORVERSION; version->VersionMinor = VER_FILEMINORVERSION; version->VersionBuild = VER_FILEBUILD; version->VersionPrivate = VER_FILEBUILD_QFE; Irp->IoStatus.Information = sizeof(BUSENUM_GET_VERSION); status = STATUS_SUCCESS; } except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); Irp->IoStatus.Information = 0; } } } break; case IOCTL_BUSENUM_UNPLUG_HARDWARE: { if ((sizeof (BUSENUM_UNPLUG_HARDWARE) == inlen) && (inlen == outlen) && (((PBUSENUM_UNPLUG_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n")); status= Bus_UnPlugDevice( (PBUSENUM_UNPLUG_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_BUSENUM_EJECT_HARDWARE: { if ((sizeof (BUSENUM_EJECT_HARDWARE) == inlen) && (inlen == outlen) && (((PBUSENUM_EJECT_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n")); status= Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_DVD_GET_STATUS: { PPDO_DEVICE_DATA pdoData; PBUSENUM_DVD_STATUS pDvdStatusData; // Check Parameter. if((inlen != outlen) || (sizeof(BUSENUM_DVD_STATUS) > inlen)) { status = STATUS_UNSUCCESSFUL ; break; } pDvdStatusData = (PBUSENUM_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("FDO: IOCTL_DVD_GET_STATUS SlotNumber = %d\n", pDvdStatusData->SlotNo)); pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_DVD_GET_STATUS, pDvdStatusData->SlotNo); break; } else { if(pdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) { // // A LUR descriptor is set. // if(((PLURELATION_DESC)pdoData->LanscsiAdapterPDO.AddDevInfo)->DevType != NDASSCSI_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } else { // // ADD_TARGET_DATA is set. // if(((PLANSCSI_ADD_TARGET_DATA)pdoData->LanscsiAdapterPDO.AddDevInfo)->ucTargetType != NDASSCSI_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_GET_DVD_STATUS, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); status = STATUS_SUCCESS; Irp->IoStatus.Information = outlen; } } break; default: break; // default status is STATUS_INVALID_PARAMETER }
ULONG GetRegFullPath( HANDLE hKey, PVOID pRootObject, PUNICODE_STRING pSubKey, PNAME_BUFFER pRegBuffer ) { NTSTATUS Status = STATUS_SUCCESS; PVOID pKey = NULL; POBJECT_NAME_INFORMATION pObjectName = NULL; ULONG ulTempLen=0, ulRet=0, ulLength=0; if(KeGetCurrentIrql() >= DISPATCH_LEVEL) { return 0; } if(!pRegBuffer || !pRegBuffer->pBuffer) { return 0; } if(hKey) { if(((ULONG_PTR)hKey>0) || (ExGetPreviousMode() == KernelMode)) { ObReferenceObjectByHandle( hKey, 0, NULL, KernelMode, &pKey, NULL); } } else if(pRootObject) { pKey = pRootObject; ObReferenceObject( pKey ); } else { return 0; } if(!pKey) return 0; KeEnterCriticalRegion(); pObjectName = (POBJECT_NAME_INFORMATION)ExAllocatePoolWithTag( NonPagedPool, MAX_POOL_LEN, MALWFIND_NAME_TAG ); if(!pObjectName) { KeLeaveCriticalRegion(); return 0; } RtlZeroMemory( pObjectName, MAX_POOL_LEN ); pObjectName->Name.Length = 0; pObjectName->Name.MaximumLength = (MAX_POOL_LEN >> 1); Status = ObQueryNameString( pKey, pObjectName, MAX_POOL_LEN, &ulRet ); if(!NT_SUCCESS( Status )) { if(pObjectName) { ExFreePoolWithTag( pObjectName, MALWFIND_NAME_TAG ); pObjectName = NULL; } KeLeaveCriticalRegion(); return 0; } ObDereferenceObject( pKey ); ulLength += pObjectName->Name.Length; Status = RtlStringCchCatNW( pRegBuffer->pBuffer, pRegBuffer->ulMaxLength, pObjectName->Name.Buffer, pObjectName->Name.Length ); if(!NT_SUCCESS( Status )) { if(pObjectName) { ExFreePoolWithTag( pObjectName, MALWFIND_NAME_TAG ); pObjectName = NULL; } KeLeaveCriticalRegion(); return 0; } if(pSubKey && pSubKey->Buffer && pSubKey->Length) { ulLength += sizeof(WCHAR); ulTempLen = sizeof(WCHAR); Status = RtlStringCchCatNW( pRegBuffer->pBuffer, pRegBuffer->ulMaxLength, L"\\", ulTempLen ); ulLength += pSubKey->Length; Status = RtlStringCchCatNW( pRegBuffer->pBuffer, pRegBuffer->ulMaxLength, pSubKey->Buffer, pSubKey->Length ); } if(pObjectName) { ExFreePoolWithTag( pObjectName, MALWFIND_NAME_TAG ); pObjectName = NULL; } KeLeaveCriticalRegion(); return ulLength; }
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; }
NTSTATUS NTAPI PspCreateThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle, IN PEPROCESS TargetProcess, OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, IN PINITIAL_TEB InitialTeb, IN BOOLEAN CreateSuspended, IN PKSTART_ROUTINE StartRoutine OPTIONAL, IN PVOID StartContext OPTIONAL) { HANDLE hThread; PEPROCESS Process; PETHREAD Thread; PTEB TebBase = NULL; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status, AccessStatus; HANDLE_TABLE_ENTRY CidEntry; ACCESS_STATE LocalAccessState; PACCESS_STATE AccessState = &LocalAccessState; AUX_ACCESS_DATA AuxData; BOOLEAN Result, SdAllocated; PSECURITY_DESCRIPTOR SecurityDescriptor; SECURITY_SUBJECT_CONTEXT SubjectContext; PAGED_CODE(); PSTRACE(PS_THREAD_DEBUG, "ThreadContext: %p TargetProcess: %p ProcessHandle: %p\n", ThreadContext, TargetProcess, ProcessHandle); /* If we were called from PsCreateSystemThread, then we're kernel mode */ if (StartRoutine) PreviousMode = KernelMode; /* Reference the Process by handle or pointer, depending on what we got */ if (ProcessHandle) { /* Normal thread or System Thread */ Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_CREATE_THREAD, PsProcessType, PreviousMode, (PVOID*)&Process, NULL); PSREFTRACE(Process); } else { /* System thread inside System Process, or Normal Thread with a bug */ if (StartRoutine) { /* Reference the Process by Pointer */ ObReferenceObject(TargetProcess); Process = TargetProcess; Status = STATUS_SUCCESS; } else { /* Fake ObReference returning this */ Status = STATUS_INVALID_HANDLE; } } /* Check for success */ if (!NT_SUCCESS(Status)) return Status; /* Also make sure that User-Mode isn't trying to create a system thread */ if ((PreviousMode != KernelMode) && (Process == PsInitialSystemProcess)) { /* Fail */ ObDereferenceObject(Process); return STATUS_INVALID_HANDLE; } /* Create Thread Object */ Status = ObCreateObject(PreviousMode, PsThreadType, ObjectAttributes, PreviousMode, NULL, sizeof(ETHREAD), 0, 0, (PVOID*)&Thread); if (!NT_SUCCESS(Status)) { /* We failed; dereference the process and exit */ ObDereferenceObject(Process); return Status; } /* Zero the Object entirely */ RtlZeroMemory(Thread, sizeof(ETHREAD)); /* Initialize rundown protection */ ExInitializeRundownProtection(&Thread->RundownProtect); /* Initialize exit code */ Thread->ExitStatus = STATUS_PENDING; /* Set the Process CID */ Thread->ThreadsProcess = Process; Thread->Cid.UniqueProcess = Process->UniqueProcessId; /* Create Cid Handle */ CidEntry.Object = Thread; CidEntry.GrantedAccess = 0; Thread->Cid.UniqueThread = ExCreateHandle(PspCidTable, &CidEntry); if (!Thread->Cid.UniqueThread) { /* We couldn't create the CID, dereference the thread and fail */ ObDereferenceObject(Thread); return STATUS_INSUFFICIENT_RESOURCES; } /* Save the read cluster size */ Thread->ReadClusterSize = MmReadClusterSize; /* Initialize the LPC Reply Semaphore */ KeInitializeSemaphore(&Thread->LpcReplySemaphore, 0, 1); /* Initialize the list heads and locks */ InitializeListHead(&Thread->LpcReplyChain); InitializeListHead(&Thread->IrpList); InitializeListHead(&Thread->PostBlockList); InitializeListHead(&Thread->ActiveTimerListHead); KeInitializeSpinLock(&Thread->ActiveTimerListLock); /* Acquire rundown protection */ if (!ExAcquireRundownProtection (&Process->RundownProtect)) { /* Fail */ ObDereferenceObject(Thread); return STATUS_PROCESS_IS_TERMINATING; } /* Now let the kernel initialize the context */ if (ThreadContext) { /* User-mode Thread, create Teb */ Status = MmCreateTeb(Process, &Thread->Cid, InitialTeb, &TebBase); if (!NT_SUCCESS(Status)) { /* Failed to create the TEB. Release rundown and dereference */ ExReleaseRundownProtection(&Process->RundownProtect); ObDereferenceObject(Thread); return Status; } /* Set the Start Addresses from the untrusted ThreadContext */ _SEH2_TRY { Thread->StartAddress = (PVOID)KeGetContextPc(ThreadContext); Thread->Win32StartAddress = (PVOID)KeGetContextReturnRegister(ThreadContext); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; /* Let the kernel intialize the Thread */ if (NT_SUCCESS(Status)) { Status = KeInitThread(&Thread->Tcb, NULL, PspUserThreadStartup, NULL, Thread->StartAddress, ThreadContext, TebBase, &Process->Pcb); } } else {
BOOL APIENTRY NtUserGetGUIThreadInfo( DWORD idThread, /* If NULL use foreground thread */ LPGUITHREADINFO lpgui) { NTSTATUS Status; PTHRDCARETINFO CaretInfo; GUITHREADINFO SafeGui; PDESKTOP Desktop; PUSER_MESSAGE_QUEUE MsgQueue; PTHREADINFO W32Thread; PETHREAD Thread = NULL; DECLARE_RETURN(BOOLEAN); TRACE("Enter NtUserGetGUIThreadInfo\n"); UserEnterShared(); Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); } if(SafeGui.cbSize != sizeof(GUITHREADINFO)) { EngSetLastError(ERROR_INVALID_PARAMETER); RETURN( FALSE); } if (idThread) { Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)idThread, &Thread); if(!NT_SUCCESS(Status)) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread; Desktop = W32Thread->rpdesk; } else { /* Get the foreground thread */ Thread = PsGetCurrentThread(); W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread; Desktop = W32Thread->rpdesk; } if (!Thread || !Desktop ) { if(idThread && Thread) ObDereferenceObject(Thread); EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } if ( W32Thread->MessageQueue ) MsgQueue = W32Thread->MessageQueue; else { if ( Desktop ) MsgQueue = Desktop->ActiveMessageQueue; } CaretInfo = MsgQueue->CaretInfo; SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0); if (MsgQueue->MenuOwner) SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState; if (MsgQueue->MoveSize) SafeGui.flags |= GUI_INMOVESIZE; /* FIXME: Add flag GUI_16BITTASK */ SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0; SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0; SafeGui.hwndCapture = MsgQueue->spwndCapture ? UserHMGetHandle(MsgQueue->spwndCapture) : 0; SafeGui.hwndMenuOwner = MsgQueue->MenuOwner; SafeGui.hwndMoveSize = MsgQueue->MoveSize; SafeGui.hwndCaret = CaretInfo->hWnd; SafeGui.rcCaret.left = CaretInfo->Pos.x; SafeGui.rcCaret.top = CaretInfo->Pos.y; SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx; SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy; if (idThread) ObDereferenceObject(Thread); Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); } RETURN( TRUE); CLEANUP: TRACE("Leave NtUserGetGUIThreadInfo, ret=%u\n",_ret_); UserLeave(); END_CLEANUP; }
/*++ * @name IoSetDeviceInterfaceState * @implemented * * Enables or disables an instance of a previously registered device * interface class. * Documented in WDK. * * @param SymbolicLinkName * Pointer to the string identifying instance to enable or disable * * @param Enable * TRUE = enable, FALSE = disable * * @return Usual NTSTATUS * * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a * system thread * *--*/ NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable) { PDEVICE_OBJECT PhysicalDeviceObject; PFILE_OBJECT FileObject; UNICODE_STRING GuidString; UNICODE_STRING SymLink; PWCHAR StartPosition; PWCHAR EndPosition; NTSTATUS Status; LPCGUID EventGuid; HANDLE InstanceHandle, ControlHandle; UNICODE_STRING KeyName; OBJECT_ATTRIBUTES ObjectAttributes; ULONG LinkedValue; GUID DeviceGuid; if (SymbolicLinkName == NULL) return STATUS_INVALID_PARAMETER_1; DPRINT("IoSetDeviceInterfaceState('%wZ', %u)\n", SymbolicLinkName, Enable); /* Symbolic link name is \??\ACPI#PNP0501#1#{GUID}\ReferenceString */ /* Get GUID from SymbolicLinkName */ StartPosition = wcschr(SymbolicLinkName->Buffer, L'{'); EndPosition = wcschr(SymbolicLinkName->Buffer, L'}'); if (!StartPosition ||!EndPosition || StartPosition > EndPosition) { DPRINT1("IoSetDeviceInterfaceState() returning STATUS_INVALID_PARAMETER_1\n"); return STATUS_INVALID_PARAMETER_1; } GuidString.Buffer = StartPosition; GuidString.MaximumLength = GuidString.Length = (USHORT)((ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)StartPosition); SymLink.Buffer = SymbolicLinkName->Buffer; SymLink.MaximumLength = SymLink.Length = (USHORT)((ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)SymLink.Buffer); DPRINT("IoSetDeviceInterfaceState('%wZ', %u)\n", SymbolicLinkName, Enable); Status = OpenRegistryHandlesFromSymbolicLink(SymbolicLinkName, KEY_CREATE_SUB_KEY, NULL, NULL, &InstanceHandle); if (!NT_SUCCESS(Status)) return Status; RtlInitUnicodeString(&KeyName, L"Control"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, InstanceHandle, NULL); Status = ZwCreateKey(&ControlHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); ZwClose(InstanceHandle); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to create the Control subkey\n"); return Status; } LinkedValue = (Enable ? 1 : 0); RtlInitUnicodeString(&KeyName, L"Linked"); Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_DWORD, &LinkedValue, sizeof(ULONG)); ZwClose(ControlHandle); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to write the Linked value\n"); return Status; } /* Get pointer to the PDO */ Status = IoGetDeviceObjectPointer( &SymLink, 0, /* DesiredAccess */ &FileObject, &PhysicalDeviceObject); if (!NT_SUCCESS(Status)) { DPRINT1("IoGetDeviceObjectPointer() failed with status 0x%08lx\n", Status); return Status; } Status = RtlGUIDFromString(&GuidString, &DeviceGuid); if (!NT_SUCCESS(Status)) { DPRINT1("RtlGUIDFromString() failed with status 0x%08lx\n", Status); return Status; } EventGuid = Enable ? &GUID_DEVICE_INTERFACE_ARRIVAL : &GUID_DEVICE_INTERFACE_REMOVAL; IopNotifyPlugPlayNotification( PhysicalDeviceObject, EventCategoryDeviceInterfaceChange, EventGuid, &DeviceGuid, (PVOID)SymbolicLinkName); ObDereferenceObject(FileObject); DPRINT("Status %x\n", Status); return STATUS_SUCCESS; }
BOOLEAN obtest( void ) { ULONG i; HANDLE Handles[ 2 ]; NTSTATUS Status; OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; ObpDumpObjectTable( ObpGetObjectTable(), NULL ); RtlInitString( &ObjectTypeAName, "ObjectTypeA" ); RtlInitString( &ObjectTypeBName, "ObjectTypeB" ); RtlZeroMemory( &ObjectTypeInitializer, sizeof( ObjectTypeInitializer ) ); ObjectTypeInitializer.Length = sizeof( ObjectTypeInitializer ); ObjectTypeInitializer.ValidAccessMask = -1; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.MaintainHandleCount = TRUE; ObjectTypeInitializer.DumpProcedure = DumpAProc; ObjectTypeInitializer.OpenProcedure = OpenAProc; ObjectTypeInitializer.CloseProcedure = CloseAProc; ObjectTypeInitializer.DeleteProcedure = DeleteAProc; ObjectTypeInitializer.ParseProcedure = ParseAProc; ObCreateObjectType( &ObjectTypeAName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObjectTypeA ); ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.MaintainHandleCount = FALSE; ObjectTypeInitializer.GenericMapping = MyGenericMapping; ObjectTypeInitializer.DumpProcedure = DumpBProc; ObjectTypeInitializer.OpenProcedure = NULL; ObjectTypeInitializer.CloseProcedure = NULL; ObjectTypeInitializer.DeleteProcedure = DeleteBProc; ObjectTypeInitializer.ParseProcedure = NULL; ObCreateObjectType( &ObjectTypeBName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObjectTypeB ); ObpDumpTypes( NULL ); RtlInitString( &DirectoryName, "\\MyObjects" ); InitializeObjectAttributes( &DirectoryObjA, &DirectoryName, OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, NULL, NULL ); NtCreateDirectoryObject( &DirectoryHandle, 0, &DirectoryObjA ); NtClose( DirectoryHandle ); RtlInitString( &ObjectAName, "\\myobjects\\ObjectA" ); InitializeObjectAttributes( &ObjectAObjA, &ObjectAName, OBJ_CASE_INSENSITIVE, NULL, NULL ); RtlInitString( &ObjectBName, "\\myobjects\\ObjectB" ); InitializeObjectAttributes( &ObjectBObjA, &ObjectBName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ObCreateObject( KernelMode, ObjectTypeA, &ObjectAObjA, KernelMode, NULL, (ULONG)sizeof( OBJECTTYPEA ), 0L, 0L, (PVOID *)&ObjectBodyA ); ObjectA = (POBJECTTYPEA)ObjectBodyA; ObjectA->TypeALength = sizeof( *ObjectA ); for (i=0; i<4; i++) { ObjectA->Stuff[i] = i+1; } KeInitializeEvent( &ObjectA->Event, NotificationEvent, TRUE ); Status = ObCreateObject( KernelMode, ObjectTypeB, &ObjectBObjA, KernelMode, NULL, (ULONG)sizeof( OBJECTTYPEB ), 0L, 0L, (PVOID *)&ObjectBodyB ); ObjectB = (POBJECTTYPEB)ObjectBodyB; ObjectB->TypeBLength = sizeof( *ObjectB ); for (i=0; i<16; i++) { ObjectB->Stuff[i] = i+1; } KeInitializeSemaphore ( &ObjectB->Semaphore, 2L, 2L ); Status = ObInsertObject( ObjectBodyA, SYNCHRONIZE | 0x3, NULL, 1, &ObjectBodyA, &ObjectHandleA1 ); DbgPrint( "Status: %lx ObjectBodyA: %lx ObjectHandleA1: %lx\n", Status, ObjectBodyA, ObjectHandleA1 ); Status = ObInsertObject( ObjectBodyB, SYNCHRONIZE | 0x1, NULL, 1, &ObjectBodyB, &ObjectHandleB1 ); DbgPrint( "Status: %lx ObjectBodyB: %lx ObjectHandleB1: %lx\n", Status, ObjectBodyB, ObjectHandleB1 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); RtlInitString( &ObjectAName, "\\MyObjects\\ObjectA" ); InitializeObjectAttributes( &ObjectAObjA, &ObjectAName, OBJ_OPENIF, NULL, NULL ); Status = ObCreateObject( KernelMode, ObjectTypeA, &ObjectAObjA, KernelMode, NULL, (ULONG)sizeof( OBJECTTYPEA ), 0L, 0L, (PVOID *)&ObjectBodyA1 ); Status = ObInsertObject( ObjectBodyA1, SYNCHRONIZE | 0x3, NULL, 1, &ObjectBodyA2, &ObjectHandleA2 ); DbgPrint( "Status: %lx ObjectBodyA1: %lx ObjectBodyA2: %lx ObjectHandleA2: %lx\n", Status, ObjectBodyA1, ObjectBodyA2, ObjectHandleA2 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); NtClose( ObjectHandleA2 ); ObDereferenceObject( ObjectBodyA2 ); // ObInsertObject,ObjectPointerBias NtWaitForSingleObject( ObjectHandleB1, TRUE, NULL ); Handles[ 0 ] = ObjectHandleA1; Handles[ 1 ] = ObjectHandleB1; NtWaitForMultipleObjects( 2, Handles, WaitAny, TRUE, NULL ); ObReferenceObjectByHandle( ObjectHandleA1, 0L, ObjectTypeA, KernelMode, &ObjectBodyA, NULL ); ObReferenceObjectByHandle( ObjectHandleB1, 0L, ObjectTypeB, KernelMode, &ObjectBodyB, NULL ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleA1, ObjectBodyA ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleB1, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObReferenceObjectByPointer( ObjectBodyA, 0L, ObjectTypeA, KernelMode ); ObReferenceObjectByPointer( ObjectBodyB, 0L, ObjectTypeB, KernelMode ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); RtlInitString( &ObjectAPathName, "\\MyObjects\\ObjectA" ); RtlInitString( &ObjectBPathName, "\\MyObjects\\ObjectB" ); ObReferenceObjectByName( &ObjectAPathName, OBJ_CASE_INSENSITIVE, 0L, ObjectTypeA, KernelMode, NULL, &ObjectBodyA ); ObReferenceObjectByName( &ObjectBPathName, OBJ_CASE_INSENSITIVE, 0L, ObjectTypeB, KernelMode, NULL, &ObjectBodyB ); DbgPrint( "Reference Name %s = %lx\n", ObjectAPathName.Buffer, ObjectBodyA ); DbgPrint( "Reference Name %s = %lx\n", ObjectBPathName.Buffer, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObDereferenceObject( ObjectBodyA ); // ObInsertObject,ObjectPointerBias ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByHandle ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByPointer ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByName ObDereferenceObject( ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); InitializeObjectAttributes( &ObjectAObjA, &ObjectAPathName, OBJ_CASE_INSENSITIVE, NULL, NULL ); ObOpenObjectByName( &ObjectAObjA, 0L, NULL, ObjectTypeA, KernelMode, NULL, &ObjectHandleA2 ); InitializeObjectAttributes( &ObjectBObjA, &ObjectBPathName, OBJ_CASE_INSENSITIVE, NULL, NULL ); ObOpenObjectByName( &ObjectBObjA, 0L, NULL, ObjectTypeB, KernelMode, NULL, &ObjectHandleB2 ); DbgPrint( "Open Object Name %s = %lx\n", ObjectAPathName.Buffer, ObjectHandleA2 ); DbgPrint( "Open Object Name %s = %lx\n", ObjectBPathName.Buffer, ObjectHandleB2 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); NtClose( ObjectHandleA1 ); NtClose( ObjectHandleB1 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObReferenceObjectByHandle( ObjectHandleA2, 0L, ObjectTypeA, KernelMode, &ObjectBodyA, NULL ); ObReferenceObjectByHandle( ObjectHandleB2, 0L, ObjectTypeB, KernelMode, &ObjectBodyB, NULL ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleA2, ObjectBodyA ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleB2, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObOpenObjectByPointer( ObjectBodyA, OBJ_CASE_INSENSITIVE, 0L, NULL, ObjectTypeA, KernelMode, &ObjectHandleA1 ); ObOpenObjectByPointer( ObjectBodyB, OBJ_CASE_INSENSITIVE, 0L, NULL, ObjectTypeB, KernelMode, &ObjectHandleB1 ); DbgPrint( "Open Object Pointer %lx = %lx\n", ObjectBodyA, ObjectHandleA1 ); DbgPrint( "Open Object Pointer %lx = %lx\n", ObjectBodyB, ObjectHandleB1 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObReferenceObjectByHandle( ObjectHandleA1, 0L, ObjectTypeA, KernelMode, &ObjectBodyA, NULL ); ObReferenceObjectByHandle( ObjectHandleB1, 0L, ObjectTypeB, KernelMode, &ObjectBodyB, NULL ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleA1, ObjectBodyA ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleB1, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByHandle ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByHandle ObDereferenceObject( ObjectBodyB ); NtClose( ObjectHandleA1 ); NtClose( ObjectHandleB1 ); NtClose( ObjectHandleA2 ); NtClose( ObjectHandleB2 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); TestFunction = NULL; return( TRUE ); }
NTSTATUS GetProcessImageName(HANDLE processId, PUNICODE_STRING ProcessImageName) { NTSTATUS status; ULONG returnedLength; ULONG bufferLength; HANDLE hProcess; PVOID buffer; PEPROCESS eProcess; PUNICODE_STRING imageName; PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process status = PsLookupProcessByProcessId(processId, &eProcess); if(NT_SUCCESS(status)) { status = ObOpenObjectByPointer(eProcess,0, NULL, 0,0,KernelMode,&hProcess); if(NT_SUCCESS(status)) { } else { DbgPrint("ObOpenObjectByPointer Failed: %08x\n", status); } ObDereferenceObject(eProcess); } else { DbgPrint("PsLookupProcessByProcessId Failed: %08x\n", status); } if (NULL == ZwQueryInformationProcess) { UNICODE_STRING routineName; RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess"); ZwQueryInformationProcess = (QUERY_INFO_PROCESS) MmGetSystemRoutineAddress(&routineName); if (NULL == ZwQueryInformationProcess) { DbgPrint("Cannot resolve ZwQueryInformationProcess\n"); } } /* Query the actual size of the process path */ status = ZwQueryInformationProcess( hProcess, ProcessImageFileName, NULL, // buffer 0, // buffer size &returnedLength); if (STATUS_INFO_LENGTH_MISMATCH != status) { return status; } /* Check there is enough space to store the actual process path when it is found. If not return an error with the required size */ bufferLength = returnedLength - sizeof(UNICODE_STRING); if (ProcessImageName->MaximumLength < bufferLength) { ProcessImageName->MaximumLength = (USHORT) bufferLength; return STATUS_BUFFER_OVERFLOW; } /* Allocate a temporary buffer to store the path name */ buffer = ExAllocatePoolWithTag(NonPagedPool, returnedLength, PROCESS_POOL_TAG); if (NULL == buffer) { return STATUS_INSUFFICIENT_RESOURCES; } /* Retrieve the process path from the handle to the process */ status = ZwQueryInformationProcess( hProcess, ProcessImageFileName, buffer, returnedLength, &returnedLength); if (NT_SUCCESS(status)) { /* Copy the path name */ imageName = (PUNICODE_STRING) buffer; RtlCopyUnicodeString(ProcessImageName, imageName); } /* Free the temp buffer which stored the path */ ExFreePoolWithTag(buffer, PROCESS_POOL_TAG); return status; }
// // I/O Control to the NDASSCSI. // Buffers must be allocated from NonPagedPool // // NOTE: Do not use LANSCSIMINIPORT_IOCTL_QUERYINFO. // It uses separate input/output buffer. // It will be obsolete. // NTSTATUS LSBus_IoctlToNdasScsiDevice( PPDO_DEVICE_DATA PdoData, ULONG IoctlCode, PVOID InputBuffer, LONG InputBufferLength, PVOID OutputBuffer, LONG OutputBufferLength ) { PDEVICE_OBJECT AttachedDevice; PIRP irp; KEVENT event; PSRB_IO_CONTROL psrbIoctl; LONG srbIoctlLength; PVOID srbIoctlBuffer; LONG srbIoctlBufferLength; NTSTATUS status; PIO_STACK_LOCATION irpStack; SCSI_REQUEST_BLOCK srb; LARGE_INTEGER startingOffset; IO_STATUS_BLOCK ioStatusBlock; AttachedDevice = NULL; psrbIoctl = NULL; irp = NULL; // // get a ScsiPort device or attached one. // AttachedDevice = IoGetAttachedDeviceReference(PdoData->Self); if(AttachedDevice == NULL) { Bus_KdPrint_Def( BUS_DBG_SS_ERROR, ("STATUS_INVALID_DEVICE\n")); return STATUS_NO_SUCH_DEVICE; } // // build an SRB for the miniport // srbIoctlBufferLength = (InputBufferLength>OutputBufferLength)?InputBufferLength:OutputBufferLength; srbIoctlLength = sizeof(SRB_IO_CONTROL) + srbIoctlBufferLength; psrbIoctl = (PSRB_IO_CONTROL)ExAllocatePoolWithTag(NonPagedPool , srbIoctlLength, BUSENUM_POOL_TAG); if(psrbIoctl == NULL) { Bus_KdPrint_Def( BUS_DBG_SS_ERROR, ("STATUS_INSUFFICIENT_RESOURCES\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } RtlZeroMemory(psrbIoctl, srbIoctlLength); psrbIoctl->HeaderLength = sizeof(SRB_IO_CONTROL); RtlCopyMemory(psrbIoctl->Signature, NDASSCSI_IOCTL_SIGNATURE, 8); psrbIoctl->Timeout = 60 * 60; psrbIoctl->ControlCode = IoctlCode; psrbIoctl->Length = srbIoctlBufferLength; srbIoctlBuffer = (PUCHAR)psrbIoctl + sizeof(SRB_IO_CONTROL); RtlCopyMemory(srbIoctlBuffer, InputBuffer, InputBufferLength); // // Initialize the notification event. // KeInitializeEvent(&event, NotificationEvent, FALSE); startingOffset.QuadPart = 1; // // Build IRP for this request. // Note we do this synchronously for two reasons. If it was done // asynchonously then the completion code would have to make a special // check to deallocate the buffer. Second if a completion routine were // used then an additional IRP stack location would be needed. // irp = IoBuildSynchronousFsdRequest( IRP_MJ_SCSI, AttachedDevice, psrbIoctl, srbIoctlLength, &startingOffset, &event, &ioStatusBlock); irpStack = IoGetNextIrpStackLocation(irp); if (irp == NULL) { Bus_KdPrint_Def( BUS_DBG_SS_ERROR, ("STATUS_INSUFFICIENT_RESOURCES\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } // // Set major and minor codes. // irpStack->MajorFunction = IRP_MJ_SCSI; irpStack->MinorFunction = 1; // // Fill in SRB fields. // irpStack->Parameters.Others.Argument1 = &srb; // // Zero out the srb. // RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); srb.PathId = 0; srb.TargetId = 0; srb.Lun = 0; srb.Function = SRB_FUNCTION_IO_CONTROL; srb.Length = sizeof(SCSI_REQUEST_BLOCK); srb.SrbFlags = /*SRB_FLAGS_DATA_IN |*/ SRB_FLAGS_NO_QUEUE_FREEZE /*| SRB_FLAGS_BYPASS_FROZEN_QUEUE */; srb.OriginalRequest = irp; // // Set timeout to requested value. // srb.TimeOutValue = psrbIoctl->Timeout; // // Set the data buffer. // srb.DataBuffer = psrbIoctl; srb.DataTransferLength = srbIoctlLength; // // Flush the data buffer for output. This will insure that the data is // written back to memory. Since the data-in flag is the the port driver // will flush the data again for input which will ensure the data is not // in the cache. // /* KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE); */ status = IoCallDriver( AttachedDevice, irp ); // // Wait for request to complete. // if (status == STATUS_PENDING) { (VOID)KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL ); status = ioStatusBlock.Status; } // // get the result // // if(status == STATUS_SUCCESS) { if(OutputBuffer && OutputBufferLength) RtlCopyMemory(OutputBuffer, srbIoctlBuffer, OutputBufferLength); Bus_KdPrint_Def( BUS_DBG_SS_NOISE, ("%d succeeded!\n", IoctlCode)); // } if(psrbIoctl->ControlCode == STATUS_BUFFER_TOO_SMALL) { status = STATUS_BUFFER_TOO_SMALL; } cleanup: if(psrbIoctl) ExFreePool(psrbIoctl); if(AttachedDevice) ObDereferenceObject(AttachedDevice); return status; }
// // Query information on LanscsiBus // NTSTATUS LSBus_QueryInformation( PFDO_DEVICE_DATA FdoData, BOOLEAN Request32, PNDASBUS_QUERY_INFORMATION Query, PNDASBUS_INFORMATION Information, LONG OutBufferLength, PLONG OutBufferLenNeeded ) { NTSTATUS ntStatus; PLIST_ENTRY entry; PPDO_DEVICE_DATA PdoData; ntStatus = STATUS_SUCCESS; *OutBufferLenNeeded = OutBufferLength; PdoData = NULL; // // Acquire the mutex to prevent PdoData ( Device Extension ) to disappear. // KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); switch(Query->InfoClass) { case INFORMATION_NUMOFPDOS: { ULONG NumOfPDOs; NumOfPDOs = 0; for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { NumOfPDOs ++; } Information->NumberOfPDOs = NumOfPDOs; break; } case INFORMATION_PDO: { KIRQL oldIrql; for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); if(Query->SlotNo == PdoData->SlotNo) { ObReferenceObject(PdoData->Self); break; } PdoData = NULL; } if(PdoData) { KeAcquireSpinLock(&PdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql); if((Query->Flags & NDASBUS_QUERYFLAG_EVENTQUEUE) == 0) { // // Return legacy status value. // Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("LastAdapterStatus:PDO:%p Status:%08lx DevMod:%08lx SupFeat:%08lx EnFeat:%08lx\n", PdoData->Self, PdoData->LanscsiAdapterPDO.LastAdapterStatus, PdoData->LanscsiAdapterPDO.DeviceMode, PdoData->LanscsiAdapterPDO.SupportedFeatures, PdoData->LanscsiAdapterPDO.EnabledFeatures )); Information->PdoInfo.AdapterStatus = PdoData->LanscsiAdapterPDO.LastAdapterStatus; Information->PdoInfo.DeviceMode = PdoData->LanscsiAdapterPDO.DeviceMode; Information->PdoInfo.SupportedFeatures = PdoData->LanscsiAdapterPDO.SupportedFeatures; Information->PdoInfo.EnabledFeatures = PdoData->LanscsiAdapterPDO.EnabledFeatures; } else { // // Return status from the event queue. // ULONG adapterStatus; PNDASBUS_PDOEVENT_ENTRY ndasPdoStatus; ndasPdoStatus = NdasBusDequeuePdoStatusItem(&PdoData->LanscsiAdapterPDO); if(ndasPdoStatus) { BOOLEAN empty; adapterStatus = ndasPdoStatus->AdapterStatus; empty = NdasBusIsEmpty(&PdoData->LanscsiAdapterPDO); if(!empty) { adapterStatus |= NDASSCSI_ADAPTERINFO_STATUSFLAG_NEXT_EVENT_EXIST; } // // Free the entry // NdasBusDestroyPdoStatusItem(ndasPdoStatus); } else { KeReleaseSpinLock(&PdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); // // No more entry // Bus_KdPrint_Def(BUS_DBG_SS_NOISE, ("No more status item for SlotNo %d!\n", Query->SlotNo)); ntStatus = STATUS_NO_MORE_ENTRIES; break; } Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("QueuedAdapterStatus:PDO:%p Status:%08lx DevMod:%08lx SupFeat:%08lx EnFeat:%08lx\n", PdoData->Self, adapterStatus, PdoData->LanscsiAdapterPDO.DeviceMode, PdoData->LanscsiAdapterPDO.SupportedFeatures, PdoData->LanscsiAdapterPDO.EnabledFeatures )); Information->PdoInfo.AdapterStatus = adapterStatus; Information->PdoInfo.DeviceMode = PdoData->LanscsiAdapterPDO.DeviceMode; Information->PdoInfo.SupportedFeatures = PdoData->LanscsiAdapterPDO.SupportedFeatures; Information->PdoInfo.EnabledFeatures = PdoData->LanscsiAdapterPDO.EnabledFeatures; } KeReleaseSpinLock(&PdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); ObDereferenceObject(PdoData->Self); } else { Bus_KdPrint_Def(BUS_DBG_SS_NOISE, ("No PDO for SlotNo %d!\n", Query->SlotNo)); ntStatus = STATUS_NO_SUCH_DEVICE; } break; } case INFORMATION_PDOENUM: { LARGE_INTEGER TimeOut; ULONG resultLength; DEVICE_INSTALL_STATE deviceInstallState; for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); if(Query->SlotNo == PdoData->SlotNo) { ObReferenceObject(PdoData->Self); break; } PdoData = NULL; } ExReleaseFastMutex (&FdoData->Mutex); KeLeaveCriticalRegion(); if(!PdoData) { KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); ntStatus = STATUS_NO_SUCH_DEVICE; break; } // // Wait until NDAS service sends AddTargetData. // Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("waiting for AddTargetEvent.\n")); TimeOut.QuadPart = -10 * 1000 * 1000 * 120; // 120 seconds ntStatus = KeWaitForSingleObject( &PdoData->LanscsiAdapterPDO.AddTargetEvent, Executive, KernelMode, FALSE, &TimeOut ); if(ntStatus != STATUS_SUCCESS) { KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("failed to wait for AddTargetEvent.\n")); ntStatus = STATUS_NO_SUCH_DEVICE; ObDereferenceObject(PdoData->Self); break; } Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Completed to wait for AddTargetEvent.\n")); if(PdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) { // // A LUR descriptor is set. // if(PdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); ntStatus = STATUS_NO_SUCH_DEVICE; ObDereferenceObject(PdoData->Self); break; } *OutBufferLenNeeded = FIELD_OFFSET(NDASBUS_INFORMATION, PdoEnumInfo) + FIELD_OFFSET(NDASBUS_INFORMATION_PDOENUM, AddDevInfo) + PdoData->LanscsiAdapterPDO.AddDevInfoLength; if(OutBufferLength < *OutBufferLenNeeded) { ntStatus = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory( Information->PdoEnumInfo.AddDevInfo, PdoData->LanscsiAdapterPDO.AddDevInfo, PdoData->LanscsiAdapterPDO.AddDevInfoLength ); Information->PdoEnumInfo.Flags = PDOENUM_FLAG_LURDESC; Information->PdoEnumInfo.MaxRequestLength = PdoData->LanscsiAdapterPDO.MaxRequestLength; // // Check to see if this is the first enumeration. // ntStatus = DrGetDeviceProperty( PdoData->Self, DevicePropertyInstallState, sizeof(deviceInstallState), &deviceInstallState, &resultLength, (Globals.MajorVersion == 5) && (Globals.MinorVersion == 0) ); if(NT_SUCCESS(ntStatus)) { if(deviceInstallState != InstallStateInstalled) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("First time installation. Do not enumerate a device.\n")); Information->PdoEnumInfo.Flags |= PDOENUM_FLAG_DRV_NOT_INSTALLED; } } else { // // Even if DrGetDeviceProperty() fails, // we can mount the device successfully. // ntStatus = STATUS_SUCCESS; } } } else { // // ADD_TARGET_DATA is set. // PNDASBUS_ADD_TARGET_DATA AddTargetData; LONG InfoBuffLenNeeded; AddTargetData = PdoData->LanscsiAdapterPDO.AddDevInfo; if(AddTargetData == NULL) { KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); ntStatus = STATUS_NO_SUCH_DEVICE; ObDereferenceObject(PdoData->Self); break; } // // calculate the length needed. // InfoBuffLenNeeded = FIELD_OFFSET(NDASBUS_INFORMATION, PdoEnumInfo) + FIELD_OFFSET(NDASBUS_INFORMATION_PDOENUM, AddDevInfo) + PdoData->LanscsiAdapterPDO.AddDevInfoLength; *OutBufferLenNeeded = InfoBuffLenNeeded; if(OutBufferLength < InfoBuffLenNeeded) { ntStatus = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory( Information->PdoEnumInfo.AddDevInfo, AddTargetData, PdoData->LanscsiAdapterPDO.AddDevInfoLength); Information->PdoEnumInfo.Flags = 0; Information->PdoEnumInfo.MaxRequestLength = PdoData->LanscsiAdapterPDO.MaxRequestLength; // // Check to see if this is the first enumeration. // ntStatus = DrGetDeviceProperty( PdoData->Self, DevicePropertyInstallState, sizeof(deviceInstallState), &deviceInstallState, &resultLength, (Globals.MajorVersion == 5) && (Globals.MinorVersion == 0) ); if(NT_SUCCESS(ntStatus)) { if(deviceInstallState != InstallStateInstalled) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("First time installation. Do not enumerate a device.\n")); Information->PdoEnumInfo.Flags |= PDOENUM_FLAG_DRV_NOT_INSTALLED; } } else { // // Even if DrGetDeviceProperty() fails, // we can mount the device successfully. // ntStatus = STATUS_SUCCESS; Information->PdoEnumInfo.Flags &= ~PDOENUM_FLAG_DRV_NOT_INSTALLED; } } } KeEnterCriticalRegion(); ExAcquireFastMutex (&FdoData->Mutex); ObDereferenceObject(PdoData->Self); break; } case INFORMATION_PDOEVENT: { for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); if(Query->SlotNo == PdoData->SlotNo) { ObReferenceObject(PdoData->Self); break; } PdoData = NULL; } if(PdoData == NULL) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not find the PDO:%u.\n", Query->SlotNo)); ntStatus = STATUS_NO_SUCH_DEVICE; break; } if( Query->Flags & NDASBUS_QUERYFLAG_USERHANDLE) { if(Request32 == FALSE) { Information->PdoEvents.SlotNo = PdoData->SlotNo; Information->PdoEvents.Flags = NDASBUS_QUERYFLAG_USERHANDLE; // // Get user-mode event handles. // ntStatus = ObOpenObjectByPointer( PdoData->LanscsiAdapterPDO.DisconEventToService, 0, NULL, EVENT_ALL_ACCESS, *ExEventObjectType, UserMode, &Information->PdoEvents.DisconEvent ); if(!NT_SUCCESS(ntStatus)) { ObDereferenceObject(PdoData->Self); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n")); break; } ntStatus = ObOpenObjectByPointer( PdoData->LanscsiAdapterPDO.AlarmEventToService, 0, NULL, EVENT_ALL_ACCESS, *ExEventObjectType, UserMode, &Information->PdoEvents.AlarmEvent ); if(!NT_SUCCESS(ntStatus)) { ObDereferenceObject(PdoData->Self); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n")); break; } } else { HANDLE disconEvent, alarmEvent; // // Need 32-bit thunk // Information->PdoEvents32.SlotNo = PdoData->SlotNo; Information->PdoEvents32.Flags = NDASBUS_QUERYFLAG_USERHANDLE; // // Get user-mode event handles. // ntStatus = ObOpenObjectByPointer( PdoData->LanscsiAdapterPDO.DisconEventToService, 0, NULL, EVENT_ALL_ACCESS, *ExEventObjectType, UserMode, &disconEvent ); if(!NT_SUCCESS(ntStatus)) { ObDereferenceObject(PdoData->Self); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n")); break; } ntStatus = ObOpenObjectByPointer( PdoData->LanscsiAdapterPDO.AlarmEventToService, 0, NULL, EVENT_ALL_ACCESS, *ExEventObjectType, UserMode, &alarmEvent ); if(!NT_SUCCESS(ntStatus)) { ObDereferenceObject(PdoData->Self); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n")); break; } // // Thunk event handles to 32 bit // ntStatus = RtlULongPtrToULong((ULONG_PTR)disconEvent, (PULONG)&Information->PdoEvents32.DisconEvent); if(!NT_SUCCESS(ntStatus)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOEVENTS: error conversion. Handle=%p\n", disconEvent)); ObDereferenceObject(PdoData->Self); break; } ntStatus = RtlULongPtrToULong((ULONG_PTR)alarmEvent, (PULONG)&Information->PdoEvents32.AlarmEvent); if(!NT_SUCCESS(ntStatus)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOEVENTS: error conversion. Handle=%p\n", alarmEvent)); ObDereferenceObject(PdoData->Self); break; } } } else { if(Request32) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOEVENTS: 32-bit thunking not supported.\n")); ObDereferenceObject(PdoData->Self); ntStatus = STATUS_INVALID_DEVICE_REQUEST; break; } Information->PdoEvents.SlotNo = PdoData->SlotNo; Information->PdoEvents.Flags = 0; Information->PdoEvents.DisconEvent = PdoData->LanscsiAdapterPDO.DisconEventToService; Information->PdoEvents.AlarmEvent = PdoData->LanscsiAdapterPDO.AlarmEventToService; } ObDereferenceObject(PdoData->Self); break; } case INFORMATION_ISREGISTERED: { ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); ntStatus = LSBus_IsRegistered(FdoData, Query->SlotNo); break; } case INFORMATION_PDOSLOTLIST: { LONG outputLength; LONG entryCnt; if(OutBufferLength < FIELD_OFFSET(NDASBUS_INFORMATION, PdoSlotList)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Buffer size is less than required\n")); ntStatus = STATUS_INVALID_PARAMETER; break; } Information->Size = 0; Information->InfoClass = INFORMATION_PDOSLOTLIST; // // Add the size of information header. // outputLength = FIELD_OFFSET(NDASBUS_INFORMATION, PdoSlotList); outputLength += sizeof(UINT32); // SlotNoCnt entryCnt = 0; for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); // // Add the size of each slot entry. // outputLength += sizeof(UINT32); if(outputLength > OutBufferLength) { continue; } Information->PdoSlotList.SlotNo[entryCnt] = PdoData->SlotNo; Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Entry #%u: %u\n", entryCnt, PdoData->SlotNo)); entryCnt ++; } if(outputLength > OutBufferLength) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Could not find a Device(%d).\n", Query->SlotNo)); *OutBufferLenNeeded = outputLength; ntStatus = STATUS_BUFFER_TOO_SMALL; } else { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Entry count:%d.\n", entryCnt)); Information->Size = outputLength; Information->PdoSlotList.SlotNoCnt = entryCnt; *OutBufferLenNeeded = outputLength; } break; } case INFORMATION_PDOFILEHANDLE: { PWCHAR devName; USHORT devNameLen; OBJECT_ATTRIBUTES objectAttr; UNICODE_STRING objName; HANDLE devFileHandle; IO_STATUS_BLOCK ioStatus; devName = NULL; for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link); if(Query->SlotNo == PdoData->SlotNo) { ObReferenceObject(PdoData->Self); break; } PdoData = NULL; } if(PdoData == NULL) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not find the PDO:%u.\n", Query->SlotNo)); ntStatus = STATUS_NO_SUCH_DEVICE; break; } // // Get the name of the physical device object. // ntStatus = GetPhyDeviceName(PdoData->Self, &devName, &devNameLen); if(!NT_SUCCESS(ntStatus)) { ObDereferenceObject(PdoData->Self); break; } // // Build unicode name of the device. // Get rid of NULL termination from the length // objName.Buffer = devName; if(devNameLen > 0 && devName[devNameLen/sizeof(WCHAR) - 1] == L'\0') { objName.MaximumLength = devNameLen; objName.Length = devNameLen - sizeof(WCHAR); } else { objName.MaximumLength = objName.Length = devNameLen; } // // Open a device file. // if(Query->Flags & NDASBUS_QUERYFLAG_USERHANDLE) { if(Request32 == FALSE) Information->PdoFile.Flags = NDASBUS_QUERYFLAG_USERHANDLE; else Information->PdoFile32.Flags = NDASBUS_QUERYFLAG_USERHANDLE; InitializeObjectAttributes(&objectAttr, &objName, OBJ_CASE_INSENSITIVE , NULL, NULL); } else { if(Request32 == FALSE) Information->PdoFile.Flags = 0; else Information->PdoFile32.Flags = 0; InitializeObjectAttributes(&objectAttr, &objName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); } ntStatus = ZwCreateFile( &devFileHandle, SYNCHRONIZE|FILE_READ_DATA, &objectAttr, &ioStatus, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if(!NT_SUCCESS(ntStatus)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open the PDO:%u. STATUS=%08lx\n", Query->SlotNo, ntStatus)); ExFreePool(devName); ObDereferenceObject(PdoData->Self); break; } // // Set the return values // if(Request32 == FALSE) { Information->PdoFile.SlotNo = PdoData->SlotNo; Information->PdoFile.PdoFileHandle = devFileHandle; } else { // // Need 32 bit thunking // ntStatus = RtlULongPtrToULong((ULONG_PTR)devFileHandle, (PULONG)&Information->PdoFile32.PdoFileHandle); if(!NT_SUCCESS(ntStatus)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOEVENTS: error conversion. Handle=%p\n", devFileHandle)); ObDereferenceObject(PdoData->Self); break; } Information->PdoFile32.SlotNo = PdoData->SlotNo; } if(devName) ExFreePool(devName); ObDereferenceObject(PdoData->Self); break; } default: ntStatus = STATUS_INVALID_PARAMETER; } ExReleaseFastMutex (&FdoData->Mutex); KeLeaveCriticalRegion(); return ntStatus; }
//这个函数主要用于确定线程结束时的APC参数 //由于实现关系, ThreadHandle/Thread必须为有效的非系统线程句柄/指针 //Handle 为TRUE时使用ThreadHandle // 为FALSE使用Thread BOOLEAN EnviromentSpecialInitialize(HANDLE ThreadHandle, PVOID Thread, BOOLEAN Handle) { BOOLEAN retVal; PETHREAD thread; NTSTATUS status; KPROCESSOR_MODE previousMode; //已经初始化了 if(PsExitSpecialApc || PspExitApcRundown || PspExitNormalApc) { return TRUE; } if(Handle) { status = ObReferenceObjectByHandle(ThreadHandle, THREAD_TERMINATE, *PsThreadType, KernelMode, &thread, NULL); if(!NT_SUCCESS(status)) return FALSE; ObDereferenceObject(thread); } else { thread = Thread; status = ObOpenObjectByPointer(Thread, OBJ_KERNEL_HANDLE, NULL, 0, *PsThreadType, KernelMode, &ThreadHandle); if(!NT_SUCCESS(status)) return FALSE; } EThreadForGetApc = thread; retVal = HookFunction(KeInsertQueueApc, FakeKeInsertQueueApc, KeInsertQueueApcJumpBack); if(!retVal) { EThreadForGetApc = NULL; return retVal; } previousMode = SetCurrentThreadProcessorMode(KernelMode); NtTerminateThread(ThreadHandle, 0x12345678); SetCurrentThreadProcessorMode(previousMode); if(!Handle) ZwClose(ThreadHandle); return TRUE; }
DWORD APIENTRY NtUserGetGuiResources( HANDLE hProcess, DWORD uiFlags) { PEPROCESS Process; PPROCESSINFO W32Process; NTSTATUS Status; DWORD Ret = 0; DECLARE_RETURN(DWORD); TRACE("Enter NtUserGetGuiResources\n"); UserEnterShared(); Status = ObReferenceObjectByHandle(hProcess, PROCESS_QUERY_INFORMATION, *PsProcessType, ExGetPreviousMode(), (PVOID*)&Process, NULL); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( 0); } W32Process = (PPROCESSINFO)Process->Win32Process; if(!W32Process) { ObDereferenceObject(Process); EngSetLastError(ERROR_INVALID_PARAMETER); RETURN( 0); } switch(uiFlags) { case GR_GDIOBJECTS: { Ret = (DWORD)W32Process->GDIHandleCount; break; } case GR_USEROBJECTS: { Ret = (DWORD)W32Process->UserHandleCount; break; } default: { EngSetLastError(ERROR_INVALID_PARAMETER); break; } } ObDereferenceObject(Process); RETURN( Ret); CLEANUP: TRACE("Leave NtUserGetGuiResources, ret=%lu\n",_ret_); UserLeave(); END_CLEANUP; }
NTSTATUS SecondaryRecoverySession ( IN PSECONDARY Secondary ) { NTSTATUS status; LONG slotIndex; LARGE_INTEGER timeOut; OBJECT_ATTRIBUTES objectAttributes; ULONG reconnectionTry; PLIST_ENTRY ccblistEntry; BOOLEAN isLocalAddress; SetFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING ); ASSERT( FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ); ASSERT( Secondary->ThreadHandle ); ASSERT( IsListEmpty(&Secondary->RequestQueue) ); for (slotIndex=0; slotIndex < Secondary->Thread.SessionContext.SessionSlotCount; slotIndex++) { ASSERT( Secondary->Thread.SessionSlot[slotIndex] == NULL ); } if (Secondary->ThreadHandle) { ASSERT( Secondary->ThreadObject ); timeOut.QuadPart = -NDASNTFS_TIME_OUT; status = KeWaitForSingleObject( Secondary->ThreadObject, Executive, KernelMode, FALSE, &timeOut ); if(status != STATUS_SUCCESS) { ASSERT( NDASNTFS_BUG ); return status; } DebugTrace( 0, Dbg2, ("Secondary_Stop: thread stoped\n") ); ObDereferenceObject( Secondary->ThreadObject ); Secondary->ThreadHandle = 0; Secondary->ThreadObject = 0; RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) ); } for (status = STATUS_UNSUCCESSFUL, reconnectionTry = 0; reconnectionTry < MAX_RECONNECTION_TRY; reconnectionTry++) { if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_TARGET_DEVICE_STOPPED)) { ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING ); return STATUS_UNSUCCESSFUL; } if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_SHUTDOWN)) { ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING ); return STATUS_UNSUCCESSFUL; } if (FlagOn(Secondary->VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_SHUTDOWN)) { //DebugTrace( 0, Dbg2, ("SecondaryToPrimary NDAS_NTFS_DEVICE_FLAG_SHUTDOWN\n") ); //DbgPrint( "SecondaryToPrimary NDAS_NTFS_DEVICE_FLAG_SHUTDOWN\n" ); ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING ); return STATUS_UNSUCCESSFUL; } if (Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY) { status = STATUS_SUCCESS; } else { status = ((PVOLUME_DEVICE_OBJECT) NdasNtfsFileSystemDeviceObject)-> NdfsCallback.SecondaryToPrimary( Secondary->VolDo->Vcb.Vpb->RealDevice, TRUE ); if (status == STATUS_NO_SUCH_DEVICE) { NDAS_ASSERT( FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_TARGET_DEVICE_STOPPED) ); ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING ); return STATUS_UNSUCCESSFUL; } } //NtfsDebugTraceLevel = 0; DebugTrace( 0, Dbg2, ("SecondaryToPrimary status = %x\n", status) ); if (status == STATUS_SUCCESS) { PVCB vcb = &Secondary->VolDo->Vcb; TOP_LEVEL_CONTEXT topLevelContext; PTOP_LEVEL_CONTEXT threadTopLevelContext; PIRP_CONTEXT tempIrpContext = NULL; SetFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME ); ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) ); ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) ); DebugTrace( 0, Dbg2, ("Vcb->State = %X\n", vcb->VcbState) ); DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) ); DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) ); tempIrpContext = NULL; threadTopLevelContext = NtfsInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE ); ASSERT( threadTopLevelContext == &topLevelContext ); NtfsInitializeIrpContext( NULL, TRUE, &tempIrpContext ); NtfsUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext ); SetFlag( tempIrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT ); ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) ); tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME; tempIrpContext->Vcb = vcb; try { status = CleanUpVcb( tempIrpContext, vcb ); } finally { NtfsCompleteRequest( tempIrpContext, NULL, 0 ); ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext ); tempIrpContext = NULL; } ASSERT( status == STATUS_SUCCESS ); ASSERT( FlagOn(vcb->VcbState, VCB_STATE_MOUNT_COMPLETED) ); ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) ); ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) ); ClearFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME ); DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) ); DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) ); DebugTrace( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->CloseCount) ); Secondary->VolDo->NetdiskEnableMode = NETDISK_SECONDARY2PRIMARY; tempIrpContext = NULL; threadTopLevelContext = NtfsInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE ); ASSERT( threadTopLevelContext == &topLevelContext ); NtfsInitializeIrpContext( NULL, TRUE, &tempIrpContext ); NtfsUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext ); ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) ); //tempIrpContext->TopLevelIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; //tempIrpContext->TopLevelIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME; tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME; tempIrpContext->Vcb = vcb; try { status = NdasNtfsMountVolume( tempIrpContext, vcb ); } finally { NtfsCompleteRequest( tempIrpContext, NULL, 0 ); ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext ); tempIrpContext = NULL; } NDAS_ASSERT( status == STATUS_SUCCESS ); ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) ); ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) ); DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) ); DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) ); DebugTrace( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->CloseCount) ); if (vcb->MftScb) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftScb->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftScb->Header.Resource) ); } if (vcb->Mft2Scb) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->Mft2Scb->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->Mft2Scb->Header.Resource) ); } if (vcb->LogFileScb) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->LogFileScb->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->LogFileScb->Header.Resource) ); } if (vcb->VolumeDasdScb) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->VolumeDasdScb->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->VolumeDasdScb->Header.Resource) ); } if (vcb->AttributeDefTableScb) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->AttributeDefTableScb->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->AttributeDefTableScb->Header.Resource) ); } if (vcb->UpcaseTableScb) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UpcaseTableScb->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UpcaseTableScb->Header.Resource) ); } if (vcb->RootIndexScb) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->RootIndexScb->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->RootIndexScb->Header.Resource) ); } if (vcb->BitmapScb) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BitmapScb->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BitmapScb->Header.Resource) ); } if (vcb->BadClusterFileScb) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BadClusterFileScb->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BadClusterFileScb->Header.Resource) ); } if (vcb->MftBitmapScb) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftBitmapScb->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftBitmapScb->Header.Resource) ); } if (vcb->SecurityDescriptorStream) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorStream->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorStream->Header.Resource) ); } if (vcb->UsnJournal) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UsnJournal->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UsnJournal->Header.Resource) ); } if (vcb->ExtendDirectory) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->ExtendDirectory->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->ExtendDirectory->Header.Resource) ); } if (vcb->SecurityDescriptorHashIndex) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorHashIndex->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorHashIndex->Header.Resource) ); } if (vcb->SecurityIdIndex) { ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityIdIndex->Header.Resource) ); ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityIdIndex->Header.Resource) ); } } Secondary->NumberOfPrimaryAddress = 0; status = ((PVOLUME_DEVICE_OBJECT) NdasNtfsFileSystemDeviceObject)-> NdfsCallback.QueryPrimaryAddress( &Secondary->VolDo->NetdiskPartitionInformation, Secondary->PrimaryAddressList, &Secondary->NumberOfPrimaryAddress, &isLocalAddress ); DebugTrace2( 0, Dbg2, ("RecoverySession: QueryPrimaryAddress status = %X\n", status) ); if (status == STATUS_SUCCESS && !(Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY && isLocalAddress)) { LONG i; NDAS_ASSERT( Secondary->NumberOfPrimaryAddress ); for (i = 0; i < Secondary->NumberOfPrimaryAddress; i++) { DebugTrace2( 0, Dbg, ("RecoverySession: Secondary = %p Found PrimaryAddress[%d] :%02x:%02x:%02x:%02x:%02x:%02x/%d\n", Secondary, i, Secondary->PrimaryAddressList[i].Node[0], Secondary->PrimaryAddressList[i].Node[1], Secondary->PrimaryAddressList[i].Node[2], Secondary->PrimaryAddressList[i].Node[3], Secondary->PrimaryAddressList[i].Node[4], Secondary->PrimaryAddressList[i].Node[5], NTOHS(Secondary->PrimaryAddressList[i].Port)) ); } } else { continue; } KeInitializeEvent( &Secondary->ReadyEvent, NotificationEvent, FALSE ); KeInitializeEvent( &Secondary->RequestEvent, NotificationEvent, FALSE ); InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); status = PsCreateSystemThread( &Secondary->ThreadHandle, THREAD_ALL_ACCESS, &objectAttributes, NULL, NULL, SecondaryThreadProc, Secondary ); if (!NT_SUCCESS(status)) { ASSERT( NDASNTFS_UNEXPECTED ); break; } status = ObReferenceObjectByHandle( Secondary->ThreadHandle, FILE_READ_DATA, NULL, KernelMode, &Secondary->ThreadObject, NULL ); if (!NT_SUCCESS(status)) { ASSERT( NDASNTFS_INSUFFICIENT_RESOURCES ); break; } timeOut.QuadPart = -NDASNTFS_TIME_OUT; status = KeWaitForSingleObject( &Secondary->ReadyEvent, Executive, KernelMode, FALSE, &timeOut ); if(status != STATUS_SUCCESS) { ASSERT( NDASNTFS_BUG ); break; } KeClearEvent( &Secondary->ReadyEvent ); InterlockedIncrement( &Secondary->SessionId ); ExAcquireFastMutex( &Secondary->FastMutex ); if (!FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_START) || FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_STOPED)) { ExReleaseFastMutex( &Secondary->FastMutex ); if(Secondary->Thread.SessionStatus == STATUS_DISK_CORRUPT_ERROR) { status = STATUS_SUCCESS; break; } timeOut.QuadPart = -NDASNTFS_TIME_OUT; status = KeWaitForSingleObject( Secondary->ThreadObject, Executive, KernelMode, FALSE, &timeOut ); if(status != STATUS_SUCCESS) { ASSERT( NDASNTFS_BUG ); return status; } DebugTrace( 0, Dbg, ("Secondary_Stop: thread stoped\n") ); ObDereferenceObject( Secondary->ThreadObject ); Secondary->ThreadHandle = 0; Secondary->ThreadObject = 0; RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) ); continue; } ExReleaseFastMutex( &Secondary->FastMutex ); status = STATUS_SUCCESS; DebugTrace( 0, Dbg2, ("SessionRecovery Success Secondary = %p\n", Secondary) ); break; }
NTSTATUS NTAPI CmpOpenHiveFiles(IN PCUNICODE_STRING BaseName, IN PCWSTR Extension OPTIONAL, OUT PHANDLE Primary, OUT PHANDLE Log, OUT PULONG PrimaryDisposition, OUT PULONG LogDisposition, IN BOOLEAN CreateAllowed, IN BOOLEAN MarkAsSystemHive, IN BOOLEAN NoBuffering, OUT PULONG ClusterSize OPTIONAL) { HANDLE EventHandle; PKEVENT Event; NTSTATUS Status; UNICODE_STRING FullName, ExtensionName; PWCHAR NameBuffer; USHORT Length; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; ULONG AttributeFlags, ShareMode, DesiredAccess, CreateDisposition, IoFlags; USHORT CompressionState; FILE_STANDARD_INFORMATION FileInformation; FILE_FS_SIZE_INFORMATION FsSizeInformation; /* Create event */ Status = CmpCreateEvent(NotificationEvent, &EventHandle, &Event); if (!NT_SUCCESS(Status)) return Status; /* Initialize the full name */ RtlInitEmptyUnicodeString(&FullName, NULL, 0); Length = BaseName->Length; /* Check if we have an extension */ if (Extension) { /* Update the name length */ Length += (USHORT)wcslen(Extension) * sizeof(WCHAR) + sizeof(UNICODE_NULL); /* Allocate the buffer for the full name */ NameBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM); if (!NameBuffer) { /* Fail */ ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_NO_MEMORY; } /* Build the full name */ FullName.Buffer = NameBuffer; FullName.MaximumLength = Length; RtlAppendUnicodeStringToString(&FullName, BaseName); } else { /* The base name is the full name */ FullName = *BaseName; NameBuffer = NULL; } /* Initialize the attributes */ InitializeObjectAttributes(&ObjectAttributes, &FullName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); /* Check if we can create the hive */ if ((CreateAllowed) && !(CmpShareSystemHives)) { /* Open only or create */ CreateDisposition = FILE_OPEN_IF; } else { /* Open only */ CreateDisposition = FILE_OPEN; } /* Setup the flags */ // FIXME : FILE_OPEN_FOR_BACKUP_INTENT is unimplemented and breaks 3rd stage boot IoFlags = //FILE_OPEN_FOR_BACKUP_INTENT | FILE_NO_COMPRESSION | FILE_RANDOM_ACCESS | (NoBuffering ? FILE_NO_INTERMEDIATE_BUFFERING : 0); /* Set share and access modes */ if ((CmpMiniNTBoot) && (CmpShareSystemHives)) { /* We're on Live CD or otherwise sharing */ DesiredAccess = FILE_READ_DATA; ShareMode = FILE_SHARE_READ; } else { /* We want to write exclusively */ ShareMode = 0; DesiredAccess = FILE_READ_DATA | FILE_WRITE_DATA; } /* Default attributes */ AttributeFlags = FILE_ATTRIBUTE_NORMAL; /* Now create the file */ Status = ZwCreateFile(Primary, DesiredAccess | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, AttributeFlags, ShareMode, CreateDisposition, FILE_SYNCHRONOUS_IO_NONALERT | IoFlags, NULL, 0); /* Check if anything failed until now */ if (!NT_SUCCESS(Status)) { /* Close handles and free buffers */ if (NameBuffer) ExFreePool(NameBuffer); ObDereferenceObject(Event); ZwClose(EventHandle); DPRINT1("ZwCreateFile failed : %lx.\n", Status); *Primary = NULL; return Status; } if (MarkAsSystemHive) { /* We opened it, mark it as a system hive */ Status = ZwFsControlFile(*Primary, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_MARK_AS_SYSTEM_HIVE, NULL, 0, NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } /* If we don't support it, ignore the failure */ if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS; if (!NT_SUCCESS(Status)) { /* Close handles and free buffers */ if (NameBuffer) ExFreePool(NameBuffer); ObDereferenceObject(Event); ZwClose(EventHandle); ZwClose(*Primary); *Primary = NULL; return Status; } } /* Disable compression */ CompressionState = 0; Status = ZwFsControlFile(*Primary, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_SET_COMPRESSION, &CompressionState, sizeof(CompressionState), NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); } /* Get the disposition */ *PrimaryDisposition = (ULONG)IoStatusBlock.Information; if (IoStatusBlock.Information != FILE_CREATED) { /* Check how large the file is */ Status = ZwQueryInformationFile(*Primary, &IoStatusBlock, &FileInformation, sizeof(FileInformation), FileStandardInformation); if (NT_SUCCESS(Status)) { /* Check if it's 0 bytes */ if (!FileInformation.EndOfFile.QuadPart) { /* Assume it's a new file */ *PrimaryDisposition = FILE_CREATED; } } } /* Check if the caller wants cluster size returned */ if (ClusterSize) { /* Query it */ Status = ZwQueryVolumeInformationFile(*Primary, &IoStatusBlock, &FsSizeInformation, sizeof(FsSizeInformation), FileFsSizeInformation); if (!NT_SUCCESS(Status)) { /* Close handles and free buffers */ if (NameBuffer) ExFreePool(NameBuffer); ObDereferenceObject(Event); ZwClose(EventHandle); return Status; } /* Check if the sector size is invalid */ if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) { /* Close handles and free buffers */ if (NameBuffer) ExFreePool(NameBuffer); ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_CANNOT_LOAD_REGISTRY_FILE; } /* Return cluster size */ *ClusterSize = max(1, FsSizeInformation.BytesPerSector / HSECTOR_SIZE); } /* Check if we don't need to create a log file */ if (!Extension) { /* We're done, close handles */ ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_SUCCESS; } /* Check if we can create the hive */ CreateDisposition = CmpShareSystemHives ? FILE_OPEN : FILE_OPEN_IF; if (*PrimaryDisposition == FILE_CREATED) { /* Over-write the existing log file, since this is a new hive */ CreateDisposition = FILE_SUPERSEDE; } /* Setup the name */ RtlInitUnicodeString(&ExtensionName, Extension); RtlAppendUnicodeStringToString(&FullName, &ExtensionName); /* Initialize the attributes */ InitializeObjectAttributes(&ObjectAttributes, &FullName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); /* Setup the flags */ IoFlags = FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING; /* Check if this is a log file */ if (!_wcsnicmp(Extension, L".log", 4)) { /* Hide log files */ AttributeFlags |= FILE_ATTRIBUTE_HIDDEN; } /* Now create the file */ Status = ZwCreateFile(Log, DesiredAccess, &ObjectAttributes, &IoStatusBlock, NULL, AttributeFlags, ShareMode, CreateDisposition, IoFlags, NULL, 0); if ((NT_SUCCESS(Status)) && (MarkAsSystemHive)) { /* We opened it, mark it as a system hive */ Status = ZwFsControlFile(*Log, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_MARK_AS_SYSTEM_HIVE, NULL, 0, NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } /* If we don't support it, ignore the failure */ if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS; /* If we failed, close the handle */ if (!NT_SUCCESS(Status)) ZwClose(*Log); } /* Check if anything failed until now */ if (!NT_SUCCESS(Status)) { /* Clear the handle */ *Log = NULL; } else { /* Disable compression */ Status = ZwFsControlFile(*Log, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_SET_COMPRESSION, &CompressionState, sizeof(CompressionState), NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); } /* Return the disposition */ *LogDisposition = (ULONG)IoStatusBlock.Information; } /* We're done, close handles and free buffers */ if (NameBuffer) ExFreePool(NameBuffer); ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_SUCCESS; }
VOID Secondary_Stop ( IN PSECONDARY Secondary ) { NTSTATUS status; LARGE_INTEGER timeOut; PLIST_ENTRY secondaryRequestEntry; PSECONDARY_REQUEST secondaryRequest; DebugTrace2( 0, Dbg2, ("Secondary stop\n") ); ExAcquireFastMutex( &Secondary->FastMutex ); if (FlagOn(Secondary->Flags, SECONDARY_FLAG_CLOSED)) { ASSERT( FALSE ); ExReleaseFastMutex( &Secondary->FastMutex ); return; } SetFlag( Secondary->Flags, SECONDARY_FLAG_CLOSED ); ExReleaseFastMutex( &Secondary->FastMutex ); if (Secondary->ThreadHandle == NULL) { Secondary_Dereference(Secondary); return; } ASSERT( Secondary->ThreadObject != NULL ); secondaryRequest = AllocSecondaryRequest( Secondary, 0, FALSE ); secondaryRequest->RequestType = SECONDARY_REQ_DISCONNECT; QueueingSecondaryRequest( Secondary, secondaryRequest ); secondaryRequest = AllocSecondaryRequest( Secondary, 0, FALSE ); secondaryRequest->RequestType = SECONDARY_REQ_DOWN; QueueingSecondaryRequest( Secondary, secondaryRequest ); timeOut.QuadPart = - NDFAT_TIME_OUT; status = KeWaitForSingleObject( Secondary->ThreadObject, Executive, KernelMode, FALSE, &timeOut ); if (status == STATUS_SUCCESS) { DebugTrace2( 0, Dbg, ("Secondary_Stop: thread stoped Secondary = %p\n", Secondary)); ObDereferenceObject( Secondary->ThreadObject ); Secondary->ThreadHandle = NULL; Secondary->ThreadObject = NULL; } else { ASSERT( NDFAT_BUG ); return; } ASSERT( IsListEmpty(&Secondary->RecoveryCcbQueue) ); ASSERT( IsListEmpty(&Secondary->RequestQueue) ); while (secondaryRequestEntry = ExInterlockedRemoveHeadList(&Secondary->RequestQueue, &Secondary->RequestQSpinLock)) { PSECONDARY_REQUEST secondaryRequest; secondaryRequest = CONTAINING_RECORD( secondaryRequestEntry, SECONDARY_REQUEST, ListEntry ); secondaryRequest->ExecuteStatus = STATUS_IO_DEVICE_ERROR; if (secondaryRequest->Synchronous == TRUE) KeSetEvent( &secondaryRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE ); else DereferenceSecondaryRequest( secondaryRequest ); } return; }
// // gerneral ioctl to LanscsiBus // NTSTATUS IoctlToLanscsiBus( IN ULONG IoControlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, OUT PLONG BufferNeeded ) { NTSTATUS ntStatus; PWSTR symbolicLinkList; UNICODE_STRING objectName; PFILE_OBJECT fileObject; PDEVICE_OBJECT deviceObject; PIRP irp; KEVENT event; IO_STATUS_BLOCK ioStatus; KDPrint(2,("IoControlCode = %x\n", IoControlCode)); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); ntStatus = IoGetDeviceInterfaces( &GUID_LANSCSI_BUS_ENUMERATOR_INTERFACE_CLASS, NULL, 0, &symbolicLinkList ); if(!NT_SUCCESS(ntStatus)) { KDPrint(1,("IoGetDeviceInterfaces ntStatus = 0x%x\n", ntStatus)); return ntStatus; } ASSERT(symbolicLinkList != NULL); KDPrint(1,("symbolicLinkList = %ws\n", symbolicLinkList)); RtlInitUnicodeString(&objectName, symbolicLinkList); ntStatus = IoGetDeviceObjectPointer( &objectName, FILE_ALL_ACCESS, &fileObject, &deviceObject ); if(!NT_SUCCESS(ntStatus)) { KDPrint(1,("ntStatus = 0x%x\n", ntStatus)); ExFreePool(symbolicLinkList); return ntStatus; } KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest( IoControlCode, deviceObject, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, FALSE, &event, &ioStatus ); if (irp == NULL) { KDPrint(1,("irp NULL\n")); ExFreePool(symbolicLinkList); ObDereferenceObject(fileObject); return ntStatus; } KDPrint(2,("Before Done...ioStatus.Status = 0x%08x Information = %d\n", ioStatus.Status, ioStatus.Information)); ntStatus = IoCallDriver(deviceObject, irp); if (ntStatus == STATUS_PENDING) { KDPrint(1,("IoCallDriver STATUS_PENDING\n")); KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); ntStatus = ioStatus.Status; } else if(NT_SUCCESS(ntStatus)) { ntStatus = ioStatus.Status; } if(BufferNeeded) *BufferNeeded = ioStatus.Information; ExFreePool(symbolicLinkList); ObDereferenceObject(fileObject); KDPrint(1,("Done...ioStatus.Status = 0x%08x Information = %d\n", ioStatus.Status, ioStatus.Information)); return ntStatus; }
VOID CloseOpenFiles ( IN PPRIMARY_SESSION PrimarySession, IN BOOLEAN Remove ) { PLIST_ENTRY openFileEntry; for (openFileEntry = PrimarySession->Thread.OpenedFileQueue.Flink; openFileEntry != &PrimarySession->Thread.OpenedFileQueue; ) { POPEN_FILE openFile; NTSTATUS closeStatus; openFile = CONTAINING_RECORD( openFileEntry, OPEN_FILE, ListEntry ); openFileEntry = openFileEntry->Flink; //ASSERT( FALSE ); if (openFile->CleanUp == FALSE) { TYPE_OF_OPEN typeOfOpen; PVCB vcb; PFCB fcb; //PSCB scb; PCCB ccb; typeOfOpen = FatDecodeFileObject( openFile->FileObject, &vcb, &fcb, &ccb ); if (typeOfOpen == UserFileOpen) { PIRP irp; PFILE_OBJECT fileObject; PDEVICE_OBJECT deviceObject; KPROCESSOR_MODE requestorMode; PIO_STACK_LOCATION irpSp; BOOLEAN synchronousIo; PKEVENT eventObject = (PKEVENT) NULL; ULONG keyValue = 0; LARGE_INTEGER fileOffset = {0,0}; PULONG majorFunction; PETHREAD currentThread; KEVENT event; NDFS_WINXP_REQUEST_HEADER ndfsWinxpRequestHeader; PIRP topLevelIrp; PRIMARY_REQUEST_INFO primaryRequestInfo; NTSTATUS cleanupStatus; do { synchronousIo = openFile->FileObject ? BooleanFlagOn(openFile->FileObject->Flags, FO_SYNCHRONOUS_IO) : TRUE; ASSERT( synchronousIo == TRUE ); deviceObject = &PrimarySession->VolDo->DeviceObject; fileObject = openFile->FileObject; currentThread = PsGetCurrentThread (); ASSERT( deviceObject->StackSize >= 1 ); irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); requestorMode = KernelMode; if (!irp) { ASSERT( NDASFAT_INSUFFICIENT_RESOURCES ); break; } irp->Tail.Overlay.OriginalFileObject = fileObject; irp->Tail.Overlay.Thread = currentThread; irp->Tail.Overlay.AuxiliaryBuffer = (PVOID) NULL; irp->RequestorMode = requestorMode; irp->PendingReturned = FALSE; irp->Cancel = FALSE; irp->CancelRoutine = (PDRIVER_CANCEL) NULL; irp->UserEvent = eventObject; irp->UserIosb = NULL; //&ioStatusBlock; irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; //ApcRoutine; irp->Overlay.AsynchronousParameters.UserApcContext = NULL; //ApcContext; KeInitializeEvent( &event, NotificationEvent, FALSE ); IoSetCompletionRoutine( irp, PrimaryCompletionRoutine, &event, TRUE, TRUE, TRUE ); IoSetNextIrpStackLocation( irp ); irpSp = IoGetCurrentIrpStackLocation( irp ); // = ¤tIrpSp; // = IoGetNextIrpStackLocation( irp ); majorFunction = (PULONG) (&irpSp->MajorFunction); *majorFunction = IRP_MJ_CLEANUP; irpSp->Control = (SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL); irpSp->MinorFunction = IRP_MJ_CLEANUP; irpSp->FileObject = fileObject; irpSp->DeviceObject = deviceObject; irp->AssociatedIrp.SystemBuffer = (PVOID) NULL; irp->MdlAddress = (PMDL) NULL; ndfsWinxpRequestHeader.CleanUp.AllocationSize = fcb->Header.AllocationSize.QuadPart; ndfsWinxpRequestHeader.CleanUp.FileSize = fcb->Header.FileSize.LowPart; ndfsWinxpRequestHeader.CleanUp.ValidDataLength = fcb->Header.FileSize.LowPart; ndfsWinxpRequestHeader.CleanUp.VaildDataToDisk = fcb->Header.FileSize.LowPart; primaryRequestInfo.PrimaryTag = 0xe2027482; primaryRequestInfo.PrimarySession = PrimarySession; primaryRequestInfo.NdfsWinxpRequestHeader = &ndfsWinxpRequestHeader; topLevelIrp = IoGetTopLevelIrp(); ASSERT( topLevelIrp == NULL ); IoSetTopLevelIrp( (PIRP)&primaryRequestInfo ); cleanupStatus = FatFsdCleanup( PrimarySession->VolDo, irp ); if (cleanupStatus == STATUS_PENDING) { KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL ); } IoSetTopLevelIrp( topLevelIrp ); cleanupStatus = irp->IoStatus.Status; ASSERT( cleanupStatus == STATUS_SUCCESS ); if (irp->MdlAddress != NULL) { MmUnlockPages( irp->MdlAddress ); IoFreeMdl( irp->MdlAddress ); } IoFreeIrp( irp ); } while (0); } openFile->CleanUp = TRUE; } if (openFile->FileObject) { ObDereferenceObject( openFile->FileObject ); openFile->FileObject = NULL; } if (openFile->FileHandle) { closeStatus = ZwClose( openFile->FileHandle ); openFile->FileHandle = NULL; ASSERT( closeStatus == STATUS_SUCCESS ); } if (openFile->EventHandle) { closeStatus = ZwClose( openFile->EventHandle ); openFile->EventHandle = NULL; ASSERT(closeStatus == STATUS_SUCCESS); } if (Remove) { RemoveEntryList( &openFile->ListEntry ); InitializeListHead( &openFile->ListEntry ); PrimarySession_FreeOpenFile( PrimarySession, openFile ); } } return; }
~CEthread() { if (Id) ObDereferenceObject(Id); }
NTSTATUS NtSuspendThread( IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL ) /*++ Routine Description: This function suspends the target thread, and optionally returns the previous suspend count. Arguments: ThreadHandle - Supplies a handle to the thread object to suspend. PreviousSuspendCount - An optional parameter, that if specified points to a variable that receives the thread's previous suspend count. Return Value: return-value - Description of conditions needed to return value. - or - None. --*/ { PETHREAD Thread; NTSTATUS st; ULONG LocalPreviousSuspendCount; KPROCESSOR_MODE Mode; PAGED_CODE(); try { Mode = KeGetPreviousMode(); if ( Mode != KernelMode ) { if (ARGUMENT_PRESENT(PreviousSuspendCount)) { ProbeForWriteUlong(PreviousSuspendCount); } } } except (EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } st = ObReferenceObjectByHandle( ThreadHandle, THREAD_SUSPEND_RESUME, PsThreadType, Mode, (PVOID *)&Thread, NULL ); if ( !NT_SUCCESS(st) ) { return st; } try { if ( Thread != PsGetCurrentThread() ) { if ( Thread->HasTerminated ) { ObDereferenceObject(Thread); return STATUS_THREAD_IS_TERMINATING; } LocalPreviousSuspendCount = (ULONG) KeSuspendThread(&Thread->Tcb); } else { LocalPreviousSuspendCount = (ULONG) KeSuspendThread(&Thread->Tcb); } ObDereferenceObject(Thread); if (ARGUMENT_PRESENT(PreviousSuspendCount)) *PreviousSuspendCount = LocalPreviousSuspendCount; } except (EXCEPTION_EXECUTE_HANDLER) { st = GetExceptionCode(); // // Either the suspend, or the store could cause an // exception. The store is a partial success, while the // suspend exception is an error // if ( st == STATUS_SUSPEND_COUNT_EXCEEDED ) { ObDereferenceObject(Thread); } else { st = STATUS_SUCCESS; } return st; } return STATUS_SUCCESS; }
NTSTATUS ScDetective_DispatchDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS ntStatus = STATUS_SUCCESS; PVOID InputBuffer = NULL; PVOID OutputBuffer = NULL; ULONG cbInputBuffer = 0; ULONG cbOutputBuffer = 0; PIO_STACK_LOCATION irpSp = NULL; __try { irpSp = IoGetCurrentIrpStackLocation(Irp); InputBuffer = Irp->AssociatedIrp.SystemBuffer; cbInputBuffer = irpSp->Parameters.DeviceIoControl.InputBufferLength; OutputBuffer = Irp->AssociatedIrp.SystemBuffer; cbOutputBuffer = irpSp->Parameters.DeviceIoControl.OutputBufferLength; switch(irpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_DUMP_KERNEL_MEMORY: { PVOID DumpAddress; PMDL MdlCreate; if (cbInputBuffer == sizeof(ULONG)) { DumpAddress = (PVOID)((PULONG)InputBuffer)[0]; if (!MmIsAddressValid(DumpAddress)) { ntStatus = STATUS_INVALID_ADDRESS; break; } else { ScmMapVirtualAddress(DumpAddress, cbOutputBuffer, &MdlCreate); RtlCopyMemory(OutputBuffer, DumpAddress, cbOutputBuffer); ScmUnmapVirtualAddress(MdlCreate); Irp->IoStatus.Information = cbOutputBuffer; break; } } else { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_SSDT: // ��ȡ ssdt { ULONG NeedLen = 0; ULONG Number = GetSsdtServiceNumber(); NeedLen = Number * sizeof(SSDT_ADDRESS); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } Number = GetSsdtCurrentAddresses((PSSDT_ADDRESS)OutputBuffer, &NeedLen); if (Number == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = Number * sizeof(SSDT_ADDRESS); break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_UNHOOK_SSDT: // �ָ� ssdt { PSSDT_ADDRESS SsdtOrig = (PSSDT_ADDRESS)InputBuffer; if (cbInputBuffer < sizeof(SSDT_ADDRESS) || InputBuffer == NULL) { KdPrint(("���뻺���������뻺����������Ч")); ntStatus = STATUS_UNSUCCESSFUL; break; } KdPrint(("Ҫ�ָ��ķ����ţ�%d ԭʼ��ַ��0x%X", SsdtOrig->nIndex, SsdtOrig->FunAddress)); if (!UnHookSsdtItem(SsdtOrig)) { KdPrint(("�ָ�ʧ��")); ntStatus = STATUS_UNSUCCESSFUL; } break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_SSDTSHADOW: { ULONG Number = GetShadowSsdtServiceNumber(); ULONG NeedLen = 0; NeedLen = Number * sizeof(SSDT_ADDRESS); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } Number = GetShadowSsdtCurrentAddresses((PSSDT_ADDRESS)OutputBuffer, &NeedLen); if (Number == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = Number * sizeof(SSDT_ADDRESS); break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_UNHOOK_SSDTSHADOW: { PSSDT_ADDRESS ShadowSsdtOrig = (PSSDT_ADDRESS)InputBuffer; if (cbInputBuffer < sizeof(SSDT_ADDRESS) || InputBuffer == NULL) { KdPrint(("���뻺���������뻺����������Ч")); ntStatus = STATUS_UNSUCCESSFUL; break; } KdPrint(("Ҫ�ָ��ķ����ţ�%d ԭʼ��ַ��0x%X", ShadowSsdtOrig->nIndex, ShadowSsdtOrig->FunAddress)); if (!UnHookShadowSsdtItem(ShadowSsdtOrig, g_CsrssProcess)) { ntStatus = STATUS_UNSUCCESSFUL; } break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_PROCESSES: { PPROCESS_LIST_HEAD ProcessHead; ULONG NeedLen; ULONG ReturnLength; ProcessHead = ScPsQuerySystemProcessList(); NeedLen = ProcessHead->NumberOfProcesses * sizeof(PROCESS_INFO); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } ReturnLength = ExCopyProcessList2Buffer((PPROCESS_INFO)OutputBuffer); if (ReturnLength == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = ReturnLength; break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_PROCESS_IMAGE_PATH: { PEPROCESS Process = NULL; PUNICODE_STRING NameString; ULONG BufferSize; if (cbInputBuffer == sizeof(ULONG)) { Process = ((PEPROCESS*)InputBuffer)[0]; if (Process == NULL) { ntStatus = STATUS_ACCESS_DENIED; break; } } else { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } if (Process == g_SystemProcess) { if (cbOutputBuffer > sizeof(L"System")) { RtlCopyMemory(OutputBuffer, L"System", sizeof(L"System")); Irp->IoStatus.Information = sizeof(L"System"); break; } } else if (Process == g_IdleProcess) { if (cbOutputBuffer > sizeof(L"Idle")) { RtlCopyMemory(OutputBuffer, L"Idle", sizeof(L"Idle")); Irp->IoStatus.Information = sizeof(L"Idle"); break; } } if (cbOutputBuffer < 520) { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } BufferSize = cbOutputBuffer + sizeof(UNICODE_STRING); NameString = ExAllocatePoolWithTag(NonPagedPool, BufferSize, MEM_TAG); NameString->Buffer = (PWCH)((ULONG)NameString + 8); NameString->Length = 0; NameString->MaximumLength = (USHORT)cbOutputBuffer; ntStatus = ScPsGetProcessImagePath(Process, NameString); if (NT_SUCCESS(ntStatus)) { RtlCopyMemory(OutputBuffer, NameString->Buffer, NameString->Length); } Irp->IoStatus.Information = NameString->Length; ExFreePoolWithTag(NameString, MEM_TAG); break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_PROCESS_THREADS: { PTHREAD_LIST_HEAD ThreadHead = NULL; PEPROCESS EProcess = NULL; ULONG NeedLen = 0; ULONG ReturnLength = 0; if (cbInputBuffer == sizeof(ULONG)) { EProcess = ((PEPROCESS*)InputBuffer)[0]; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } if (EProcess == g_IdleProcess) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } } ThreadHead = ScPsQueryProcessThreadList(EProcess); if (ThreadHead == NULL) { ntStatus = STATUS_UNSUCCESSFUL; break; } NeedLen = ThreadHead->NumberOfThread * sizeof(THREAD_INFO); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } ReturnLength = ExCopyThreadList2Buffer((PTHREAD_INFO)OutputBuffer); if (ReturnLength == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = ReturnLength; break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_PROCESS_MODULES: { PMODULE_LIST_HEAD ModuleHead = NULL; PEPROCESS EProcess = NULL; ULONG NeedLen = 0; ULONG ReturnLength = 0; if (cbInputBuffer == sizeof(ULONG)) { EProcess = ((PEPROCESS*)InputBuffer)[0]; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } if (EProcess == g_IdleProcess) { if (cbOutputBuffer = sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } } ModuleHead = ScPsQueryProcessModuleList(EProcess); if (ModuleHead == NULL) { ntStatus = STATUS_UNSUCCESSFUL; break; } NeedLen = ModuleHead->NumberOfModules * sizeof(MODULE_INFO); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } ReturnLength = ExCopyModuleList2Buffer((PMODULE_INFO)OutputBuffer); if (ReturnLength == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = ReturnLength; break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_DRIVER_OBJECT: { PDRIVER_LIST_HEAD DriverHead = NULL; PEPROCESS EProcess = NULL; HANDLE UserEvent; PKEVENT kEvent; ULONG NeedLen = 0; ULONG ReturnLength = 0; if (cbInputBuffer == sizeof(HANDLE) * 2) { UserEvent = *(PHANDLE)InputBuffer; ntStatus = ObReferenceObjectByHandle(UserEvent, 0, *ExEventObjectType, UserMode, &kEvent, NULL); if (NT_SUCCESS(ntStatus)) { ScObQueryDriverObject(pdoGlobalDrvObj, kEvent); ObDereferenceObject(kEvent); } Irp->IoStatus.Information = 0; break; } DriverHead = ScObQueryDriverObject(NULL, NULL); if (DriverHead == NULL) { ntStatus = STATUS_UNSUCCESSFUL; break; } NeedLen = DriverHead->NumberOfDrivers * sizeof(DRIVER_INFO); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } ReturnLength = ExCopyDriverList2Buffer((PDRIVER_INFO)OutputBuffer); if (ReturnLength == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = ReturnLength; break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_LIST_DIRECTORY: { PWCHAR pszDirectory; ULONG NeedLength; ULONG ReturnLength; PFILE_LIST_HEAD FileHead; pszDirectory = ExAllocatePoolWithTag(PagedPool, 260 * 2, MEM_TAG); RtlZeroMemory(pszDirectory, 260 * 2); if (cbInputBuffer == 260 * 2) { RtlCopyMemory(pszDirectory, InputBuffer, 260 * 2); } else { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } FileHead = ScfsQueryDirectoryInformation(pszDirectory); if (FileHead == NULL) { ((PULONG)OutputBuffer)[0] = 0; Irp->IoStatus.Information = sizeof(ULONG); ntStatus = STATUS_SUCCESS; break; } NeedLength = FileHead->NumberOfItems * sizeof(FILE_INFO); if (cbOutputBuffer < NeedLength) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLength; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } ReturnLength = ExCopyFileList2Buffer((PFILE_INFO)OutputBuffer); if (ReturnLength == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = ReturnLength; ExFreePoolWithTag(pszDirectory, MEM_TAG); break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_PROTECT_MYSELF: { HANDLE ProcessId; if (cbInputBuffer == sizeof(ULONG)) { ProcessId = ((PHANDLE)InputBuffer)[0]; if (ProcessId) { ntStatus = ScPtHideProcessById(ProcessId); } } Irp->IoStatus.Information = 0; break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_EXIT_PROCESS: ScPtUnloadRoutine(); break; ////////////////////////////////////////////////////////////////////////// default: Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; break; } } __except (EXCEPTION_EXECUTE_HANDLER) { ntStatus = GetExceptionCode(); Irp->IoStatus.Information = 0; } Irp->IoStatus.Status = ntStatus; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; }
NTSTATUS NtSignalAndWaitForSingleObject( IN HANDLE SignalHandle, IN HANDLE WaitHandle, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL ) /*++ Routine Description: This function atomically signals the specified signal object and then waits until the specified wait object attains a state of Signaled. An optional timeout can also be specified. If a timeout is not specified, then the wait will not be satisfied until the wait object attains a state of Signaled. If a timeout is specified, and the wait object has not attained a state of Signaled when the timeout expires, then the wait is automatically satisfied. If an explicit timeout value of zero is specified, then no wait will occur if the wait cannot be satisfied immediately. The wait can also be specified as alertable. Arguments: SignalHandle - supplies the handle of the signal object. WaitHandle - Supplies the handle for the wait object. Alertable - Supplies a boolean value that specifies whether the wait is alertable. Timeout - Supplies an pointer to an absolute or relative time over which the wait is to occur. Return Value: The wait completion status. A value of STATUS_TIMEOUT is returned if a timeout occurred. A value of STATUS_SUCCESS is returned if the specified object satisfied the wait. A value of STATUS_ALERTED is returned if the wait was aborted to deliver an alert to the current thread. A value of STATUS_USER_APC is returned if the wait was aborted to deliver a user APC to the current thread. --*/ { OBJECT_HANDLE_INFORMATION HandleInformation; KPROCESSOR_MODE PreviousMode; PVOID RealObject; PVOID SignalObject; POBJECT_HEADER SignalObjectHeader; NTSTATUS Status; LARGE_INTEGER TimeoutValue; PVOID WaitObject; POBJECT_HEADER WaitObjectHeader; // // Establish an exception handler and probe the specified timeout value // if necessary. If the probe fails, then return the exception code as // the service status. // PreviousMode = KeGetPreviousMode(); if ((ARGUMENT_PRESENT(Timeout)) && (PreviousMode != KernelMode)) { try { TimeoutValue = ProbeAndReadLargeInteger(Timeout); Timeout = &TimeoutValue; } except(EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } } // // Reference the signal object by handle. // Status = ObReferenceObjectByHandle(SignalHandle, 0, NULL, PreviousMode, &SignalObject, &HandleInformation); // // If the reference was successful, then reference the wait object by // handle. // if (NT_SUCCESS(Status)) { Status = ObReferenceObjectByHandle(WaitHandle, SYNCHRONIZE, NULL, PreviousMode, &WaitObject, NULL); // // If the reference was successful, then determine the real wait // object, check the signal object access, signal the signal object, // and wait for the real wait object. // if (NT_SUCCESS(Status)) { WaitObjectHeader = OBJECT_TO_OBJECT_HEADER(WaitObject); RealObject = WaitObjectHeader->Type->DefaultObject; if ((LONG)RealObject >= 0) { RealObject = (PVOID)((PCHAR)WaitObject + (ULONG)RealObject); } // // If the signal object is an event, then check for modify access // and set the event. Otherwise, if the signal object is a mutant, // then attempt to release ownership of the mutant. Otherwise, if // the object is a semaphore, then check for modify access and // release the semaphore. Otherwise, the signal objet is invalid. // SignalObjectHeader = OBJECT_TO_OBJECT_HEADER(SignalObject); Status = STATUS_ACCESS_DENIED; if (SignalObjectHeader->Type == ExEventObjectType) { // // Check for access to the specified event object, // if ((PreviousMode != KernelMode) && (SeComputeDeniedAccesses(HandleInformation.GrantedAccess, EVENT_MODIFY_STATE) != 0)) { goto WaitExit; } // // If the wait object is also an event, the wait is not // alertable, and no timeout was specified, then the event // pair path can be used. Otherwise, set the event and wait // atomically. // if ((WaitObjectHeader->Type == ExEventObjectType) && (Alertable == FALSE) && (Timeout == NULL)) { Status = KiSetServerWaitClientEvent((PKEVENT)SignalObject, (PKEVENT)RealObject, PreviousMode); goto WaitExit; } // // Set the specified event and wait atomically. // KeSetEvent((PKEVENT)SignalObject, EVENT_INCREMENT, TRUE); } else if (SignalObjectHeader->Type == ExMutantObjectType) { // // Release the specified mutant and wait atomically. // // N.B. The release will only be successful if the current // thread is the owner of the mutant. // try { KeReleaseMutant((PKMUTANT)SignalObject, MUTANT_INCREMENT, FALSE, TRUE); } except(EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); goto WaitExit; } } else if (SignalObjectHeader->Type == ExSemaphoreObjectType) { // // Check for access to the specified semaphore object, // if ((PreviousMode != KernelMode) && (SeComputeDeniedAccesses(HandleInformation.GrantedAccess, SEMAPHORE_MODIFY_STATE) != 0)) { goto WaitExit; } // // Release the specified semaphore and wait atomically. // try { // // If the wait object is also a semaphore, the wait is // not alertable, and no timeout was specified, then // the semaphore path can be used. Otherwise, release // the semaphore and wait atomically. // if ((WaitObjectHeader->Type == ExSemaphoreObjectType) && (Alertable == FALSE) && (Timeout == NULL)) { Status = KeReleaseWaitForSemaphore((PKSEMAPHORE)SignalObject, (PKSEMAPHORE)RealObject, UserRequest, PreviousMode); goto WaitExit; } // // Release the specified semaphore and wait atomically. // KeReleaseSemaphore((PKSEMAPHORE)SignalObject, SEMAPHORE_INCREMENT, 1, TRUE); } except(EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); goto WaitExit; } } else { Status = STATUS_OBJECT_TYPE_MISMATCH; goto WaitExit; } Status = KeWaitForSingleObject(RealObject, UserRequest, PreviousMode, Alertable, Timeout); WaitExit: ObDereferenceObject(WaitObject); }
BOOLEAN SKillDeleteFile( IN HANDLE FileHandle ) { NTSTATUS ntStatus = STATUS_SUCCESS; PFILE_OBJECT fileObject; PDEVICE_OBJECT DeviceObject; PIRP Irp; KEVENT event; FILE_DISPOSITION_INFORMATION FileInformation; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION irpSp; PSECTION_OBJECT_POINTERS pSectionObjectPointer; //////////////////// BOOL bInit = FALSE; ReLoadNtosCALL(&RObReferenceObjectByHandle,L"ObReferenceObjectByHandle",SystemKernelModuleBase,ImageModuleBase); ReLoadNtosCALL(&RKeInitializeEvent,L"KeInitializeEvent",SystemKernelModuleBase,ImageModuleBase); ReLoadNtosCALL(&RIoAllocateIrp,L"IoAllocateIrp",SystemKernelModuleBase,ImageModuleBase); ReLoadNtosCALL(&RIoCallDriver,L"IoCallDriver",SystemKernelModuleBase,ImageModuleBase); ReLoadNtosCALL(&RKeWaitForSingleObject,L"KeWaitForSingleObject",SystemKernelModuleBase,ImageModuleBase); if (RObReferenceObjectByHandle && RKeInitializeEvent && RIoAllocateIrp && RIoCallDriver && RKeWaitForSingleObject) { bInit = TRUE; } if (!bInit) return NULL; SKillStripFileAttributes( FileHandle); //去掉只读属性,才能删除只读文件 ntStatus = RObReferenceObjectByHandle(FileHandle, DELETE, *IoFileObjectType, KernelMode, &fileObject, NULL); if (!NT_SUCCESS(ntStatus)) { return FALSE; } DeviceObject = IoGetRelatedDeviceObject(fileObject); Irp = RIoAllocateIrp(DeviceObject->StackSize, TRUE); if (Irp == NULL) { ObDereferenceObject(fileObject); return FALSE; } RKeInitializeEvent(&event, SynchronizationEvent, FALSE); FileInformation.DeleteFile = TRUE; Irp->AssociatedIrp.SystemBuffer = &FileInformation; Irp->UserEvent = &event; Irp->UserIosb = &ioStatus; Irp->Tail.Overlay.OriginalFileObject = fileObject; Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); Irp->RequestorMode = KernelMode; irpSp = IoGetNextIrpStackLocation(Irp); irpSp->MajorFunction = IRP_MJ_SET_INFORMATION; irpSp->DeviceObject = DeviceObject; irpSp->FileObject = fileObject; irpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION); irpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation; irpSp->Parameters.SetFile.FileObject = fileObject; IoSetCompletionRoutine( Irp, SkillSetFileCompletion, &event, TRUE, TRUE, TRUE); //再加上下面这三行代码 ,MmFlushImageSection 函数通过这个结构来检查是否可以删除文件。 //这个和Hook ulImageSectionObject = NULL; ulDataSectionObject = NULL; ulSharedCacheMap = NULL; pSectionObjectPointer = NULL; pSectionObjectPointer = fileObject->SectionObjectPointer; if (MmIsAddressValidEx(pSectionObjectPointer)) { ulImageSectionObject = pSectionObjectPointer->ImageSectionObject; // 备份之~~~ pSectionObjectPointer->ImageSectionObject = 0; //清零,准备删除 ulDataSectionObject = pSectionObjectPointer->DataSectionObject; //备份之 pSectionObjectPointer->DataSectionObject = 0; //清零,准备删除 ulSharedCacheMap = pSectionObjectPointer->SharedCacheMap; pSectionObjectPointer->SharedCacheMap = 0; } //发irp删除 RIoCallDriver(DeviceObject, Irp); //等待操作完毕 RKeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL); //删除文件之后,从备份那里填充回来 pSectionObjectPointer = NULL; pSectionObjectPointer = fileObject->SectionObjectPointer; if (MmIsAddressValidEx(pSectionObjectPointer)) { if (ulImageSectionObject) pSectionObjectPointer->ImageSectionObject = ulImageSectionObject; //填充回来,不然蓝屏哦 if (ulDataSectionObject) pSectionObjectPointer->DataSectionObject = ulDataSectionObject; if (ulSharedCacheMap) pSectionObjectPointer->SharedCacheMap = ulSharedCacheMap; } ObDereferenceObject(fileObject); fileObject = NULL; return TRUE; }
/*++ * @name ExpWorkerThreadBalanceManager * * The ExpWorkerThreadBalanceManager routine is the entrypoint for the * worker thread balance set manager. * * @param Context * Unused. * * @return None. * * @remarks The worker thread balance set manager listens every second, but can * also be woken up by an event when a new thread is needed, or by the * special shutdown event. This thread runs at priority 7. * * This routine must run at IRQL == PASSIVE_LEVEL. * *--*/ VOID NTAPI ExpWorkerThreadBalanceManager(IN PVOID Context) { KTIMER Timer; LARGE_INTEGER Timeout; NTSTATUS Status; PVOID WaitEvents[3]; PAGED_CODE(); UNREFERENCED_PARAMETER(Context); /* Raise our priority above all other worker threads */ KeSetBasePriorityThread(KeGetCurrentThread(), EX_CRITICAL_QUEUE_PRIORITY_INCREMENT + 1); /* Setup the timer */ KeInitializeTimer(&Timer); Timeout.QuadPart = Int32x32To64(-1, 10000000); /* We'll wait on the periodic timer and also the emergency event */ WaitEvents[0] = &Timer; WaitEvents[1] = &ExpThreadSetManagerEvent; WaitEvents[2] = &ExpThreadSetManagerShutdownEvent; /* Start wait loop */ for (;;) { /* Wait for the timer */ KeSetTimer(&Timer, Timeout, NULL); Status = KeWaitForMultipleObjects(3, WaitEvents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); if (Status == 0) { /* Our timer expired. Check for deadlocks */ ExpDetectWorkerThreadDeadlock(); } else if (Status == 1) { /* Someone notified us, verify if we should create a new thread */ ExpCheckDynamicThreadCount(); } else if (Status == 2) { /* We are shutting down. Cancel the timer */ DPRINT1("System shutdown\n"); KeCancelTimer(&Timer); /* Make sure we have a final thread */ ASSERT(ExpLastWorkerThread); /* Wait for it */ KeWaitForSingleObject(ExpLastWorkerThread, Executive, KernelMode, FALSE, NULL); /* Dereference it and kill us */ ObDereferenceObject(ExpLastWorkerThread); PsTerminateSystemThread(STATUS_SYSTEM_SHUTDOWN); } } }
BOOLEAN SKillStripFileAttributes( IN HANDLE FileHandle ) { NTSTATUS ntStatus = STATUS_SUCCESS; PFILE_OBJECT fileObject; PDEVICE_OBJECT DeviceObject; PIRP Irp; KEVENT event; FILE_BASIC_INFORMATION FileInformation; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION irpSp; BOOL bInit = FALSE; ReLoadNtosCALL(&RObReferenceObjectByHandle,L"ObReferenceObjectByHandle",SystemKernelModuleBase,ImageModuleBase); ReLoadNtosCALL(&RKeInitializeEvent,L"KeInitializeEvent",SystemKernelModuleBase,ImageModuleBase); ReLoadNtosCALL(&RIoAllocateIrp,L"IoAllocateIrp",SystemKernelModuleBase,ImageModuleBase); ReLoadNtosCALL(&RIoCallDriver,L"IoCallDriver",SystemKernelModuleBase,ImageModuleBase); ReLoadNtosCALL(&RKeWaitForSingleObject,L"KeWaitForSingleObject",SystemKernelModuleBase,ImageModuleBase); if (RObReferenceObjectByHandle && RKeInitializeEvent && RIoAllocateIrp && RIoCallDriver && RKeWaitForSingleObject) { bInit = TRUE; } if (!bInit) return NULL; ntStatus = RObReferenceObjectByHandle(FileHandle, DELETE, *IoFileObjectType, KernelMode, &fileObject, NULL); if (!NT_SUCCESS(ntStatus)) { return FALSE; } DeviceObject = IoGetRelatedDeviceObject(fileObject); Irp = RIoAllocateIrp(DeviceObject->StackSize, TRUE); if (Irp == NULL) { ObDereferenceObject(fileObject); return FALSE; } RKeInitializeEvent(&event, SynchronizationEvent, FALSE); memset(&FileInformation,0,0x28); FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL; Irp->AssociatedIrp.SystemBuffer = &FileInformation; Irp->UserEvent = &event; Irp->UserIosb = &ioStatus; Irp->Tail.Overlay.OriginalFileObject = fileObject; Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); Irp->RequestorMode = KernelMode; irpSp = IoGetNextIrpStackLocation(Irp); irpSp->MajorFunction = IRP_MJ_SET_INFORMATION; irpSp->DeviceObject = DeviceObject; irpSp->FileObject = fileObject; irpSp->Parameters.SetFile.Length = sizeof(FILE_BASIC_INFORMATION); irpSp->Parameters.SetFile.FileInformationClass = FileBasicInformation; irpSp->Parameters.SetFile.FileObject = fileObject; IoSetCompletionRoutine( Irp, SkillSetFileCompletion, &event, TRUE, TRUE, TRUE); RIoCallDriver(DeviceObject, Irp); RKeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL); ObDereferenceObject(fileObject); return TRUE; }
/* * @implemented */ NTSTATUS NTAPI NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL, IN NTSTATUS ExitStatus) { NTSTATUS Status; PEPROCESS Process, CurrentProcess = PsGetCurrentProcess(); PETHREAD Thread, CurrentThread = PsGetCurrentThread(); BOOLEAN KillByHandle; PAGED_CODE(); PSTRACE(PS_KILL_DEBUG, "ProcessHandle: %p ExitStatus: %d\n", ProcessHandle, ExitStatus); /* Were we passed a process handle? */ if (ProcessHandle) { /* Yes we were, use it */ KillByHandle = TRUE; } else { /* We weren't... we assume this is suicide */ KillByHandle = FALSE; ProcessHandle = NtCurrentProcess(); } /* Get the Process Object */ Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_TERMINATE, PsProcessType, KeGetPreviousMode(), (PVOID*)&Process, NULL); if (!NT_SUCCESS(Status)) return(Status); /* Check if this is a Critical Process, and Bugcheck */ if (Process->BreakOnTermination) { /* Break to debugger */ PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n", Process, Process->ImageFileName); } /* Lock the Process */ if (!ExAcquireRundownProtection(&Process->RundownProtect)) { /* Failed to lock, fail */ ObDereferenceObject(Process); return STATUS_PROCESS_IS_TERMINATING; } /* Set the delete flag, unless the process is comitting suicide */ if (KillByHandle) PspSetProcessFlag(Process, PSF_PROCESS_DELETE_BIT); /* Get the first thread */ Status = STATUS_NOTHING_TO_TERMINATE; Thread = PsGetNextProcessThread(Process, NULL); if (Thread) { /* We know we have at least a thread */ Status = STATUS_SUCCESS; /* Loop and kill the others */ do { /* Ensure it's not ours*/ if (Thread != CurrentThread) { /* Kill it */ PspTerminateThreadByPointer(Thread, ExitStatus, FALSE); } /* Move to the next thread */ Thread = PsGetNextProcessThread(Process, Thread); } while (Thread); } /* Unlock the process */ ExReleaseRundownProtection(&Process->RundownProtect); /* Check if we are killing ourselves */ if (Process == CurrentProcess) { /* Also make sure the caller gave us our handle */ if (KillByHandle) { /* Dereference the process */ ObDereferenceObject(Process); /* Terminate ourselves */ PspTerminateThreadByPointer(CurrentThread, ExitStatus, TRUE); } } else if (ExitStatus == DBG_TERMINATE_PROCESS) { /* Disable debugging on this process */ DbgkClearProcessDebugObject(Process, NULL); } /* Check if there was nothing to terminate, or if we have a Debug Port */ if ((Status == STATUS_NOTHING_TO_TERMINATE) || ((Process->DebugPort) && (KillByHandle))) { /* Clear the handle table */ ObClearProcessHandleTable(Process); /* Return status now */ Status = STATUS_SUCCESS; } /* Decrease the reference count we added */ ObDereferenceObject(Process); /* Return status */ return Status; }
NTSTATUS NTAPI PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState, POWER_ACTION PowerAction) { PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT Fdo; NTSTATUS Status; DEVICETREE_TRAVERSE_CONTEXT Context; POWER_STATE_TRAVERSE_CONTEXT PowerContext; Status = IopGetSystemPowerDeviceObject(&DeviceObject); if (!NT_SUCCESS(Status)) { DPRINT1("No system power driver available\n"); Fdo = NULL; } else { Fdo = IoGetAttachedDeviceReference(DeviceObject); if (Fdo == DeviceObject) { DPRINT("An FDO was not attached\n"); return STATUS_UNSUCCESSFUL; } } /* Set up context */ PowerContext.PowerAction = PowerAction; PowerContext.SystemPowerState = PowerState; PowerContext.PowerDevice = Fdo; /* Query for system power change */ IopInitDeviceTreeTraverseContext(&Context, IopRootDeviceNode, PopQuerySystemPowerStateTraverse, &PowerContext); Status = IopTraverseDeviceTree(&Context); if (!NT_SUCCESS(Status)) { DPRINT1("Query system power state failed; changing state anyway\n"); } /* Set system power change */ IopInitDeviceTreeTraverseContext(&Context, IopRootDeviceNode, PopSetSystemPowerStateTraverse, &PowerContext); IopTraverseDeviceTree(&Context); if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED; if (Fdo != NULL) { if (PowerAction != PowerActionShutdownReset) PopSendSetSystemPowerState(Fdo, PowerState, PowerAction); ObDereferenceObject(Fdo); } return Status; }