회사 제품을 만드는 중에 버그트랙이 하나 올라왔습니다.
내용은 ipconfig 에서 출력되는 어댑터의 Description 과 제품에서 올려주는 Description 이 다르다는 것이었습니다.
제품에서는 GetAdaptersInfo 로 어댑터의 정보를 구하는데 일반적으로 그렇게 만들고 저 또한 예전에는 그렇게 만들어서 왜 다른 결과값이 나오는지 궁금해졌습니다.
먼저 간단하게 VMWare를 통해 확인을 해보니 아래와 같이 결과가 다르게 나오는 것을 확인하였습니다.
 


위에서 보듯이 ipconfig 는 VMWare Accelerated AMD PCNet Adapter 라고 나오고 GetAdaptersInfo에서는 그냥 AMD PCNET Family PCI Ethernet Adapter 라고 나옵니다.

그럼 과연 ipconfig는 어디서 정보를 가져오는 것일까요. 궁금해지기 시작해서 올리로 한번 추적해보기로 하였습니다.
 


먼저 ipconfig 에서는 GetAdaptersInfo를 사용하지 않고 GetAdaptersAddresses를 이용해서 어댑터 정보를 구하는 것을 알 수 있었습니다. GetAdaptersInfo와 GetAdaptersAddresses는 약간 차이가 있는데 먼저 무슨 정보를 반환하는지는 아래의 MSDN 에 기술되어 있습니다.

 GetAdaptersAddresses Function

The GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer.


 GetAdaptersInfo Function

The GetAdaptersInfo function retrieves adapter information for the local computer.

On Windows XP and later: Use the GetAdaptersAddresses function instead of GetAdaptersInfo.
 
GetAdaptersInfo 는 로컬컴퓨터의 설치된 어댑터정보를 추출하는 것인데 XP 이상에서는 대신 GetAdaptersAddress를 사용하기를 권장하고 있습니다.
GetAdaptersAddresses는 로컬컴퓨터의 주소할당과 관련된 어댑터를 추출한다고 나와 있습니다.

반환되는 구조체 역시 약간 다른데 아래의 구조체가 그것입니다.




위와 같이 GetAdaptersAddresses에 반환되는 구조체에는 더 많은 정보를 포함하고 있습니다. 그러나 결론적으로는 아래와 같이 GetAdaptersInfo와 GetAdaptersAddresses 에서 반환되는 Description 은 같습니다.... -_-;;


그것은 ipconfig 가 어댑터의 정확한 Description을 얻기위해 추가작업을 한다는 뜻이 되겠죠.
뭔가 단서를 더 잡기 위해 스트링을 출력하기 이전까지 눈 빠지게 추적해봤습니다.
결국 아래와 같은 함수를 호출하는 것을 확인하였습니다.


IP_ADAPTER_ADDRESSES.AdapterName

IP_ADAPTER_ADDRESSES.AdapterName


AdapterName으로 PnpInstanceId 획득

AdapterName으로 PnpInstanceId 획득


SetupDiCreateDeviceInfoList 시작

SetupDiCreateDeviceInfoList 시작


PnpInstanceId로 SetupDiOpenDeviceInfo 디바이스 정보 오픈

PnpInstanceId로 SetupDiOpenDeviceInfo 디바이스 정보 오픈


SetupDiGetDeviceRegistryProperty 호출

SetupDiGetDeviceRegistryProperty 호출


VMWare Accelerated AMD PCNet Adapter 획득

VMWare Accelerated AMD PCNet Adapter 획득

SetupDi 류 종료

SetupDi 류 종료


간략하게 다시 기술하면 아래와 같습니다.
ipconfig 에서 Adapter Description 구하는 절차

1. GetAdaptersAddresses 로 어댑터 리스트 획득
2. netman.dll HrPnpInstanceIdFromGuid 함수를 통해 AdapterName 으로 InstanceId를 획득
3. SetupDi 함수류를 통해 InstanceId로 Adapter의 Description 을 획득
4. SetupDiCreateDeviceInfoList ( GUID_DEVCLASS_NET 으로 오픈 )
5. SetupDiOpenDeviceInfo ( InstanceId 입력 )
6. SetupDiGetDeviceRegistryProperty ( Description 획득 )
7. SetupDiDestroyDeviceInfoList

참고로 SetupDi 류의 함수는 하드웨어 정보를 더욱 낮은 단계로부터 구하는 함수이며 결국은 대부분 레지스트리에서 가지고 오는 것입니다.
위에서 사용한 SetupDi류가 가지고 오는 레지스트리 위치는 아래와 같더군요.

SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\[NUMBER]\\

따라서 ipconfig 와 같은 결과를 얻기 위해서는 아래의 절차를 따르면 됩니다.

1. GetAdaptersAddresses를 통해 어댑터 정보를 획득
2. 위에서 기술된 레지스트리로 이동
3. 모든 키를 열거하여 NetCfgInstanceId 와 획득한 어댑터의 AdapterName 과 일치하는 키확인
4. 해당 키에서 DriverDesc 를 획득

아무튼 획득하는 방법을 알게 되었지만 HrPnpInstanceIdFromGuid 함수에 대해서는 도저히 찾을 수가 없더군요.
어디에도 다큐먼트되어 있지 않네요. -_-;; COM 인거는 같은데..

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기