lpFilename [out]
指向接收模块的完全限定路径的缓冲区的指针。如果路径的长度小于nSize参数指定的大小,则函数成功,并将路径作为以null结尾的字符串返回。
如果路径长度超过nSize参数指定的大小,则函数成功,字符串被截断为nSize字符,包括终止空字符。
Windows XP:字符串被截断为nSize字符,并且不会以空值终止。
这是含糊不清的。我是否要解释这个字符串在Windows XP上从不以null结尾?或者,当字符串被截断时,它是否仅以空值终止?
如果有人知道更好的参考资料,或者在某个地方运行Windows XP并且可以简单地测试行为,我将不胜感激。
答案 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;
}