How do I list all of the Adapters?

I would like to use WMI to list all of the Ethernet card adapters on my computer and then query them.

I have been looking for some sample code. Alas, I have found none.

I can see how I could use IoWMIOpenBlock with the appropriate GUID as first parameter.

But how do I then get all of the instances names? I have to know these instances names, unless I’m mistaken… (see IoWMIQuerySingleInstance or IoWMIQuerySingleInstanceMultiple).

Thank you for any help,

Patrick

Regards
Deepak

On Mon, Nov 22, 2010 at 6:52 AM, wrote:

> I would like to use WMI to list all of the Ethernet card adapters on my
> computer and then query them.
>
> I have been looking for some sample code. Alas, I have found none.
>

src\network\config\bindview

thought not based on WMI I think but still if task is to enumerate then it
can be used.

>
>
>
>
>
> —
> 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
>

Obviously the preferred way to do it is in usermode (and with a nice dynamic language like Powershell). But if you must enumerate all network adapters from kernelmode, it can still be done. It’s just a little more complicated than you’d think :slight_smile:

I’m going to use the example of querying MSNdis_EthernetCurrentAddress, since that’s a continuation of my previous WMI example. But if you are interested in getting *all* miniports, you shouldn’t use that WMI class, since it only shows normal Ethernet-like adapters (unsurprisingly). Instead, you can use MSNdis_EnumerateAdapter to see all the CoNDIS adapters and whatnot.

// The results of a WNODE_ALL_DATA contain the instance name packed
// using a structure like this. No structure definition is available
// from the headers, however, so we’ll define our own to make the
// instance name easier to work with.
typedef struct _COUNTED_STRING
{
USHORT Length;

__field_bcount(Length)
WCHAR String[ANYSIZE_ARRAY];
} COUNTED_STRING, *PCOUNTED_STRING;

//
// Enumerates all Ethernet-like adapters via MSNdis_EthernetCurrentAddress.
// For each adapter, this routine calls “kmwmiAddMacAddress”, which is a
// fictional callback for your code.
//
__drv_requiresIRQL(PASSIVE_LEVEL)
NTSTATUS
kmwmiQueryAllMacAddresses()
{
NTSTATUS NtStatus;
PVOID WmiDataBlock = NULL;
ULONG WmiBufferSize = 0;
PUCHAR WNodeAllocation = NULL;
PWNODE_ALL_DATA WNode = NULL;
PCUCHAR EndOfBuffer;

// Get the MSNdis_EthernetCurrentAddress block
NtStatus = IoWMIOpenBlock(
&MSNdis_EthernetCurrentAddress_GUID,
WMIGUID_QUERY,
&WmiDataBlock);
if (STATUS_SUCCESS != NtStatus)
{
WmiDataBlock = NULL;
goto Cleanup;
}

// Query all instances of the MSNdis_EthernetCurrentAddress class
WmiBufferSize = 0;
NtStatus = IoWMIQueryAllData(
WmiDataBlock,
&WmiBufferSize,
&WNodeAllocation);
if (STATUS_BUFFER_TOO_SMALL != NtStatus)
{
goto Cleanup;
}

// Allocate enough space for the WNODE and requery.
WNodeAllocation = ExAllocatePoolWithTag(NonPagedPool, WmiBufferSize, ‘imwk’);
if (!WNodeAllocation)
{
goto Cleanup;
}

// For debugging, we keep a pointer to the last byte after the
// end of the buffer – that way we don’t accidentally fall off.
EndOfBuffer = WNodeAllocation + WmiBufferSize;

// Now actually get data
NtStatus = IoWMIQueryAllData(
WmiDataBlock,
&WmiBufferSize,
WNodeAllocation);
if (STATUS_SUCCESS != NtStatus)
{
goto Cleanup;
}

WNode = (PWNODE_ALL_DATA)WNodeAllocation;

// Grab the first WNODE_ALL_DATA and dump its contents
kmwmiProcessWNode(WNode, EndOfBuffer);

// Now grab any chained WNODE_ALL_DATA objects too
while (WNode->WnodeHeader.Linkage)
{
WNode = (PWNODE_ALL_DATA)((PUCHAR)WNode + WNode->WnodeHeader.Linkage);
kmwmiProcessWNode(WNode, EndOfBuffer);
}

Cleanup:

if (WmiDataBlock)
{
ObDereferenceObject(WmiDataBlock);
}

if (WNodeAllocation)
{
ExFreePool(WNodeAllocation);
}

return NtStatus;
}

