You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

长目录路径下SetupGetInfFileList返回ERROR_INSUFFICIENT_BUFFER的问题咨询

长目录路径下SetupGetInfFileList返回ERROR_INSUFFICIENT_BUFFER的解决方法

核心问题定位

从当前代码运行表现(第一次调用就返回122错误、RequiredSize返回0)可以拆解出三个叠加的问题:

  • 没有把缓冲区探测阶段返回的ERROR_INSUFFICIENT_BUFFER(错误码122)识别为预期行为,直接被通用错误分支拦截,导致拿不到接口返回的缓冲区大小值
  • 旧版SetupAPI对超过MAX_PATH长度的长路径支持不完善,无法正确计算需要的缓冲区长度,就会出现RequiredSize返回0的异常表现
  • 代码中存在变量名不匹配的隐患:分配内存时引用的dwRequiredSize和前面定义的RequiredSize不是同一个变量,后续运行还会触发其他异常

具体Workaround实现

1. 修正第一次调用的错误处理逻辑

调整错误分支的判断逻辑,单独识别缓冲区不足的预期返回,不要直接抛出通用错误码:

TCHAR *aBuffer = NULL;
DWORD BufferSize = 0, RequiredSize = 0;
DWORD lastError = 0;

// 第一次调用做缓冲区探测
BOOL bError = SetupGetInfFileList(DirectoryPath, INF_STYLE_WIN4, NULL, BufferSize, &RequiredSize);
lastError = GetLastError();

if (!bError) { 
    if (lastError == ERROR_ACCESS_DENIED) {
        return RESULT2(ERR_SUCCESS);
    }
    // 关键:单独识别ERROR_INSUFFICIENT_BUFFER(122),不走到通用错误分支
    if (lastError != ERROR_INSUFFICIENT_BUFFER) {
        return RESULT2(ERR_INI_FILELIST);
    }
    // 兼容长路径下RequiredSize返回0的异常,设置兜底初始大小
    if (RequiredSize == 0) {
        RequiredSize = MAX_PATH * 4;
    }
}

2. 对超长路径做长路径前缀兼容处理

旧版SetupAPI没有开启长路径感知时,无法识别超过MAX_PATH的目录路径,需要手动给路径补上长路径标记,绕过路径长度校验:

TCHAR longDirBuffer[MAX_PATH * 4] = {0};
// 仅当路径长度接近MAX_PATH、且没有已带长路径前缀时做处理
if (_tcslen(DirectoryPath) >= MAX_PATH && _tcsncmp(DirectoryPath, _T("\\\\?\\"), 4) != 0) {
    // UNC网络路径的特殊前缀处理
    if (_tcsncmp(DirectoryPath, _T("\\\\"), 2) == 0) {
        _stprintf_s(longDirBuffer, _countof(longDirBuffer), _T("\\\\?\\UNC\\%s"), DirectoryPath + 2);
    } else {
        // 本地路径的常规长路径前缀
        _stprintf_s(longDirBuffer, _countof(longDirBuffer), _T("\\\\?\\%s"), DirectoryPath);
    }
    // 后续全部用兼容处理后的路径做接口入参
    DirectoryPath = longDirBuffer;
}

3. 修正内存分配与第二次调用的传值逻辑

匹配变量名的同时,针对长路径下可能出现的缓冲区大小不准的问题,加上兜底重试机制:

// 修正变量名不匹配问题,按TCHAR单元计算分配大小
aBuffer = (TCHAR *)LocalAlloc(LPTR, RequiredSize * sizeof(TCHAR));
if (aBuffer == NULL) {
    return RESULT2(ERROR_MEMORY_EXCEPTION);
}

// BufferSize需要传入缓冲区的TCHAR数量,和接口要求的参数粒度匹配
BufferSize = RequiredSize;

// 第二次调用传入实际分配的缓冲区
BOOL aError = SetupGetInfFileList(DirectoryPath, INF_STYLE_WIN4, aBuffer, BufferSize, NULL);
if (!aError) {
    DWORD opError = GetLastError();
    // 如果第二次调用还是缓冲区不足,按2倍扩容重试,最多重试2次避免死循环
    int retryCount = 0;
    while (opError == ERROR_INSUFFICIENT_BUFFER && retryCount < 2) {
        LocalFree(aBuffer);
        aBuffer = NULL;
        BufferSize *= 2;
        aBuffer = (TCHAR *)LocalAlloc(LPTR, BufferSize * sizeof(TCHAR));
        if (aBuffer == NULL) {
            return RESULT2(ERROR_MEMORY_EXCEPTION);
        }
        aError = SetupGetInfFileList(DirectoryPath, INF_STYLE_WIN4, aBuffer, BufferSize, NULL);
        if (aError) {
            break;
        }
        opError = GetLastError();
        retryCount++;
    }
    // 超过重试次数后再抛出通用错误
    if (!aError) {
        return RESULT2(ERR_INI_FILELIST);
    }
}

内容的提问来源于stack exchange,提问作者EnZO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.23 10:54:04