Regd: WDM NDIS620 Miniport driver as WMI data and method provider

Hi Folks,

I need to make a WDM miniport driver(NDIS620_MINIPORT) as a WMI data and
method provider. OID_GEN_SUPPORTED_GUIDS requires a NDIS_GUID array to map
the custom OID to GUID.
How should be the NDIS_GUID structure populated for a sample mof of say:*

MOF content*:
#pragma autorecover
#pragma namespace (“\\.\root\wmi”)
[Dynamic, Provider(“WMIProv”),
WMI,
Description(“Sample WMI provider”),
guid(“{XXYYYYXX-AAAA-BBBB-CCCC-DDEEFFGGHHI}”),
locale(“MS\0x409”)]
class sample
{
[key,read]
string InstanceName;
[read] boolean Active;

[WmiDataId(1),
read, write,
DisplayName(“Input”) : amended,
Description(“Input Element”) : amended]
uint32 input;

[WmiDataId(2),
read, write,
DisplayName(“Output”) : amended,
Description(“Output Element”) : amended]
uint32 output;

[Implemented,
Description(“sample method”) : amended,
WmiMethodId(1)]
void sample_method([in] uint32 input, [out] uint32 output);
};

How should be the size and flags parameter of NDIS_GUID be set specifically?
is fNDIS_GUID_METHOD allowed to be used? I dont see any reference in WDK for
this flag usage but it is there in ntddndis.h.
I use WMI tools for the client on Windows Server 2008 R2 OS.

Thanks,
G.Subbiah.

You have a lot going on in that one class :). I don’t think that NDIS supports a WMI class that has both a method and data; you’d need to create a separate class for the data and another class for the method.

So let’s ignore the method and I’ll show how to implement an OID for the data.

You first invent your own private OID:

#define OID_MY_SAMPLE_REQUEST 0xFF731401 // Custom OIDs must begin with 0xFF.

Next, declare a C-language version of the WMI class:

typedef struct _MY_SAMPLE_DATA
{
UINT32 Input;
UINT32 Output;
} MY_SAMPLE_DATA;

Finally, set up the mapping between the WMI class and the OID:

NDIS_GUID MyWmiClass = { 0 };
MyWmiClass.Guid = {XXYYYYXX-AAAA-BBBB-CCCC-DDEEFFGGHHI}; // From the MOF
MyWmiClass.Oid = OID_MY_SAMPLE_OID;
MyWmiClass.Size = sizeof(MY_SAMPLE_DATA);
MyWmiClass.Flags = fNDIS_GUID_TO_OID;

Now when you register this GUID, you’ll get NdisRequestQueryInformation and NdisRequestSetInformation requests, with the InformationBuffer pointing to a MY_SAMPLE_DATA.

Ok, so what about the WMI method? Let’s throw away the above, and pretend your WMI class only has a method on it (although InstanceName and Active are still included; you get those for free).

Again you start with defining a private OID:

#define OID_MY_SAMPLE_METHOD 0xFF731402 // Custom OIDs must begin with 0xFF

You don’t need to set up any datastructures, so you can jump right into the NDIS_GUID:

NDIS_GUID MyWmiMethod = { 0 };
MyWmiMethod.Guid = {XXYYYYXZ-AAAA-BBBB-CCCC-DDEEFFGGHHI}; // From the MOF
MyWmiMethod.Oid = OID_MY_SAMPLE_METHOD;
MyWmiMethod.Size = (ULONG)-1; // Ignored for methods
MyWmiMethod.Flags = fNDIS_GUID_METHOD;

Now in your MiniportOidRequest handler, you’ll get method requests. Since they’re a little uncommon, I’ll illustrate one here:

NDIS_STATUS
MyMiniportOidRequest(NDIS_HANDLE Adapter, PNDIS_OID_REQUEST OidRequest)
{
switch (OidRequest->RequestType)
{
case NdisRequestMethod:
switch (OidRequest->DATA.METHOD_INFORMATION.Oid)
{
case OID_MY_SAMPLE_METHOD:
switch (Request->DATA.METHOD_INFORMATION.MethodId)
{
case 0: // First (and only) method in the class
return MySampleMethod(OidRequest);
}
}
}
return NDIS_STATUS_INVALID_OID;
}

