Win32 调用netapi32实现用户枚举

netapi32.dll是Windows网络应用程序接口,用于支持访问微软网络。

先看代码;

#include <windows.h>
#include <assert.h>
#include <lm.h>
#include "resource.h"

//#pragma comment(lib,"Y:\\xxx\\cfreePrj\\userdemo2\\mingw5\\NETAPI32.LIB")

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
int ListUsers(LPWSTR, HDC );

HINSTANCE hInst;
TCHAR szClassName[] = TEXT("userDemo");
char errBuffer[100];
char szBuffer[100];

int WINAPI
WinMain (HINSTANCE hThisInstance,
         HINSTANCE hPrevInstance,
         LPSTR lpszArgument,
         int nFunsterStil)
{
    HWND hwnd;
    MSG messages;
    WNDCLASSEX wincl;

	hInst = hThisInstance;
	
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof (WNDCLASSEX);

    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = MAKEINTRESOURCE (IDC_USERDEMO1);
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

    if (!RegisterClassEx (&wincl))
        return 0;

    hwnd = CreateWindowEx (
           0,
           szClassName,
           TEXT("userDemo"),
           WS_OVERLAPPEDWINDOW,
           CW_USEDEFAULT,
           CW_USEDEFAULT,
           200,
           200,
           HWND_DESKTOP,
           NULL,
           hThisInstance,
           NULL
           );

    ShowWindow (hwnd, nFunsterStil);

    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }

    return messages.wParam;
}

LRESULT CALLBACK
WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;
	RECT rt;
	int ret;
				
    switch (message)
    {
			case WM_COMMAND:
    		switch (LOWORD(wParam))
    		{
		    case IDM_ABOUT:
				MessageBox (hwnd, TEXT ("userDemo v1.0\nCopyright (C) 2020\n by bo"),
                        TEXT ("userDemo"), MB_OK | MB_ICONINFORMATION);
				break;
			case IDM_EXIT:
				DestroyWindow(hwnd);
				break;
			default:
				return DefWindowProc(hwnd, message, wParam, lParam);	    		
		    }
    		break;
    	case WM_PAINT:
			hdc = BeginPaint(hwnd, &ps);					
			GetClientRect(hwnd, &rt);			
			ret=ListUsers(NULL, hdc);			
			EndPaint(hwnd, &ps);
			break;
        case WM_DESTROY:
            PostQuitMessage (0);
            break;
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

/*************************************
* 功能    列举用户
* 参数    szServerName,主机名,如果为本机设置为NULL
**************************************/
int ListUsers(LPWSTR pszServerName, HDC hdc)
{
    LPUSER_INFO_0 pBuf = NULL;
    LPUSER_INFO_0 pTmpBuf;
    DWORD dwLevel = 0;
    DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
    DWORD dwEntriesRead = 0;
    DWORD dwTotalEntries = 0;
    DWORD dwResumeHandle = 0;
    DWORD i;
    DWORD dwTotalCount = 0;
    NET_API_STATUS nStatus;

    //pBuf=(LPUSER_INFO_0)VirtualAlloc(NULL,MAX_PREFERRED_LENGTH,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
    // 循环,直到可以成功调用 NetUserEnum
    do 
    {
        // 调用NetUserEnum函数
        nStatus = NetUserEnum(pszServerName,
            dwLevel,// 这里设置为0,使用 LPUSER_INFO_0 返回结果
            FILTER_NORMAL_ACCOUNT, // 只列举正常类型的用户
            (LPBYTE*)&pBuf,// LPUSER_INFO_0 保存返回结果
            // MAX_PREFERRED_LENGTH,内存由API分配,需要在之后调用NetApiBufferFree释放
            dwPrefMaxLen,
            &dwEntriesRead,// 读了的 Entries
            &dwTotalEntries,// 一共的 Entries
            &dwResumeHandle);
        
        if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
        {
            if ((pTmpBuf = pBuf) != NULL)
            {
                for (i = 0; (i < dwEntriesRead); i++)// 循环读取用户信息
                {
                    assert(pTmpBuf != NULL);

                    if (pTmpBuf == NULL)
                    {
                        MessageBox(NULL,"An access violation has occurred\n",TEXT("列举用户"),0);
                        break;
                    }
                    // 输出
                    wsprintf(szBuffer, "%s", pTmpBuf->usri0_name);
		            TextOut(hdc, 20, 20+i*30, szBuffer, lstrlen(szBuffer));
                    // 下一个
                    pTmpBuf++;
                    dwTotalCount++;
                }
            }
        }
        else
            wsprintf(errBuffer, "A system error has occurred: %d\n",nStatus);
            MessageBox(NULL,errBuffer,TEXT("列举用户"),0);
        // 释放内存
        if (pBuf != NULL)
        {
            NetApiBufferFree(pBuf);
            pBuf = NULL;
        }
    }
    while (nStatus == ERROR_MORE_DATA); // end do

    // 释放内存
    if (pBuf != NULL)
        NetApiBufferFree(pBuf);

    wsprintf(szBuffer, "总数 of users:%d\n\n",dwTotalCount);
    MessageBox(NULL,szBuffer,TEXT("列举用户"),0);

    return 0;
}

运行;

获取到2个用户;只输出了用户名第一个字母;

pBuf可能要预先分配内存;

命令行用 net user 查看,用户如下;代码还有问题,有时间再看;

在CFree里,工程设置,如下图,找到NETAPI32.lib,加入进来;然后把路径名和文件后缀,都去掉;才能构建成功;

如果包含lib后缀名;会报类似如下;

[Error] C:\PROGRA~2\C-FREE~1\mingw\bin\ld.exe: cannot find -lNETAPI32.lib

这个好像是g++编译器,不太认识lib文件;

 

还不清楚lib和dll是拷贝到源码或者构建目录,都拷一下;构建出exe的目录是mingw5;

没有netapi32.dll和lib的话,网上单独下;

为了在列举函数里面在窗口上输出,传递 HDC hdc 参数过来;

添加了资源后如下;

resource.h和.rc文件文件类似此文;

https://blog.csdn.net/bcbobo21cn/article/details/106143664

 


版权声明:本文为bcbobo21cn原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。