GetModuleFileName

时间:2016-07-13 12:43:58

标签: c++ winapi windows-xp getmodulefilename

MSDN docs州:

  

lpFilename [out]

     

指向接收模块的完全限定路径的缓冲区的指针。如果路径的长度小于nSize参数指定的大小,则函数成功,并将路径作为以null结尾的字符串返回。

     

如果路径长度超过nSize参数指定的大小,则函数成功,字符串被截断为nSize字符,包括终止空字符。

     

Windows XP:字符串被截断为nSize字符,并且不会以空值终止。

这是含糊不清的。我是否要解释这个字符串在Windows XP上从不以null结尾?或者,当字符串被截断时,它是否仅以空值终止?

如果有人知道更好的参考资料,或者在某个地方运行Windows XP并且可以简单地测试行为,我将不胜感激。

1 个答案:

答案 0 :(得分:1)

我认为你需要在上面的段落中阅读该行:

  

如果函数成功,则返回值是复制到缓冲区的字符串的长度,以字符为单位,不包括终止空字符。如果缓冲区太小而无法容纳模块名称,则字符串将截断为nSize字符(包括终止空字符),函数返回nSize,函数将最后一个错误设置为ERROR_INSUFFICIENT_BUFFER。

     

Windows XP:如果缓冲区太小而无法容纳模块名称,则该函数返回nSize。最后一个错误代码仍然是ERROR_SUCCESS。如果nSize为零,则返回值为零,最后一个错误代码为ERROR_SUCCESS。

     

如果函数失败,则返回值为0(零)。要获取扩展错误信息,请调用GetLastError。

然后使用返回值和对GetLastError()的调用的组合来确定您是否有完整的路径。

如果你有一个完整的路径(ERROR_SUCCESS)和return-value == nSize,那么你不应该假设它是以空的方式终止的。

在我看来,这主张从不假设它是以空终止的。界面坏了。发送给函数的缓冲区应该比nSize大一个char。然后你可以空终止。

从c ++ 11开始,std::basic_string<TCHAR>保证附加一个尾随零,所以这样的事情应该做得很好:

std::basic_string<TCHAR> better_get_module_filename(HMODULE hModule)
{
    std::basic_string<TCHAR> result(128, 0);
    DWORD err = ERROR_SUCCESS;
    do {
        auto actual = GetModuleFileName(hModule, std::addressof(result[0]), result.size());
        err = GetLastError();
        if (actual == 0) {
            throw "error of choice, wrapping err";
        }
        result.resize(actual);
    } while(err == ERROR_INSUFFICIENT_BUFFER);
    return result;
}