status = STATUS_SUCCESS;

   break;

  }

 default:

  DebugPrintMsg('QueryWmiDataBlock: Bad GUID index');

  status = STATUS_WMI_GUID_NOT_FOUND;

  break;

 }

 return WmiCompleteRequest(fdo, Irp, status, size, IO_NO_INCREMENT);

}

SetWmiDataBlock Handler

The Wdm3 SetWmiDataBlock routine shown in Listing 12.7 lets a user change the device extension IdlePowerDownEnable settings. If the MSPower_DeviceEnable GUID index is given and the input buffer size is large enough, the BOOLEAN at the start of Pbuffer is stored in IdlePowerDownEnable.

SetWmiDataBlock then acts on the new power down enable setting. If powering down is now enabled, PoRegisterDeviceForIdleDetection is called, if necessary. If now disabled, PoRegisterDeviceForIdleDetection is called to turn off idle detection; if the Wdm3 device is powered down, SendDeviceSetPower is called to power the device up.

Listing 12.7 SetWmiDataBlock routine

NTSTATUS SetWmiDataBlock(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG InstanceIndex, IN ULONG BufferSize, IN PUCHAR PBuffer) {

 DebugPrint('SetWmiDataBlock: GuidIndex %d, InstanceIndex %d, BufferSize %d',

  GuidIndex,Instancelndex,BufferSize);

 PWDM3_DEVICE_EXTENSION dx = (PWDM3_DEVICE_EXTENSION)fdo->DeviceExterision;

 if (GuidIndex==GUID_POWER_DEVICE_ENABLE_INDEX) // MSPower_DeviceEnable

 {

  if (BufferSize<sizeof(BOOLEAN))

   return WmiCompleteRequest(fdo, Irp, STATUS_BUFFER_TOO_SMALL, 0, IO_NO_INCREMENT);

  // Get Enable property into IdlePowerDownEnable

  dx->IdlePowerDownEnable = *(BOOLEAN*)PBuffer;

  // Action IdlePowerDownEnable

  if (dx->IdlePowerDownEnable) {

   DebugPrintMsg('SetWmiDataBlock: Enabling power down');

   // Enable power down idling

   if (dx->PowerIdleCounter==NULL) dx->PowerIdleCounter = PoRegisterDeviceForIdleDetection(dx->pdo, 30, 60, PowerDeviceD3);

  } else {

   DebugPrintMsg('SetWmiDataBlock: Disabling power down');

   // Disable power down idling

   if (dx->PowerIdleCounter!=NULL) dx->PowerIdleCounter = PoRegisterDeviceForIdleDetection(dx->pdo, 0, 0, PowerDeviceD3);

   if (dx->PowerState>PowerDeviceD0) {

    DebugPrintMsg('SetWmiDataBlock: Disabling power down: power up');

    SendDeviceSetPower(dx, PowerDeviceD0);

   }

  }

  return WmiCompleteRequest( fdo, Irp, STATUS_SUCCESS, 0, IO_NO_INCREMENT);

 }

 return FailWMIRequest(fdo, Irp, GuidIndex);

}

SetWmiDataItem Handler

A SetWmiDataItem callback handles the setting of one data item in an instance. This routine is not called in Wdm3. Listing 12.8 shows how SetWmiDataItem calls FailWMIRequest to reject the WMI IRP. FailWMIRequest fails the IRP with STATUS_WMI_GUID_NOT_FOUND if an invalid GUID was given, or STATUS_INVALID_DEVICE_REQUEST otherwise.

Listing 12.8 SetWmiDataItem routine

NTSTATUS SetWmiDataItem(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG InstanceIndex, IN ULONG DataltemId, IN ULONG BufferSize, IN PUCHAR PBuffer) {

 DebugPrint('SetWmiDataItem: GuidIndex %d, InstanceIndex %d, DataItemId %d, BufferSize %d',

  GuidIndex.InstanceIndex, DataItemId, BufferSize);

 return FailWMIRequest(fdo, Irp, GuidIndex);

}

NTSTATUS FailWMIRequest(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN ULONG GuidIndex) {

 DebugPrint('FailWMIRequest: GuidIndex %d',GuidIndex);

 NTSTATUS status;

 if (GuidIndex<0 || GuidIndex>=GUID_COUNT) status = STATUS_WMI_GUID_NOT_FOUND;

 else status = STATUS_INVALID_DEVICE_REQUEST;

 status = WmiCompleteRequest(fdo, Irp, status, 0, IO_NO_INCREMENT);

 return status;

}

ExecuteWmiMethod Handler

Listing 12.9 shows how I think the optional ExecuteWmiMethod routine should be implemented. As I stated earlier, I could not get mofcomp to compile the PowerDown method in the Wdm3Information WMI data block. Therefore, I have not so far been able to test this method.

Listing 12.9 ExecuteWmiMethod routine

NTSTATUS ExecuteWmiMethod(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG InstanceIndex, IN ULONG MethodId, IN ULONG InBufferSize, IN ULONG OutBufferSize, IN OUT PUCHAR Buffer) {

 DebugPrint('ExecuteWmiMethod: GuidIndex %d, InstanceIndex %d, '

  'MethodId %d, InBufferSize %d OutBufferSize %d',

  GuidIndex, InstanceIndex, MethodId, InBufferSize, OutBufferSize);

 PWOM3_DEVICE_EXTENSION dx = (PWDM3_DEVICE_EXTENSION)fdo->DeviceExtension;

 if (GuidIndex==WDM3_WMI_GUID_INDEX && MethodId==0) {

  DebugPrintMsg('ExecuteWmiMethod: PowerDown method');

  // Power Down

  if (dx->PowerState<PowerDeviceD3) SendDeviceSetPower(dx, PowerDeviceD3);

  return WmiCompleteRequest(fdo, Irp, STATUS_SUCCESS, 0, IO_NO_INCREMENT);

 }

 return FailWMIRequest(fdo, Irp, GuidIndex);

}

Firing WMI Events

To fire a WMI event, simply call WmiFireEvent, passing the relevant WMI event block GUID, the InstanceIndex, and any event data. WmiFireEvent makes the appropriate call to IoWmiWriteEvent.

The Wdm3 driver provides a helper function Wdm3FireEvent, shown in Listing 12.10. This takes a NULL-terminated wide string, formats it into a Wdm3Event message, and calls WmiFireEvent.

A user application must ask for events first by setting an Enable flag. This request arrives at the driver in its WmiFunctionControl optional callback routine. If the Function parameter is WmiEventControl, the new Enable setting is stored in the WMIEventEnabled flag in the device extension. WmiFunctionControl is also called to ask a driver to collect WMI data blocks that were marked as being expensive to collect.

The WMIEventEnabled flag is initially FALSE, which means that no events are generated. As I have found no way of registering for events, the Wdm3FireEvent and WmiFunctionControl functions have not been tested.

Listing 12.10 Wdm3FireEvent and WmiFunctionControl routines

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×