NDIS_STATUS
MySampleMethod(PNDIS_OID_REQUEST OidRequest)
{
ULONG Input;
PULONG pOutput;

if (OidRequest->DATA.METHOD_INFORMATION.InputBufferLength != sizeof(ULONG)
|| OidRequest->DATA.METHOD_INFORMATION.OutputBufferLength != sizeof(ULONG))
{
return NDIS_STATUS_INVALID_DATA;
}

Input = *(PULONG UNALIGNED)OidRequest->DATA.METHOD_INFORMATION.InformationBuffer;
pOutput = (PULONG UNALIGNED)OidRequest->DATA.METHOD_INFORMATION.InformationBuffer;

*pOutput = /* something */;

return NDIS_STATUS_SUCCESS;
}

A few notes:

  • When inventing new OIDs, try to stick to this format of 0xFFXXXXYY, where XXXX is a “pick a random number and hope it’s mostly unique in the world” value used across your driver, and YY is a serial number for the individual OID (01, 02, 03…).

  • I didn’t show strings or arrays here (because you didn’t ask :slight_smile: ) but the idea is that you just add the relevant flag (fNDIS_GUID_UNICODE_STRING or fNDIS_GUID_ARRAY). NDIS will do less input-validation than for scalars, so make sure you validate inputs carefully.

  • Be aware that fNDIS_GUID_ALLOW_READ and fNDIS_GUID_ALLOW_WRITE are not the best way to implement access control. You should instead put a SDDL string into your INF. That’ll give you more granular control over who gets access. Here’s the doc for that: http://msdn.microsoft.com/en-us/library/ff547350(VS.85).aspx

  • Do make sure to some security testing! The MOF file does *not* limit the user from throwing arbitrary data against your WMI classes. Basically the user can bypass the MOF (either by using the C interface, or by supplying their own MOF that has your GUID in it). Ultimately, your driver is responsible for validating inputs and output buffer sizes.

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Subbiah Ganesan
Sent: Friday, September 23, 2011 1:34 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Regd: WDM NDIS620 Miniport driver as WMI data and method provider

Hi Folks,

I need to make a WDM miniport driver(NDIS620_MINIPORT) as a WMI data and method provider. OID_GEN_SUPPORTED_GUIDS requires a NDIS_GUID array to map the custom OID to GUID.
How should be the? NDIS_GUID structure populated for a sample mof of say:

MOF content:
#pragma autorecover
#pragma namespace (“\\.\root\wmi”)
[Dynamic, Provider(“WMIProv”),
?WMI,
?Description(“Sample WMI provider”),
?guid(“{XXYYYYXX-AAAA-BBBB-CCCC-DDEEFFGGHHI}”),
?locale(“MS\0x409”)]
class sample
{
??? [key,read]
??? string InstanceName;
??? [read] boolean Active;

??? [WmiDataId(1),
??? read, write,
??? DisplayName(“Input”) : amended,
??? Description(“Input Element”) : amended]
??? uint32 input;

??? [WmiDataId(2),
??? read, write,
??? DisplayName(“Output”) : amended,
??? Description(“Output Element”) : amended]
??? uint32 output;

??? [Implemented,
??? Description(“sample method”) : amended,
??? WmiMethodId(1)]
??? void sample_method([in] uint32 input, [out] uint32 output);
};

How should be the size and flags parameter of NDIS_GUID be set specifically? is fNDIS_GUID_METHOD allowed to be used? I dont see any reference in WDK for this flag usage but it is there in ntddndis.h.
I use WMI tools for the client on Windows Server 2008 R2 OS.

Thanks,
G.Subbiah.
— NTDEV is sponsored by OSR For our schedule of WDF, WDM, debugging and other seminars visit: http://www.osr.com/seminars To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer