Для получения списка ресурсов локальной сети нужно использовать функции lan manager: WNetOpenEnum - начать перечисление, WNetEnumResource - перечислить ресурсы, WNetCloseEnum - закончить перечисление.
3 вышеописанные функции дают список имен серверов, принтеров, и т. д. Для получения информации о конкретном сервере можно воспользоваться функцией NetServerGetInfo.
Также, иногда интересно узнать IP адрес компа - здесь нужен WinSock и его gethostbyname.
Пример консольной проги, реализующей все вышеописанное:
#pragma comment(lib, "netapi32.lib") #pragma comment(lib, "mpr.lib") #pragma comment(lib, "ws2_32.lib")
#include <windows.h> #include <stdio.h> #include <lm.h>
// Максимум ресурсов в container'е #define MAX_NET_RESOURCES (1024)
// Рекурсивная функция, которая, собственно, и пишет всю инфу int ResFunc(NETRESOURCE *pNr, // pNr - NETRESOURCE container'а, где смотреть содержимое int sp); // sp - количество пробелов для отступа
// Удалось ли проинициализировать WinSock BOOL bWSA;
// Дни недели char *szWeekDays[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; // Месяцы char *szMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int main() { // Для определения IP адресов нужен WinSock // Попытаемся проинициализировать WinSock WORD wVersion = MAKEWORD(1, 1); WSADATA wsaData; DWORD dwRes = WSAStartup(wVersion, &wsaData); bWSA = (dwRes == 0); if(!bWSA) // Если WinSock не работает, то определение IP будет не доступно :-( printf("WSAStartup() failed with %d, gethostbyname() unavailable\n", dwRes);
// Начнем сканирование с самого верхнего уровня ResFunc(NULL, 0);
// Освободим WinSock if(bWSA) WSACleanup();
return 0; }
int ResFunc(NETRESOURCE *pNr, int sp) { HANDLE hEnum; DWORD dwRes;
// Начнем перечисление сетевых ресурсов dwRes = WNetOpenEnum( RESOURCE_GLOBALNET, // область видимости - вся сеть RESOURCETYPE_ANY, // тип ресурсов - диски и принтеры 0, // тип ресурсов - подключаемые и содержащие pNr, // начать с pNr &hEnum); // передать хендл в hEnum if(dwRes!=NO_ERROR) // ошибка { printf("WNetOpenEnum failed with %d\n", dwRes); if(dwRes==ERROR_EXTENDED_ERROR) { DWORD dwError; char szErrorBuff[256], szNameBuff[256];
WNetGetLastError(&dwError, szErrorBuff, 256, szNameBuff, 256); printf("%s [%d]: %s\n", szNameBuff, dwError, szErrorBuff); }
return 1; }
NETRESOURCE NetResource[MAX_NET_RESOURCES]; // буффер для хранения информации про ресурсы DWORD dwCount = 0xFFFFFFFF, dwSize = sizeof(NETRESOURCE)*MAX_NET_RESOURCES;
// Перечислим ресурсы в текущем container'е dwRes = WNetEnumResource(hEnum, // хендл на перечисление &dwCount, // количество ресурсов (LPVOID*)&NetResource, // буффер для хранения информации про ресурсы &dwSize);
if(dwRes!=NO_ERROR) // ошибка { printf("WNetEnumResource failed with %d\n", dwRes); if(dwRes==ERROR_EXTENDED_ERROR) { DWORD dwError; char szErrorBuff[256], szNameBuff[256];
WNetGetLastError(&dwError, szErrorBuff, 256, szNameBuff, 256); printf("%s [%d]: %s\n", szNameBuff, dwError, szErrorBuff); }
return 2; }
// Будем перебирать все ресурсы DWORD dw; for(dw=0; dw < dwCount; dw++) { for(int i=0; i < sp; i++) // Нарисуем отступ
// Если ресурс - сервер if(NetResource[dw].dwDisplayType == RESOURCEDISPLAYTYPE_SERVER) { char szIP[256]; if(bWSA) // Если WinSock доступен, то определим IP адрес { char szName[256]; for(int i=0; NetResource[dw].lpRemoteName[i+1]!='\0'; i++) szName[i]=NetResource[dw].lpRemoteName[i+2];
struct hostent *hp = gethostbyname(szName); if(!hp) strcpy(szIP, "ip=???"); else { DWORD dwIP = ((in_addr*)hp->h_addr_list[0])->S_un.S_addr; int a = LOBYTE(LOWORD(dwIP)); int b = HIBYTE(LOWORD(dwIP)); int c = LOBYTE(HIWORD(dwIP)); int d = HIBYTE(HIWORD(dwIP));
sprintf(szIP, "%d.%d.%d.%d", a, b, c, d); } } else sprintf(szIP, "ip=???");
// Буфферы для информации в текстовом виде char szOS[256]; char szOS_Version[256], szOS_Platform[256], szOS_Soft[256]; // Буффер для информации о сервере SERVER_INFO_101 *pSI101; NetApiBufferAllocate(sizeof(SERVER_INFO_101), (LPVOID*)&pSI101); wchar_t wcName[256]; mbstowcs(wcName, NetResource[dw].lpRemoteName, 256); // Получим информацию о сервере NET_API_STATUS nasRes; nasRes = NetServerGetInfo( (char*)&wcName, 101, (UCHAR**)&pSI101); if(nasRes!=NERR_Success) { printf("NetServerGetInfo failed with %d\n", nasRes); continue; }
// Версия системы sprintf(szOS_Version, "%d.%d", pSI101->sv101_version_major & MAJOR_VERSION_MASK, pSI101->sv101_version_minor);
// Тип системы switch(pSI101->sv101_platform_id) { case PLATFORM_ID_DOS: strcpy(szOS_Platform, "DOS"); break; case PLATFORM_ID_OS2: strcpy(szOS_Platform, "OS2"); break; case PLATFORM_ID_NT: strcpy(szOS_Platform, "NT"); break; case PLATFORM_ID_OSF: strcpy(szOS_Platform, "OSF"); break; case PLATFORM_ID_VMS: strcpy(szOS_Platform, "VMS"); break; default: strcpy(szOS_Platform, "ost=???"); }
// Сервисы strcpy(szOS_Soft, ""); if(pSI101->sv101_type & SV_TYPE_WORKSTATION) strcat(szOS_Soft, "Wst, "); if(pSI101->sv101_type & SV_TYPE_SERVER) strcat(szOS_Soft, "Serv, "); if(pSI101->sv101_type & SV_TYPE_SQLSERVER) strcat(szOS_Soft, "SQL Serv, "); if(pSI101->sv101_type & SV_TYPE_DOMAIN_CTRL) strcat(szOS_Soft, "PDC, "); if(pSI101->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) strcat(szOS_Soft, "BDC, "); if(pSI101->sv101_type & SV_TYPE_TIME_SOURCE) strcat(szOS_Soft, "TimeSource, "); if(pSI101->sv101_type & SV_TYPE_AFP) strcat(szOS_Soft, "AFP, "); if(pSI101->sv101_type & SV_TYPE_NOVELL) strcat(szOS_Soft, "Novell Serv, "); if(pSI101->sv101_type & SV_TYPE_DOMAIN_MEMBER) strcat(szOS_Soft, "Domain Member, "); if(pSI101->sv101_type & SV_TYPE_PRINTQ_SERVER) strcat(szOS_Soft, "Printer Serv, "); if(pSI101->sv101_type & SV_TYPE_DIALIN_SERVER) strcat(szOS_Soft, "Dial Serv, "); if(pSI101->sv101_type & SV_TYPE_XENIX_SERVER) strcat(szOS_Soft, "Unix Serv, "); if(pSI101->sv101_type & SV_TYPE_NT) strcat(szOS_Soft, "NT Wst/Serv, "); if(pSI101->sv101_type & SV_TYPE_SERVER_NT) strcat(szOS_Soft, "NT non-DC, "); if(pSI101->sv101_type & SV_TYPE_WFW) strcat(szOS_Soft, "WFW, "); if(pSI101->sv101_type & SV_TYPE_SERVER_MFPN) strcat(szOS_Soft, "MFPN, "); if(pSI101->sv101_type & SV_TYPE_SERVER_OSF) strcat(szOS_Soft, "OSF, "); if(pSI101->sv101_type & SV_TYPE_SERVER_VMS) strcat(szOS_Soft, "VMS, "); if(pSI101->sv101_type & SV_TYPE_DFS) strcat(szOS_Soft, "DFS, "); if(pSI101->sv101_type & SV_TYPE_CLUSTER_NT) strcat(szOS_Soft, "NT Cluster, "); if(pSI101->sv101_type & SV_TYPE_DCE) strcat(szOS_Soft, "IBM DSS, "); if(pSI101->sv101_type & SV_TYPE_POTENTIAL_BROWSER) strcat(szOS_Soft, "PBR, "); if(pSI101->sv101_type & SV_TYPE_BACKUP_BROWSER) strcat(szOS_Soft, "BBR, "); if(pSI101->sv101_type & SV_TYPE_MASTER_BROWSER) strcat(szOS_Soft, "MBR, "); if(pSI101->sv101_type & SV_TYPE_DOMAIN_MASTER) strcat(szOS_Soft, "Domain master, "); if(pSI101->sv101_type & SV_TYPE_DOMAIN_ENUM) strcat(szOS_Soft, "Primary domain, "); if(pSI101->sv101_type & SV_TYPE_WINDOWS) strcat(szOS_Soft, "W95, ");
szOS_Soft[strlen(szOS_Soft)-2]='\0';
sprintf(szOS, "%s | %s", szOS_Platform, szOS_Version);
NetApiBufferFree((LPVOID)pSI101);
// Буфферы для хранения информации о времени char szTime[256]; TIME_OF_DAY_INFO *pTODI = NULL;
// Получим время на сервере nasRes = NetRemoteTOD(wcName, (LPBYTE*)&pTODI);
if(nasRes==NERR_Success) { sprintf(szTime, "%02d:%02d:%02d %02d/%s/%02d ", pTODI->tod_hours - pTODI->tod_timezone/60, pTODI->tod_mins, pTODI->tod_secs, pTODI->tod_day, szMonths[pTODI->tod_month-1], pTODI->tod_year, szWeekDays[pTODI->tod_weekday], pTODI->tod_timezone); } else sprintf(szTime, "NetRemoteTOD failed");
NetApiBufferFree((LPVOID*)pTODI);
// Напишем то, что удалось узнать DWORD j; printf("%s [%s] [%s]\n", NetResource[dw].lpRemoteName, szIP, szOS);
for(j=0; j < sp + strlen(NetResource[dw].lpRemoteName) + 1; j++) printf(" "); printf("[%s]\n", szOS_Soft); for(j=0; j < sp + strlen(NetResource[dw].lpRemoteName) + 1; j++) printf(" "); printf("[%s]\n", szTime); for(j=0; j < sp + strlen(NetResource[dw].lpRemoteName) + 1; j++) printf(" "); printf("(%s) is ", NetResource[dw].lpComment); } else printf("%s (%s) is ", NetResource[dw].lpRemoteName, NetResource[dw].lpComment); // Напишем тип ресурса switch(NetResource[dw].dwDisplayType) { case RESOURCEDISPLAYTYPE_GENERIC: printf("generic, "); break; case RESOURCEDISPLAYTYPE_DOMAIN: printf("domain, "); break; case RESOURCEDISPLAYTYPE_SERVER: printf("server, "); break; case RESOURCEDISPLAYTYPE_SHARE: printf("share, "); break; case RESOURCEDISPLAYTYPE_FILE: printf("file, "); break; case RESOURCEDISPLAYTYPE_GROUP: printf("group, "); break; case RESOURCEDISPLAYTYPE_NETWORK: printf("network, "); break; case RESOURCEDISPLAYTYPE_ROOT: printf("root, "); break; case RESOURCEDISPLAYTYPE_SHAREADMIN: printf("shareadmin, "); break; case RESOURCEDISPLAYTYPE_DIRECTORY: printf("directory, "); break; case RESOURCEDISPLAYTYPE_TREE: printf("tree, "); break; case RESOURCEDISPLAYTYPE_NDSCONTAINER: printf("nds, "); break; default: printf("rdt=???, "); break; }
// connectable - то, что можно подключить (диск, принтер, ...) if(NetResource[dw].dwUsage & RESOURCEUSAGE_CONNECTABLE) printf("connectable, ");
// container - то, что содержит connectable :-) if(NetResource[dw].dwUsage & RESOURCEUSAGE_CONTAINER) printf("container, ");
// Напишем, чем является ресурс switch(NetResource[dw].dwType) { case RESOURCETYPE_ANY: printf("any"); break; case RESOURCETYPE_DISK: printf("disk"); break; case RESOURCETYPE_PRINT: printf("print"); break; case RESOURCETYPE_RESERVED: printf("reserved"); break; case RESOURCETYPE_UNKNOWN: printf("unknown"); break;
default: printf("rt=???"); break; }
printf("\n"); // Если ресурс является container'ом, то посмотрим, что в нем есть :-) if(NetResource[dw].dwUsage & RESOURCEUSAGE_CONTAINER) ResFunc(&NetResource[dw], sp+1); }
// Закроем перечисление WNetCloseEnum(hEnum);
return 0; } |