Часто задаваемые вопросы и ответы по C/C++/Visual C++
Последнее обновление: 27.08.2003
FAQ по C/C++/Visual C++
Работа с сетью
Ресурсы локальной сети
Составители: SUnteXx, Leprecon
Ресурсы локальной сети
A: (andyag)
Оригинальная ссылка: нету

Для получения списка ресурсов локальной сети нужно использовать функции 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;
}

Содержание Обсудить на форуме « Предыдущая статья | Следующая статья »
Перейти к FAQ:  
FAQ составлен по материалам Форума на Исходниках.Ру.
Copyright © 2002 by Sources.ru. All rights reserved.