Click here to Skip to main content
15,886,362 members
Articles / Programming Languages / C++
Article

Fix for KB article 823206

Rate me:
Please Sign up or sign in to vote.
4.34/5 (10 votes)
13 Jun 20043 min read 60.4K   539   25   3
How to solve the behaviour described in KB 823206

Introduction

With Windows 2003 Server, Microsoft changed the Plug'n'Play detection routine. If a system contains multiple network interface cards, the following symptoms can occur:

  • The NIC assigned to "Local Area Connection" is not always the first NIC. This is the same for the second NIC and "Local Area Connection 2" and so on.
  • The order returned by calling SetupDiEnumDeviceInfo() is not the same as the build in order of the NICs. This includes WMI also.
  • The friendly name of the first detected NIC (which is sometimes really the first NIC) has the postfix #2 or higher.

This article provides a solution for the problem described above. I didn't know where to publish this. So I think CodeProject is the best place.

Background

A customer reported this behaviour to Microsoft already. Check out KB article 823206.

Abstract of KB 823206:

Cause:

The order in which devices are detected is not guaranteed, and the order can change to optimize any platform or for any other reason that affects the timing. A device in a higher-numbered slot on a PCI bus can be enumerated prior to an identical device in a lower-numbered slot on the PCI bus. In the case of network adapters, the net class installer assigns the friendly name that is shown in Device Manager in the order that the devices were enumerated

Workaround:

To work around this problem, rename the Local Area Connections that are listed in Network Connections.

Nice workaround... isn't it?

Solution

Everyone expects that the NIC assigned to "Local Area Connection" is the first NIC. The second NIC is assigned to "Local Area Connection 2" and so on. Because this, the only thing we need to do is:

  • Enum all NIC devices
  • Get their bus number, device number on the bus, and function number on the device
  • Sort them using the three criteria above
  • Rename the network connection name starting from "Local Area Connection" to "Local Area Connection x"

The network connection names are stored under:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\
Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}

To each network connection, the PNP instance ID of the corresponding NIC is stored under this registry key.

How to enumerate the network devices:

SP_DEVINFO_DATA deviceInfoData;
HDEVINFO hDevInfo;

hDevInfo = SetupDiGetClassDevs(&GUID_NDIS_LAN_CLASS, NULL,
   NULL, DIGCF_DEVICEINTERFACE); 
for (i=0; SetupDiEnumDeviceInfo(hDevInfo,i,&deviceInfoData) ;i++) 
{
    //
    //
    //
}

This will enumerate all devices which are belong to the

GUID_NDIS_LAN_CLASS
class.

Next we call SetupDiGetDeviceRegistryProperty() a few times to get out the following properties:

Bus NumberThe bus number represents the ID of the BUS, where the device is connected to.
Device NumberThis is the number of the device on the BUS specified above (starting a 0).
Function NumberA NIC may contain have multiple network ports. So function number 0 is the first port, 1 the second and so on.
PDO NamePhysical Device Object Name. This value assigned through the P'n'P manager at the detection scan. By sorting this value alphabetically, we can find out the built in order of the devices. Sample string: \Device\NTPNP_PCI0014

#define MY_BUFFER_SIZE 4096

int iFunctionNumber;
int iDeviceNumber;
int iBusNumber;
CString strPdoName;

CString strPnpInstanceId;
BYTE buff[MY_BUFFER_SIZE+1];
WCHAR wBuff[MY_BUFFER_SIZE+1];
DWORD dwDataType = 0;
.
.
.


// 
// if this function fails, the device is 
// not a physical device (no address).
//
if (SetupDiGetDeviceRegistryProperty( hDevInfo, &deviceInfoData, 
  SPDRP_ADDRESS, &dwDataType, buff, MY_BUFFER_SIZE, NULL) == FALSE)
    continue;


// 
// the lower 16 bits are the function number, 
// the upper 16 bits are the device number
//
iFunctionNumber = ((int)buff[0]) + (((int)buff[1])<<0x10);
iDeviceNumber = ((int)buff[2]) + (((int)buff[3])<<0x10);


//
// Get the bus number (DWORD)
//
if (SetupDiGetDeviceRegistryProperty( hDevInfo, &deviceInfoData, 
  SPDRP_BUSNUMBER, &dwDataType, buff, MY_BUFFER_SIZE, NULL) == FALSE)
    continue;
iBusNumber = (int) *(DWORD*)buff;


//
// We need to know the pnp instance ID
//
if (SetupDiGetDeviceInstanceId( hDevInfo, &deviceInfoData, 
  wBuff, MY_BUFFER_SIZE, &dwSizeRequired) == FALSE)
    continue;
strPnpInstanceId =  wBuff;


//
// get the PDO name (optional).
// This name is assigned to the device from the Pnp manager.
// This shows also the order in which the devices are enumerated
// Sorting them using a string comparer will also show the built in order
//
if (SetupDiGetDeviceRegistryProperty( hDevInfo, &deviceInfoData, 
  SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, &dwDataType, 
  buff, MY_BUFFER_SIZE, NULL) == FALSE)
    continue;
strPdoName = (LPWSTR) buff;

With the collected information, we can sort them using:

  • iBusNumber
  • iDeviceNumber
  • iFunctionNumber

or

  • The name of the PDO (alphabetical sort)

Using the code

You can download the fully working demo project at the top of this page.

To recompile, the following developer packs are required:

  • Windows XP/2003 SDK
  • The newest DDK

