【问题标题】:NetApiBufferFree returns ERROR_INVALID_PARAMETER (Error Code 87)NetApiBufferFree 返回 ERROR_INVALID_PARAMETER(错误代码 87)
【发布时间】:2026-01-28 10:45:01
【问题描述】:

我一直在开发一个使用 winapi 获取管理员组成员的应用程序。为此,我使用了 NetLocalGroupGetMembers 方法。我的问题是当我尝试释放缓冲区的堆空间时,我从 NetApiBufferFree 方法得到 ERROR_INVALID_PARAMETER (错误代码 87)。我拥有该应用程序的管理员权限。

代码如下:

#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <lm.h>
#include <time.h>
#include <assert.h>

#define SLEEP_TIME 2000
#define OS_GROUP_NAME L"administrators"

void createServiceThread();
DWORD WINAPI mainServiceThread( LPVOID lpParam );
char** getUsersByLocalGroup();
void freeNetApiBuffer(LPVOID buffer);

int localGroupUserCount;

int WriteToLog(char* str)
{
    printf("%s\n", str);
    return 0;
}

int main() 
{ 
    createServiceThread();  
}

void createServiceThread(){
    WriteToLog("Application Started...");
    while(TRUE){
        mainServiceThread(NULL);

        Sleep(SLEEP_TIME);
    }
    WriteToLog("Application Closed...");
}

//-------------------------------------------
// A function that represents Main Service Thread
//-------------------------------------------
DWORD WINAPI mainServiceThread( LPVOID lpParam ) 
{
    time_t startTime;
    time (&startTime);
    char startTimeText[30];
    sprintf(startTimeText, "Service Loop Started %s", ctime(&startTime));
    WriteToLog(startTimeText);
    localGroupUserCount = 0;

    char** localGroupUsers = getUsersByLocalGroup();

    WriteToLog("User not found...");

    time_t endTime;
    time (&endTime);
    char endTimeText[30];
    sprintf(endTimeText, "Service Loop Ended %s", ctime(&endTime));
    WriteToLog(endTimeText);
}

char** getUsersByLocalGroup(){
    WriteToLog("getUsersByLocalGroup started");
    LOCALGROUP_MEMBERS_INFO_3 *pBuf;
    DWORD dwLevel = 3;
    DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
    DWORD dwEntriesRead = 0;
    DWORD dwTotalEntries = 0;
    DWORD dwResumeHandle = 0;
    NET_API_STATUS nStatus;

    WriteToLog("Call NetLocalGroupGetMembers"); 
    nStatus = NetLocalGroupGetMembers(
        NULL,
        OS_GROUP_NAME,
        dwLevel,
        (LPBYTE *) &pBuf,
        dwPrefMaxLen,
        &dwEntriesRead,
        &dwTotalEntries,
        NULL
    );  
//  nStatus = ERROR_SUCCESS;
    WriteToLog("NetLocalGroupGetMembers called");
    //
    // If the call succeeds,
    //
    if (nStatus == ERROR_SUCCESS  || nStatus == ERROR_MORE_DATA)
    {
        DWORD i;
        DWORD dwTotalCount = 0;
        WriteToLog("Correct Status");
        if (pBuf != NULL)
        {
            //
            // Loop through the entries.
            //
            for (i = 0; (i < dwEntriesRead); i++)
            {
                assert(pBuf != NULL);

                if (pBuf == NULL)
                {
                    char bufError[] = "";
                    sprintf(bufError, "An access violation has occurred %d", stderr);
                    WriteToLog(bufError);
                    break;
                }
                LPWSTR userNameOnBuffer = pBuf->lgrmi3_domainandname;
                pBuf++;
                dwTotalCount++;     
            }
            localGroupUserCount = dwTotalCount;
            char totalCount[] = "";
            sprintf(totalCount, "Entries enumerated: %d", dwTotalCount);
            WriteToLog(totalCount); 
        }
        //
        // Otherwise, print the system error.
        //
        else{
        char systemError[] = "";
        sprintf(systemError, "An system error has occurred %d - %d", stderr, nStatus);
        WriteToLog(systemError);
        }
    }
    //
    // Free the allocated buffer.
    //  
    if (pBuf != NULL)
    {
        NET_API_STATUS nBufferFreeStatus = NetApiBufferFree((LPVOID)pBuf);
        if(nBufferFreeStatus == NERR_Success){
            WriteToLog("Succesfully freed buffer");
        }
        else{
            WriteToLog("Error occured freeing buffer");
        }
        pBuf = NULL;
    }
    WriteToLog("getUsersByLocalGroup finished");
    return NULL;
}

【问题讨论】:

    标签: c++ c winapi memory-leaks free


    【解决方案1】:

    在您的循环中,您有pBuf++; 行。这会修改pBuf,这意味着您要释放的值不是分配的值。因此参数无效。

    还有这几行

    char totalCount[] = "";
    sprintf(totalCount, "Entries enumerated: %d", dwTotalCount);
    

    创建堆栈缓冲区溢出,这可能会破坏您的pBuf 变量。几行之后还有另一个例子。

    一般来说,调试方法如下:NetLocalGroupGetMembers 返回后立即设置断点。查看pBuf 中的值并将其写在安全的地方。当您要调用NetApiBufferFree 时设置另一个断点。查看您传递的pBuf 的值。它是否等于您之前记下的值?如果没有,那么你有一个错误。使用调试器找出您传递错误值的原因。

    【讨论】:

    • 我注释掉了pBuf++; 行,但它返回了相同的错误代码。
    • @Masterhead 查看编辑。您没有将与NetLocalGroupGetMembers 返回的相同值传递回NetApiBufferFree。调试器将帮助您找出原因。
    • 你是对的,pBuf 指针由于堆栈缓冲区溢出而发生变化。我修复了它,现在 NetApiBufferFree 可以工作了。感谢您的帮助。