__drv_requiresIRQL(PASSIVE_LEVEL)
VOID
kmwmiProcessWNode(
__in PWNODE_ALL_DATA WNode,
__in PCUCHAR EndOfBuffer
)
{
ULONG i;
PULONG InstanceNameOffsetArray;

UNREFERENCED_PARAMETER(EndOfBuffer); // For asserts only

// The WNODE contains an array of ULONGs, each giving the offset
// to the i-th InstanceName string.
InstanceNameOffsetArray = (PULONG)((PUCHAR)WNode + WNode->OffsetInstanceNameOffsets);

// Now for each instance in this WNODE…
for (i = 0; i < WNode->InstanceCount; i++)
{
ULONG InstanceNameOffset = InstanceNameOffsetArray[i];
PCOUNTED_STRING InstanceName = (PCOUNTED_STRING)((PUCHAR)WNode + InstanceNameOffset);
UNICODE_STRING IfDescription;
ULONG DataOffset;
ULONG DataLength;
ULONG MacAddressLength;
PMSNdis_EthernetCurrentAddress CurrentAddress;

// For many MSNdis_* classes, the network interface’s ifDescription is
// used as the WMI class’s InstanceName. Format it as a UNICODE_STRING,
// since that’s easier to work with.
ASSERT((PUCHAR)InstanceName < EndOfBuffer);
ASSERT((PUCHAR)InstanceName->String + InstanceName->Length < EndOfBuffer);
IfDescription.Buffer = InstanceName->String;
IfDescription.Length = InstanceName->Length;
IfDescription.MaximumLength = InstanceName->Length;

// There are two kinds of WMI classes: those with a fixed size
// and those with dynamic sizes. Fixed sizes are easier to work
// with. Our specific case of MSNdis_EthernetCurrentAddress is
// a fixed-sized class, but we’ll show how to use both here.
if (WNode->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE)
{
DataOffset = WNode->DataBlockOffset + i * WNode->FixedInstanceSize;
DataLength = WNode->FixedInstanceSize;
}
else
{
POFFSETINSTANCEDATAANDLENGTH VariableDataLength;

VariableDataLength = &WNode->OffsetInstanceDataAndLength[i];
DataOffset = VariableDataLength->OffsetInstanceData;
DataLength = VariableDataLength->LengthInstanceData;
}

// Now we know where the data is located. Cast it to the class-
// specific datatype.
ASSERT((PUCHAR)WNode + DataOffset < EndOfBuffer);
ASSERT((PUCHAR)WNode + DataOffset + DataLength < EndOfBuffer);
CurrentAddress = (PMSNdis_EthernetCurrentAddress)((PUCHAR)WNode + DataOffset);

// Note that for the specific case of MSNdis_EthernetCurrentAddress, we
// know DataLength == 6 == ETH_LENGTH_OF_ADDRESS == MSNdis_NetworkAddress_SIZE.
// But we calculated it anyway to show how it’s done for other, more
// dynamic classes.
MacAddressLength = DataLength;
ASSERT(MacAddressLength == 6);

// Finally we are done. We have the interface name and its MAC address.
// Let’s pass them to a fictional function so that it looks like all
// this effort was good for something.
kmwmiAddMacAddress(
&IfDescription,
CurrentAddress->NdisCurrentAddress.Address,
MacAddressLength);
}
}

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@hapax.qc.ca
Sent: Sunday, November 21, 2010 5:23 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] How do I list all of the Adapters?

I would like to use WMI to list all of the Ethernet card adapters on my computer and then query them.

I have been looking for some sample code. Alas, I have found none.

I can see how I could use IoWMIOpenBlock with the appropriate GUID as first parameter.

But how do I then get all of the instances names? I have to know these instances names, unless I’m mistaken… (see IoWMIQuerySingleInstance or IoWMIQuerySingleInstanceMultiple).

Thank you for any help,

Patrick


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

Great help Jeffrey. Thanks, let me digest this.