Windows Netapi32

Я сейчас получаю доступ к Windows Netapi32 с помощью Netapi32.libВ настоящее время я использую c++ чтобы получить доступ к API. У меня проблемы с получением имени компьютера, в настоящее время NetFileEnum здесь на FILE_INFO_3 структура здесь. В документации сказано:

fi3_username

Указатель на строку, которая указывает, какой пользователь (на серверах с безопасностью на уровне пользователей) или какой компьютер (на серверах с безопасностью на уровне общих ресурсов) открыл ресурс. Обратите внимание, что Windows не поддерживает безопасность на уровне общего ресурса. Эта строка является Unicode, если определены _WIN32_WINNT или FORCE_UNICODE.

Теперь сеть, в которой я запускаю этот скрипт, действительно имеет безопасность на уровне общего ресурса, я просто не знаю, как указать имя компьютера.

Соответствующий код

Библиотека включает в себя:

#pragma comment(lib, "Netapi32.lib")
#include <stdio.h>
#include <assert.h>
#include <windows.h> 
#include <lm.h>

Начальная структура:

fstatus определяется в моем коде как, NET_API_STATUS fStatusэто структура ввода / вывода. Документация здесь

если fstatus Успешно возвращаемое значение NERR_Success,

Если функция завершается ошибкой, возвращаемое значение может быть одним из следующих кодов ошибок.

  • ERROR_ACCESS_DENIED Пользователь не имеет доступа к запрашиваемой информации.
  • ERROR_INVALID_LEVEL Значение, указанное для параметра уровня, недопустимо.
  • ERROR_INVALID_PARAMETER Указанный параметр недействителен.
  • ERROR_MORE_DATA More Записи доступны. Укажите достаточно большой буфер для получения всех записей.
  • ....

больше здесь

Чтобы справиться с этим я использую if ((fStatus == NERR_Success) || (fStatus == ERROR_MORE_DATA))

Имя пользователя не может быть найдено.

fStatus = NetFileEnum(
                flServerName, //Pointer to a string that specifies the DNS or NetBIOS name of the remote server on which the function is to execute. If this parameter is NULL, the local computer is used. 
                flBasePath, //Pointer to a string that specifies a qualifier for the returned information. If this parameter is NULL, all open resources are enumerated.
                flUserName, //Pointer to a string that specifies the name of the user or the name of the connection.
                dfLevel, //Pointer to a string that specifies the name of the user or the name of the connection. Can be either 2 or 3, I am using 3
                (LPBYTE*)&pFile, //Pointer to the address of the buffer that receives the information. The format of this data depends on the value of the level parameter. 
                fwPrefMaxLen, //pecifies the preferred maximum length of returned data, in bytes.
                &fwEntriesRead, //Pointer to a value that receives the count of elements actually enumerated.
                &fwTotalEntries, //Pointer to a value that receives the total number of entries that could have been enumerated from the current resume position.
                &fwResumeHandle); //Pointer to a value that contains a resume handle which is used to continue an existing file search.

NET_API_STATUS NetFileEnum(
  _In_     LMSTR servername,
  _In_     LMSTR basepath,
  _In_     LMSTR username,
  _In_     DWORD level,
  _Out_    LPBYTE *bufptr,
  _In_     DWORD prefmaxlen,
  _Out_    LPDWORD entriesread,
  _Out_    LPDWORD totalentries,
  _Inout_  PDWORD_PTR resume_handle
);

RAW значения для вышеупомянутого:

   NET_API_STATUS fStatus;
   LPFILE_INFO_3 pFile = NULL;
   LPFILE_INFO_3 pTmpFile;
   DWORD dfLevel = 3;
   LPTSTR flServerName = NULL;
   LPTSTR flUserName = NULL;
   LPTSTR flBasePath = NULL;
   DWORD fwPrefMaxLen = MAX_PREFERRED_LENGTH;
   DWORD fwEntriesRead = 0;
   DWORD fwTotalEntries = 0;
   DWORD fwResumeHandle = 0;

pTmpfile является буферным объектом уровня 3 (документация здесь),

bufptr [out]

Pointer to the address of the buffer that receives the information. The format of this data depends on the value of the levelparameter.

Этот буфер возвращает данные в этом формате,

typedef struct _FILE_INFO_3 {
  DWORD fi3_id;
  DWORD fi3_permissions;
  DWORD fi3_num_locks;
  LMSTR fi3_pathname;
  LMSTR fi3_username;
} FILE_INFO_3, *PFILE_INFO_3, *LPFILE_INFO_3;

Получить данные:

