Ресурсы локальной сети
Для получения списка ресурсов локальной сети нужно использовать функции lan manager:
WNetOpenEnum - начать перечисление,
WNetEnumResource - перечислить ресурсы,
WNetCloseEnum - закончить перечисление.
3 вышеописанные функции дают список имен серверов, принтеров, и т. д. Для получения информации о конкретном сервере можно воспользоваться функцией NetServerGetInfo.
Также, иногда интересно узнать IP адрес компа - здесь нужен WinSock и его gethostbyname.
Пример консольной проги, реализующей все вышеописанное:
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;
}