День добрый, пишу небольшую программку и споткнулся о проблему, суть программы: определить сетевой адаптер типа Ethernet (Wireless должен игнорироваться), к которому был подключен кабель (в случае если их несколько). 1. К сожалению определять тип адаптера не получается, ни через GetAdaptersInfo (даже если подключение виртуальное - например Hamachi - то всеравно PIP_ADAPTER_INFO->Type = MIB_IF_TYPE_ETHERNET), ни через GetIfTable (аналогичная картина - PMIB_IFROW->dwType = IF_TYPE_ETHERNET_CSMACD), единственное что пришло в голову так это определять тип энумератора через SetupDiGetDeviceRegistryProperty (если в буфере лежит "PCI" - значит сетевуха установлена физически), но опять же - тип адаптера не известен - Ethernet или Wireless...где то видел буржуи предлагают установить DDK и использовать NDIS и далее проверять каждый адаптер на совместимые OID_SCOPE...сюда я покачто не лез... 2. Может быть есть другой подход, но более ничего в голову не пришло как определять подключен кабель или нет, суть идеи такова: когда кабель отсутствует то PIP_ADAPTER_INFO->IpAddressList = 0.0.0.0 (при условии что DHCP включен), тоесть когда будет получен PIPA IP то это и есть искомая сетевуха, но есть и свои затыки - например отключено несколько связанных служб и получение адреса может идти "бесконечно" (либо по другим причинам), так что в этом месте тоже непонятки, как лучше сделать... У кого-нибудь есть идеи на этот счёт ?..
Определить подключен ли сетевой кабель можно с точностью в 100% вот таким способом (код древний и на паскале, но там сплошное апи): Код (Text): 66 MAX_ADAPTER_NAME_LENGTH = 256; 67 MAX_ADAPTER_DESCRIPTION_LENGTH = 128; 68 MAX_ADAPTER_ADDRESS_LENGTH = 8; 69 70 MAX_INTERFACE_NAME_LEN = $100; 71 MAXLEN_IFDESCR = $100; 72 MIB_IF_ADMIN_STATUS_UP = 1; 73 MIB_IF_ADMIN_STATUS_DOWN = 2; 74 MIB_IF_ADMIN_STATUS_TESTING = 3; 75 MIB_IF_OPER_STATUS_NON_OPERATIONAL = 0; 76 MIB_IF_OPER_STATUS_UNREACHABLE = 1; 77 MIB_IF_OPER_STATUS_DISCONNECTED = 2; 78 MIB_IF_OPER_STATUS_CONNECTING = 3; 79 MIB_IF_OPER_STATUS_CONNECTED = 4; 80 MIB_IF_OPER_STATUS_OPERATIONAL = 5; 81 MIB_IF_TYPE_OTHER = 1; 82 MIB_IF_TYPE_ETHERNET = 6; 83 MIB_IF_TYPE_TOKENRING = 9; 84 MIB_IF_TYPE_FDDI = 15; 85 MIB_IF_TYPE_PPP = 23; 86 MIB_IF_TYPE_LOOPBACK = 24; 87 MIB_IF_TYPE_SLIP = 28; 88 89 type 90 TMac = array [0..MAX_ADAPTER_ADDRESS_LENGTH-1] of byte; 91 _MIB_IFROW = packed record 92 wszName: array [0..MAX_INTERFACE_NAME_LEN-1] of WCHAR; 93 dwIndex, 94 dwType, 95 dwMtu, 96 dwSpeed, 97 dwPhysAddrLen: DWORD; 98 bPhysAddr: TMac; 99 dwAdminStatus, 100 dwOperStatus, 101 dwLastChange, 102 dwInOctets, 103 dwInUcastPkts, 104 dwInNUcastPkts, 105 dwInDiscards, 106 dwInErrors, 107 dwInUnknownProtos, 108 dwOutOctets, 109 dwOutUcastPkts, 110 dwOutNUcastPkts, 111 dwOutDiscards, 112 dwOutErrors, 113 dwOutQLen, 114 dwDescrLen: DWORD; 115 bDescr: array [0..MAXLEN_IFDESCR-1] of char; 116 end; 117 MIB_IFROW = _MIB_IFROW; 118 PMIB_IFROW = ^MIB_IFROW; 119 120 _MIB_IFTABLE = packed record 121 dwNumEntries: DWORD; 122 table: array [0..0] of MIB_IFROW; 123 end; 124 MIB_IFTABLE = _MIB_IFTABLE; 125 PMIB_IFTABLE = ^MIB_IFTABLE; ... 306 function GetAdapterError(MAC: TMac): DWORD;stdcall; 307 var 308 IFTABLESIZE: DWORD; 309 IFTABLE: PMIB_IFTABLE; 310 begin 311 IFTABLESIZE := 0; 312 Result := 0; 313 GetIfTable(nil,@IFTABLESIZE,true); 314 if IFTABLESIZE = 0 then exit; 315 GetMem(IFTABLE,IFTABLESIZE); 316 ZeroMemory(IFTABLE,IFTABLESIZE); 317 if GetIfTable(IFTABLE,@IFTABLESIZE,true) = 0 then 318 begin 319 while (IFTABLE^.dwNumEntries > 0) and 320 (not CompareMem(@IFTABLE^.table[IFTABLE^.dwNumEntries-1].bPhysAddr, 321 @Mac,IFTABLE^.table[IFTABLE^.dwNumEntries-1].dwPhysAddrLen)) do dec(IFTABLE^.dwNumEntries); 322 if IFTABLE^.dwNumEntries > 0 then 323 Result := IFTABLE^.table[IFTABLE^.dwNumEntries-1].dwOperStatus; 324 end; 325 FreeMem(IFTABLE); 326 end; Если возвращает: MIB_IF_OPER_STATUS_DISCONNECTED то сетевой не подключен P.S. Кажется и MIB_IF_OPER_STATUS_NON_OPERATIONAL указывает на не подключенность сетевого кабеля.
Хмм...есть мнение, что этот код будет возвращать MIB_IF_OPER_STATUS_DISCONNECTED и в том случае если адаптер просто отключен.... Как на работу приду - перепишу и посмотрим, спасибо за отклик )
Проверил, на 2003 Server / XP - проблем нет, работает, а вот на висте и семёрке почему то...не могу запустить GetIfTable, возвращает ERROR_INSUFFICIENT_BUFFER... Вот что пишет по этому поводу msdn: Самое интересное в том, что в хидере, описания на GetIfTable2 я так и не нашёл...опять гемморой.....
На висте такое вполне работает: Код (Text): ULONG bsz=0; GetIfTable(NULL,&bsz,false); char* buf=malloc(bsz); GetIfTable((PMIB_IFTABLE)buf,&bsz,false);
Делаю аналогично: Код (Text): PMIB_IFTABLE pTable = NULL; DWORD dwSize = 0; if ( GetIfTable( pTable, &dwSize, FALSE ) == ERROR_INSUFFICIENT_BUFFER ) { pTable = PMIB_IFTABLE(LocalAlloc(LMEM_ZEROINIT, dwSize)); if ( !GetIfTable( pTable, &dwSize, TRUE ) ) {... GetIfTable возвращает код 87, ничего не понятно, буду ковырять...
Wereww Может для случая когда последний параметр TRUE требуется больше памяти чем для FALSE? хотя конечно маразм.
Маразм... Без разницы, последний параметр отвечает за сортировку помойму, менял их и true и false и наоборот, - менялся только порядок перечисления интерфейсов... Даже так сделал: Код (Text): PMIB_IFTABLE pTable = NULL; DWORD dwSize = 0; GetIfTable( NULL, &dwSize, FALSE ); if (dwSize != 0) { pTable = PMIB_IFTABLE(LocalAlloc(LMEM_ZEROINIT, dwSize)); if ( !GetIfTable( pTable, &dwSize, FALSE ) ) { Результат один и тот же, затык именно на первой GetIfTable, что то с размером не так... Код (Text): ULONG bsz=0; GetIfTable(NULL,&bsz,false); char* buf=malloc(bsz); GetIfTable((PMIB_IFTABLE)buf,&bsz,false); [C++ Error] iphlpapi.cpp(26): E2034 Cannot convert 'void *' to 'char *' Сразу оговорюсь, что компилятор Borland, пишу на CB6.
Wereww А если заранее попробовать выделить много памяти? Код (Text): DWORD bsz = 0x100000; char buf[0x100000]; GetIfTable((PMIB_IFTABLE)buf,&bsz,false);
Пффф...заработало, сделал через GetProcAddress (GetIfTable2, GetIfTable) Оказывается такая проблема не только у меня Так нельзя делать, exception будет, функция не проверяет размер буфера
Теперь осталась одна проблемка, надо отличить Ethernet адаптер от Wireless, как найду чего-нибудь, отпишусь...
Проблема полностью решена, переписываю и делаю только через NDIS ) удобная штука ) Сейчас ковыряю этот сочный сорец ) Накидаю еще несколько линков, кому интересно: Unplugged ethernet cable vs. ip address conflict Network Driver Object Identifiers OCTL_NDIS_QUERY_GLOBAL_STATS NDIS Object Identifiers
Рабочий ) правда писал на С++ и немного по другому ) Насчёт NDIS ) аналогичная ситуация )))))) проверял на нескольких ноутбуках ))) когда делаю запрос OID_GEN_MEDIA_IN_USE то в буфере всеравно лежит 0, тоесть NdisMedium802_3, тоесть Ethernet ) простите за тавтологию ) но всеравно вышел из ситуации - делаю повторный запрос OID_802_11_NETWORK_TYPE_IN_USE и разумеется если это не вай фай то получу на выходе ноль )
Ну на С, не на С там АПИ в основном потому тут на язык грубо говоря по...й. Сам когда-то перерыл кучу форумов, в том числе и Васм...