typedef ULONG NET_IFINDEX; typedef ULONG NETIO_STATUS; typedef union _NET_LUID { ULONG64 Value; struct { ULONG64 Reserved : 24; ULONG64 NetLuidIndex : 24; ULONG64 IfType : 16; } Info; } NET_LUID, *PNET_LUID; typedef NETIO_STATUS (WINAPI * ConvertInterfaceIndexToLuidProc)( NET_IFINDEX InterfaceIndex, PNET_LUID InterfaceLuid ); // // Suspected prototype of NsiGetParameter, via reverse engineering. // typedef DWORD (__stdcall * NsiGetParameterProc)( DWORD Unknown0, // 0x1 CONST UCHAR* NpiId, // 0x14 bytes for us DWORD Unknown1, // 0x7 PNET_LUID NetLuid, // Interface LUID DWORD LuidLength, // Length of LUID DWORD Unknown2, // 0x0 PUCHAR OutputBuf, // IF metric for LUID DWORD OutputLength, // sizeof(DWORD) DWORD Unknown3 // 0x1c ); /* 0:000> db NPI_MS_IPV4_MODULEID l14 751b3364 18 00 00 00 01 00 00 00-00 4a 00 eb 1a 9b d4 11 751b3374 91 23 00 50 04 77 59 BC */ const unsigned char NPI_MS_IPV4_MODULEID[0x18] = { 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x00, 0xEB, 0x1A, 0x9B, 0xD4, 0x11, 0x91, 0x23, 0x00, 0x50, 0x04, 0x77, 0x59, 0xBC }; // // Determine the "interface metric", or the lowest metric permissible on an // interface. // DWORD GetInterfaceMetric( __in DWORD InterfaceIndex, __out __deref PDWORD InterfaceMetric ) { NET_LUID Luid; HMODULE Nsi, Iphlpapi; DWORD Status; ConvertInterfaceIndexToLuidProc _ConvertInterfaceIndexToLuid; NsiGetParameterProc _NsiGetParameter; // // Set InterfaceMetric to zero. This is the acceptable value for pre-Vista // systems. // *InterfaceMetric = 0; do { // // We'll need access to iphlpapi.dll for ConvertInterfaceIndexToLuid. // Iphlpapi = LoadLibraryW(L"Iphlpapi.dll"); if (!Iphlpapi) { Status = GetLastError(); break; } // // Try to load Nsi.dll, which is only present on Vista and later. // Nsi = LoadLibraryW(L"Nsi.dll"); if (!Nsi) { Status = GetLastError(); break; } // // Resolve entrypoints in Iphlpapi and Nsi. // _ConvertInterfaceIndexToLuid = (ConvertInterfaceIndexToLuidProc)GetProcAddress(Iphlpapi, "ConvertInterfaceIndexToLuid"); if (!_ConvertInterfaceIndexToLuid) { Status = GetLastError(); break; } _NsiGetParameter = (NsiGetParameterProc)GetProcAddress(Nsi, "NsiGetParameter"); if (!_NsiGetParameter) { Status = GetLastError(); break; } Status = _ConvertInterfaceIndexToLuid(InterfaceIndex, &Luid); if (Status != NO_ERROR) break; Status = _NsiGetParameter(0x01, NPI_MS_IPV4_MODULEID, 0x07, &Luid, sizeof(Luid), 0, (PUCHAR)InterfaceMetric, sizeof(*InterfaceMetric), 0x1C); if (Status != NO_ERROR) break; } while(0) ; if (Nsi) FreeLibrary(Nsi); if (Iphlpapi) FreeLibrary(Iphlpapi); return Status; }