c++ - Windows Netapi32

标签 c++ c windows netapi32

我目前正在使用 Netapi32.lib 访问 Windows Netapi32,目前我正在使用 c++ 访问 api。我在检索计算机名称时遇到问题,目前是 NetFileEnum hereFILE_INFO_3 结构上 here .在文档中说,

fi3_username

Pointer to a string that specifies which user (on servers that have user-level security) or which computer (on servers that have share-level security) opened the resource. Note that Windows does not support share-level security.This string is Unicode if _WIN32_WINNT or FORCE_UNICODE are defined.

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

相关代码

库包括:

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

初始化结构:

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

如果 fstatus 成功返回值 NERR_Success

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

  • ERROR_ACCESS_DENIED 用户无权访问请求 信息。
  • ERROR_INVALID_LEVEL 为级别参数指定的值是 无效。
  • ERROR_INVALID_PARAMETER 指定的参数无效。
  • ERROR_MORE_DATA 更​​多 条目可用。指定一个足够大的缓冲区来接收所有条目。
  • ....

更多here

为了处理这个问题,我使用 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 级(文档 here)缓冲区对象,

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

最佳答案

如果其他人想知道解决方案,我想出来了。要查询与 Computer 而不仅仅是 User 关联的文件数,必须使用 NetFileEnum 函数,文档 here . 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) 检索计算机名称,这将返回网络中的所有计算机名称,文档 here ) 并且查询返回基于 DWORD 级别 的文件详细信息,FILE_INFO_3 文档 hereFILE_INFO_2 文档 here .

关于c++ - Windows Netapi32,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15888794/

相关文章:

C-插入排序链表

c - 为什么mingw-gcc允许无条件使用getch()?

c - 参数与原型(prototype) : struct in_addr 不兼容

c++ - 二进制模式下的 std::ifstream 和 C++ 中的区域设置

c++ - C++ 连续内存中的模板化可变大小结构

c++ - 切换到新选项卡时更改 View - C++、MFC visual studio 2013

c# - WinForms 中如何处理不可见控件的绘制?

windows - xampp 入门

windows - 确定程序是否正在远程桌面上运行

c++ - 构造函数继承和自定义构造函数