History

  • June, 08. 2004 -- Version 1.0
    • Initial Creation

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Switzerland Switzerland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionCode does not work properly with Broadcom NIC multifunction adapters Pin
lunjaa7-Oct-09 2:00
lunjaa7-Oct-09 2:00 
Great code. We tried to use script to fix issue with network interface numbering sequence.
Script is perfect for most network cards, but some of our HP servers have dual Broadcom based multifunction cards (NC371i) onboard and those are detected differently (no info for Bus, Device, Function in the registry as other NIC's), see attached export from Registry. They are always assigned wrong order: Onboard1 is always "Local Area Connection 2" and Onboard2 is always "Local Area Connection".

Is there a way to expand the existing script to include check for adapters with Bus0, Device0 and Function0 and for those two it will assign connection name based on the MAC address?

Ex.: Smaller of the two MAC addresses is onboard1 - "Local Area Connection"

Or if there is any other idea how to do it?

This is output from the code:

Bus 0, Device 0, Function 0
    Pdo Name=\Device\00000062
    Slot Number=N/A
    Connection GUID={2C6BF2C7-FBE0-4F65-A153-41B224D92A0A}
    MAC Address=00:22:64:F7:CB:5C
    Description=HP NC373i Multifunction Gigabit Server Adapter
    Pnp Id=B06BDRV\L2ND&PCI_164C14E4&SUBSYS_7038103C&REV_12\6&154EFE07&0&20050500
    Local area connection names:
        ConnectionName=Local Area Connection
        New ConnectionName=Local Area Connection
        Rename: No action required.



Bus 0, Device 0, Function 0
    Pdo Name=\Device\00000061
    Slot Number=N/A
    Connection GUID={F3B76159-B494-4BF4-B347-EABBCD7F9D58}
    MAC Address=00:22:64:F7:CB:6C
    Description=HP NC373i Multifunction Gigabit Server Adapter #2
    Pnp Id=B06BDRV\L2ND&PCI_164C14E4&SUBSYS_7038103C&REV_12\6&183F41DD&0&20050300
    Local area connection names:
        ConnectionName=Local Area Connection 2
        New ConnectionName=Local Area Connection 2
        Rename: No action required.



Bus 32, Device 0, Function 0
    Pdo Name=\Device\NTPNP_PCI0051
    Slot Number=7
    Connection GUID={BA9A5933-BCBA-44C7-8D43-0B8A9E2786E1}
    MAC Address=00:15:17:91:83:EC
    Description=Intel(R) PRO/1000 PT Quad Port Server Adapter #3
    Pnp Id=PCI\VEN_8086&DEV_10A4&SUBSYS_10A48086&REV_06\6&36493DC&0&00000030
    Local area connection names:
        ConnectionName=Local Area Connection 5
        New ConnectionName=Local Area Connection 3
        Rename: Required!!!



Bus 32, Device 0, Function 1
    Pdo Name=\Device\NTPNP_PCI0052
    Slot Number=7
    Connection GUID={532BECE5-F698-4A38-9C40-2BDBA38C5344}
    MAC Address=00:15:17:91:83:ED
    Description=Intel(R) PRO/1000 PT Quad Port Server Adapter #4
    Pnp Id=PCI\VEN_8086&DEV_10A4&SUBSYS_10A48086&REV_06\6&36493DC&0&01000030
    Local area connection names:
        ConnectionName=Local Area Connection 6
        New ConnectionName=Local Area Connection 4
        Rename: Required!!!



Bus 33, Device 0, Function 0
    Pdo Name=\Device\NTPNP_PCI0049
    Slot Number=7
    Connection GUID={C0893663-7558-4A23-A3FA-522EF7AD08F3}
    MAC Address=00:15:17:91:83:EE
    Description=Intel(R) PRO/1000 PT Quad Port Server Adapter
    Pnp Id=PCI\VEN_8086&DEV_10A4&SUBSYS_10A48086&REV_06\6&23168775&0&00080030
    Local area connection names:
        ConnectionName=Local Area Connection 3
        New ConnectionName=Local Area Connection 5
        Rename: Required!!!



Bus 33, Device 0, Function 1
    Pdo Name=\Device\NTPNP_PCI0050
    Slot Number=7
    Connection GUID={5F6B643F-1F9F-4B04-8EB9-A75839D6EADE}
    MAC Address=00:15:17:91:83:EF
    Description=Intel(R) PRO/1000 PT Quad Port Server Adapter #2
    Pnp Id=PCI\VEN_8086&DEV_10A4&SUBSYS_10A48086&REV_06\6&23168775&0&01080030
    Local area connection names:
        ConnectionName=Local Area Connection 4
        New ConnectionName=Local Area Connection 6
        Rename: Required!!!


This is export from registry for HP (Broadcom) card:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0012]
"Characteristics"=dword:00000084
"BusType"="5"
"ComponentId"="b06bdrv\\l2nd&pci_164c14e4&subsys_7038103c"
"*SpeedDuplex"="0"
"enable_8021p"="0"
"enable_lso"="1"
"enable_rss"="1"
"flow_ctrl_cap"="2147483648"
"ofld_cap"="63"
"wire_speed"="1"
"InfPath"="oem14.inf"
"InfSection"="NC373i_x86ws3"
"ProviderName"="Hewlett-Packard Company"
"DriverDateData"=hex:00,80,ce,5c,db,80,c9,01
"DriverDate"="1-28-2009"
"DriverVersion"="4.8.5.0"
"MatchingDeviceId"="b06bdrv\\l2nd&pci_164c14e4&subsys_7038103c"
"DriverDesc"="HP NC373i Multifunction Gigabit Server Adapter"
"NetCfgInstanceId"="{F3B76159-B494-4BF4-B347-EABBCD7F9D58}"

GeneralGood article, bad title Pin
Rodrigo Strauss14-Jun-04 8:43
Rodrigo Strauss14-Jun-04 8:43 
GeneralRe: Good article, bad title Pin
Anonymous14-Jun-04 21:55
Anonymous14-Jun-04 21:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.