NTSTATUS NdasPortFdoDispatchSystemControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS status; PNDASPORT_FDO_EXTENSION FdoExtension; SYSCTL_IRP_DISPOSITION disposition; PIO_STACK_LOCATION irpStack; ULONG isRemoved; FdoExtension = (PNDASPORT_FDO_EXTENSION) DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation(Irp); isRemoved = NpAcquireRemoveLock(FdoExtension->CommonExtension, Irp); if (isRemoved) { return NpReleaseRemoveLockAndCompleteIrp( FdoExtension->CommonExtension, Irp, STATUS_NO_SUCH_DEVICE); } #ifdef RUN_WPP #ifdef WPP_TRACE_W2K_COMPATABILITY // // One of the mythical things that people tell you that // you need to do to get WPP tracing to work on Windows // 2000 is to call the WPP_SYSTEMCONTROL macro in your // DriverEntry entry point. The problem with this is that // what is does is actually trash your IRP_MJ_SYSTEM_CONTROL // entry point, meaning that you can no longer expose your // driver through WMI. What we will do to get around this // is to incorporate a call to the function that the WPP // IRP_MJ_SYSTEM_CONTROL handler calls in order to handle // WPP data. By doing this, we can satisfy WPP while // also supporting our own WMI data. // // You can find the code for the WPP SYSTEM_CONTROL // handler (WPPSystemControlDispatch) in the km-init.tpl // file located in the DDK's bin\wppconfig directory. // if (DeviceObject == (PDEVICE_OBJECT)irpStack->Parameters.WMI.ProviderId) { // // If this is a REG_INFO request and we have not registered // with WMI yet, we must zero the buffer. The reason for this // is that the WPP code will just blindly use it without // verifying any of the members of the structure. We learned // this trick from the WPPSystemControl handler code in // km-init.tpl // if (irpStack->MinorFunction == IRP_MN_REGINFO && !FdoExtension->IsWmiRegistered) { RtlZeroMemory( irpStack->Parameters.WMI.Buffer, irpStack->Parameters.WMI.BufferSize); } // // Yet another nice thing about trying to get tracing and WMI // support working is that we can NOT allow an IRP_MN_REGINFO_EX // request to get to the WMI library, we must do the registering // of WMI through an IRP_MN_REGINFO request. // // Why? Because the W2K tracing code has no idea what an // IRP_MN_REGINFO_EX is, so it will refuse to setup the // parts necessary for WPP tracing support. So, if // we see an IRP_MN_REGINFO_EX request come in and we're // built for Windows 2000, that means that we need to // reject it to force the code to send us an IRP_MN_REGINFO // request instead. // // IRP_MN_REGINFO_EX isn't defined for Windows 2000, so we use // its constant value of 0xb here. // if (IRP_MN_REGINFO_EX == irpStack->MinorFunction) { // // Fail the request // return NpReleaseRemoveLockAndCompleteIrpEx( FdoExtension->CommonExtension, Irp, STATUS_INVALID_DEVICE_REQUEST, 0, IO_NO_INCREMENT); } } #endif // W2K #endif //RUN_WPP // // Call WMILIB to process the request. // status = WmiSystemControl( &FdoExtension->WmiLibInfo, DeviceObject, Irp, &disposition); // // Check the disposition of the request, so that we can determine // what to do. // switch(disposition) { case IrpProcessed: { // // This IRP has been processed and may be completed or pending. // // // DispatchWmiXXXX routine is responsible to hold the remove lock. // WmiRoutine or our DispatchWmiXXX may later complete the IRP. // We just release our remove lock here. // NpReleaseRemoveLock( FdoExtension->CommonExtension, Irp); return status; } case IrpNotCompleted: { NTSTATUS wppStatus = STATUS_SUCCESS; #ifdef RUN_WPP #ifdef WPP_TRACE_W2K_COMPATABILITY ULONG bytesReturned; // // If the WMILIB didn't complete the IRP, then let's // see if WPP will. // KdPrint(("NDASPORT.SYS: WPP_TRACE_CONTROL (MN=%X)\n", irpStack->MinorFunction)); wppStatus = WPP_TRACE_CONTROL( irpStack->MinorFunction, irpStack->Parameters.WMI.Buffer, irpStack->Parameters.WMI.BufferSize, bytesReturned); if (!NT_SUCCESS(status) && NT_SUCCESS(wppStatus)) { // // WMILIB failed the IRP, but WPP completed it // with success. Therefore, we'll change the IRP's // status and bytes returned count to what WPP // would like them to be. // Irp->IoStatus.Status = wppStatus; Irp->IoStatus.Information = bytesReturned; status = wppStatus; } #endif // W2K #endif //RUN_WPP // // This IRP has not been completed, but has been fully processed. // we will complete it now. // return NpReleaseRemoveLockAndCompleteIrp( FdoExtension->CommonExtension, Irp, wppStatus); } case IrpForward: case IrpNotWmi: { // // This IRP is either not a WMI IRP or is a WMI IRP targeted // at a device lower in the stack. return NpReleaseRemoveLockAndForwardIrp( FdoExtension->CommonExtension, Irp); } default: { // // We really should never get here, but if we do just forward.... // ASSERTMSG("Unkown SYSCTL_IRP_DISPOSITION from WmiSystemControl", FALSE); return NpReleaseRemoveLockAndForwardIrp( FdoExtension->CommonExtension, Irp); } } }
NTSTATUS PciDrvSystemControl ( PDEVICE_OBJECT DeviceObject, PIRP Irp ) /*++ Routine Description We have just received a System Control IRP. Assume that this is a WMI IRP and call into the WMI system library and let it handle this IRP for us. --*/ { PFDO_DATA fdoData; SYSCTL_IRP_DISPOSITION disposition; NTSTATUS status; PIO_STACK_LOCATION stack; PAGED_CODE(); stack = IoGetCurrentIrpStackLocation (Irp); DebugPrint(TRACE, DBG_WMI, "FDO %s\n", WMIMinorFunctionString(stack->MinorFunction)); fdoData = (PFDO_DATA) DeviceObject->DeviceExtension; PciDrvPowerUpDevice(fdoData, TRUE); PciDrvIoIncrement (fdoData); if (fdoData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE; IoCompleteRequest (Irp, IO_NO_INCREMENT); PciDrvIoDecrement (fdoData); return status; } status = WmiSystemControl(&fdoData->WmiLibInfo, DeviceObject, Irp, &disposition); // // Following code is required if we want to do tracing in WIN2K. // Tracing is enabled or disabled explicitly by sending WMI // control events on Win2K. // #if defined(WIN2K) && defined(EVENT_TRACING) if (disposition != IrpProcessed && DeviceObject == (PDEVICE_OBJECT)stack->Parameters.WMI.ProviderId) { ULONG returnSize = 0; DebugPrint(INFO, DBG_WMI, "Calling WPP_TRACE_CONTROL\n"); WPP_TRACE_CONTROL(stack->MinorFunction, stack->Parameters.WMI.Buffer, stack->Parameters.WMI.BufferSize, returnSize); } #endif switch(disposition) { case IrpProcessed: { // // This irp has been processed and may be completed or pending. break; } case IrpNotCompleted: { // // This irp has not been completed, but has been fully processed. // we will complete it now IoCompleteRequest(Irp, IO_NO_INCREMENT); break; } case IrpForward: case IrpNotWmi: { // // This irp is either not a WMI irp or is a WMI irp targeted // at a device lower in the stack. IoSkipCurrentIrpStackLocation (Irp); status = IoCallDriver (fdoData->NextLowerDriver, Irp); break; } default: { // // We really should never get here, but if we do just forward.... ASSERT(FALSE); IoSkipCurrentIrpStackLocation (Irp); status = IoCallDriver (fdoData->NextLowerDriver, Irp); break; } } PciDrvIoDecrement(fdoData); return(status); }