Windows Netapi32

Windows Netapi32

本文关键字:Netapi32 Windows      更新时间:2023-10-16

我目前使用Netapi32.lib访问Windows Netapi32,目前我使用c++访问api。我在检索计算机名称时遇到了麻烦,目前在FILE_INFO_3结构上的NetFileEnum在这里。文档中写着

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("ntComputer: %Sn", pTmpFile->fi3_username); //how do I retrieve computer name???
printf("ntid: %Dn", pTmpFile->fi3_id);
printf("ntpath: %Sn", 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 occurredn");
                        break;
                    }
                    printf("ntComputer: %S", pTmpFile->fi3_username);
                    printf("ntid: %d", pTmpFile->fi3_id);
                    printf("ntpath: %s", pTmpFile->fi3_pathname);
                    printf("ntLocks: %dn", pTmpFile->fi3_num_locks);
                    pTmpFile++;
                    fwTotalEntries++;
                }
            }
        }
        else
        fprintf(stderr, "A system error has occurred: %dn", 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:fipslibrary
 Computer: User2 //prints only username, not computername (in our system, each user has the same username)
 id: 1005689
 path: c:fipslibraryutil

如果有人想知道解决方案,我已经想到了。要查询与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文档。