// 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 targetted

  // at a device lower in the stack.

  IoSkipCurrentIrpStacktocation(Irp);

  status = IoCallDriver(dx->NextStackDevice, Irp);

  break;

 default:

  DebugPrint('Wdm3SystemControl bad disposition %d',disposition);

  // ASSERT(FALSE);

 }

 return status;

}

At a minimum, you should write QueryWmiRegInfo, QueryWmiDataBlock, SetWmiDataBlock, and SetWmiDataItem callbacks. Even though the last two callbacks are optional, it is best to implement them to ensure that WmiCompleteRequest is called with an appropriate error code.

QueryWmiRegInfo Handler

The Wdm3 QueryWmiRegInfo callback routine shown in Listing 12.5 provides further information about the WMI blocks you are registering, in addition to the GuidList provided in your WMILIB_CONTEXT.

Return your MOF resource name and your registry path.

If you are writing a WDM driver, you will usually set the WMIREG_FLAG_INSTANCE_PD0 flag and pass the device's PDO. See the DDK documentation for details of other flags that you can set.

Listing 12.5 QueryWmiRegInfo routine

#define MofResourceNameText L'MofResource'

NTSTATUS QueryWmiRegInfo(IN PDEVICE_OBJECT fdo, OUT PULONG PRegFlags, OUT PUNICODE_STRING PInstanceName, OUT PUNICODE_STRING *PRegistryPath, OUT PUNICODE_STRING MofResourceName, OUT PDEVICE_OBJECT *Pdo) {

 DebugPrintMsg('QueryWmiRegInfo');

 PWDM3_DEVICE_EXTENSION dx = (PWDM3_DEVICE_EXTENSION)fdo->DeviceExtension;

 *PRegFlags = WMIREG_FLAG_INSTANCE_PDO;

 *PRegistryPath = &Wdm3RegistryPath;

 RtlInitUnicodeString( MofResourceName, MofResourceNameText);

 *Pdo = dx->pdo;

 return STATUS_SUCCESS;

}

QueryWmiDataBlock Handler

A QueryWmiDataBlock callback routine returns one or more instances of a data block. When finished, it should call WmiCompleteRequest. A driver can return STATUS_PENDING if the IRP cannot be completed immediately.

QueryWmiDataBlock is passed GuidIndex, the relevant index into your GuidList array, the InstanceIndex, and the InstanceCount required. You have to fill the Buffer (that has a maximum size of BufferAvail). Fill in InstanceLengthArray, an array of ULONGs giving the length of each instance.

In the buffer, each instance's data should be aligned on an 8-byte boundary. The actual data should correspond to the class MOF definition. A MOF string should be returned as a counted Unicode, MOF Boolean returned as a BOOLEAN, MOF uint32 returned as a ULONG, MOF uint64 as a ULONGLONG, etc.

Listing 12.6 shows how the Wdm3 QueryWmiDataBlock routine handles requests for the Wdm3Information and MSPower_DeviceEnable WMI data blocks. For Wdm3Information, QueryWmiDataBlock first works out the size of buffer required and checks that the given output buffer is large enough. It then stores the BufferLen, BufferFirstWord, and SymbolicLinkName property values. The SymbolicLinkName string is stored in counted Unicode (i.e., a USHORT count followed by the wide char characters). Finally, the number of bytes set is stored. Only one instance of a Wdm3Information data block is ever processed, so this size is stored in the first ULONG pointed to by InstanceLengthArray.

QueryWmiDataBlock handles a MSPower_DeviceEnable WMI data block request in a similar way.

Listing 12.6 QueryWmiDataBlock routine

NTSTATUS QueryWmiDataBlock(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN ULONG GuidIndex, IN ULONG InstanceIndex, IN ULONG InstanceCount, IN OUT PULONG InstanceLengthArray, IN ULONG OutBufferSize, OUT PUCHAR PBuffer) {

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

  'InstanceCount %d, OutBufferSize %d',

  GuidIndex,InstanceIndex, InstanceCount, OutBufferSize);

 PWDM3_DEVICE_EXTENSI0N dx = (PWDK3_DEVICE_EXTENSION)fdo->DeviceExtension;

 NTSTATUS status;

 ULONG size =0;

 switch( GuidIndex) {

 case WDM3_WMI_GUID_INDEX: // Wdm3Information

  {

   ULONG SymLinkNameLen = dx->ifSymLinkName.Length;

   size = sizeof(ULONG)+sizeof(ULONG)+SymLinkNameLen+sizeof(USHORT);

   // Check output buffer size

   if (OutBufferSize<size) {

    status = STATUS_BUFFER_TOO_SMALL;

    break;

   }

   // Store uint32 BufferLen

   *(ULONG *)PBuffer = BufferSize;

   PBuffer +-= sizeof (ULONG);

   // Store uint32 BufferFirstWord

   ULONG FirstWord = 0;

   if (Buffer!=NULL && BufferSize>=4) FirstWord = *(ULONG*)Buffer;

   *(ULONG *)PBuffer = FirstWord;

   PBuffer += sizeof(ULONG);

   // Store string SymbolicLinkName as counted Unicode

   *(USHORT *)PBuffer = (USHORT)SymLinkNameLen;

   PBuffer += sizeof(USHORT);

   RtlCopyMemory(PBuffer, dx->ifSymLinkName.Buffer, SymLinkNameLen);

   // Store total size

   *InstanceLengthArray = size;

   status = STATUS_SUCCESS;

   break;

  }

 case GUID_POWER_DEVICE_ENABLE_INDEX: // MSPower_DeviceEnable

  {

   size = sizeof(BOOLEAN);

   // Check output buffer size

   if (OutBufferSize<size) {

    status = STATUS_BUFFER_TOO_SMALL;

    break;

   }

   // Store boolean IdlePowerDownEnable in Enable property

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

   // Store total size

   *InstanceLengthArray = size;

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

0

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

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