printf("\n\tComputer: %S\n", pTmpFile->fi3_username); //how do I retrieve computer name???
printf("\n\tid: %D\n", pTmpFile->fi3_id);
printf("\n\tpath: %S\n", pTmpFile->fi3_pathname);

** Важно отметить, что я пробовал это с помощью vbnet, и это работает, но как-то не могу понять, как это сделать на C++.

Полная программа испытаний:

#ifndef UNICODE
#define UNICODE
#endif
//Initialize the NetAPI Library
#pragma comment(lib, "Netapi32.lib")
#include <stdio.h>
#include <assert.h>
#include <windows.h>
#include <lm.h>
int wmain(int argc, wchar_t *argv[])
{
    //NetFile Enum, using 3 Level.
    NET_API_STATUS fStatus;
    LPFILE_INFO_3 pFile = NULL;
    LPFILE_INFO_3 pTmpFile;
    DWORD dfLevel = 3;
    LPTSTR flServerName = NULL;
    LPTSTR flUserName = NULL;
    LPTSTR flBasePath = NULL;
    DWORD fwPrefMaxLen = MAX_PREFERRED_LENGTH;
    DWORD fwEntriesRead = 0;
    DWORD fwTotalEntries = 0;
    DWORD fwResumeHandle = 0;
    DWORD fi;
    //
    // Check command line arguments.
    // Dont need this currently.
    //
    do
    {
        fStatus = NetFileEnum(flServerName,
        flBasePath,
        flUserName,
        dfLevel,
        (LPBYTE*)&pFile,
        fwPrefMaxLen,
        &fwEntriesRead,
        &fwTotalEntries,
        &fwResumeHandle);
        if ((fStatus == NERR_Success) || (fStatus == ERROR_MORE_DATA))
        {
            if ((pTmpFile = pFile) != NULL)
            {
                for (fi=0; fi < fwEntriesRead; fi++)
                {
                    assert(pTmpFile != NULL);
                    if (pTmpFile == NULL)
                    {
                        fprintf(stderr, "An access violation has occurred\n");
                        break;
                    }
                    printf("\n\tComputer: %S", pTmpFile->fi3_username);
                    printf("\n\tid: %d", pTmpFile->fi3_id);
                    printf("\n\tpath: %s", pTmpFile->fi3_pathname);
                    printf("\n\tLocks: %d\n", pTmpFile->fi3_num_locks);
                    pTmpFile++;
                    fwTotalEntries++;
                }
            }
        }
        else
        fprintf(stderr, "A system error has occurred: %d\n", fStatus);
        //
        // Free the allocated memory.
        //
        if (pFile != NULL)
        {
            NetApiBufferFree(pFile);
            pFile = NULL;
        }
    }
    //
    // Continue to call NetFilEnum while
    //  there are more entries.
    //
    while (fStatus == ERROR_MORE_DATA);
    if (pFile != NULL)
    NetApiBufferFree(pFile);
    return 0;
}

Выход:

Из сборки:

1>------ Build started: Project: Perfmon, Configuration: Release Win32 ------
1>Compiling...
1>file_enumerate.cpp
1>Linking...
1>Generating code
1>Finished generating code
1>Embedding manifest...
1>Build log was saved at "file://...."
1>Perfmon - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Бежать:

 Computer: User1 //prints only username, not computername (in our system, each user has the same username)
 id: 1005687
 path: c:\fips\library

 Computer: User2 //prints only username, not computername (in our system, each user has the same username)
 id: 1005689
 path: c:\fips\library\util

1 ответ

Решение

Если кто-то еще задается вопросом о решении, я понял это. Для запроса количества файлов, связанных с Computer и не только User, NetFileEnum Функция должна быть использована, документация здесь. NetFileEnum синтаксис показан ниже,

NET_API_STATUS NetFileEnum(
  _In_     LMSTR servername,
  _In_     LMSTR basepath,
  _In_     LMSTR username,
  _In_     DWORD level,
  _Out_    LPBYTE *bufptr,
  _In_     DWORD prefmaxlen,
  _Out_    LPDWORD entriesread,
  _Out_    LPDWORD totalentries,
  _Inout_  PDWORD_PTR resume_handle
);

Где вы должны пройти Computer Name как LMSTR username (вы можете получить имя компьютера по запросу NetSessionEnum(502) который будет возвращать все имена компьютеров в сети, документацию здесь), а запрос возвращает сведения о файле на основе DWORD level, или FILE_INFO_3 документация здесь и FILE_INFO_2 документация здесь.

Другие вопросы по тегам