1

我目前正在使用 访问 Windows Netapi32Netapi32.lib目前我正在使用c++访问 api。我在检索计算机名称时遇到问题,目前是NetFileEnum here on FILE_INFO_3structure here之一。在文档中它说,

fi3_username

指向一个字符串的指针,该字符串指定哪个用户(在具有用户级安全性的服务器上)或哪台计算机(在具有共享级安全性的服务器上)打开了资源。请注意,Windows 不支持共享级安全性。如果定义了 _WIN32_WINNT 或 FORCE_UNICODE,则此字符串为 Unicode。

现在,我运行此脚本的网络确实具有共享级别的安全性,我只是不确定如何列出计算机名称。

相关代码

图书馆包括:

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

初始化结构:

fstatus在我的代码中定义为NET_API_STATUS fStatus,它是 I/O 结构。文档在这里

如果fstatus成功返回值NERR_Success

如果函数失败,返回值可以是以下错误代码之一。

  • ERROR_ACCESS_DENIED用户无权访问请求的信息。
  • ERROR_INVALID_LEVEL为 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
);

以上的原始值:

   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 [输出]

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
4

1 回答 1

1

如果其他人想知道解决方案,我想通了。要查询与 相关联的文件数,Computer而不仅仅是,必须使用User该函数,此处的文档。语法如下所示,NetFileEnumNetFileEnum

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 Nameas LMSTR username(您可以通过查询NetSessionEnum(502)将返回网络中的所有计算机名称,此处的文档)来检索计算机名称,并且查询返回基于此处的文档DWORD levelFILE_INFO_3此处的文档的文件详细信息。FILE_INFO_2

于 2013-04-10T21:29:56.977 回答