Документы MSDN государство:
lpFilename [out]
Указатель на буфер, который получает полный путь к модулю. Если длина пути меньше размера, указанного параметром nSize, функция завершается успешно и путь возвращается в виде строки с нулевым символом в конце.
Если длина пути превышает размер, указанный параметром nSize, функция завершается успешно, и строка усекается до символов nSize, включая завершающий нулевой символ.
Windows XP: строка усекается до символов nSize и не заканчивается нулем.
Это неоднозначно. Должен ли я интерпретировать это, что строка никогда прекращается в Windows XP? Или это только не заканчивается нулем, когда строка усекается?
Я был бы признателен, если кто-то знает справочную версию, или где-то работает под управлением Windows XP, и может просто проверить поведение.
Я думаю, что вам нужно прочитать эту строку в контексте пункта выше:
Если функция завершается успешно, возвращаемое значение — это длина строки, которая копируется в буфер, в символах, не включая завершающий нулевой символ. Если буфер слишком мал для хранения имени модуля, строка усекается до символов nSize, включая завершающий нулевой символ, функция возвращает nSize, а функция устанавливает для последней ошибки значение ERROR_INSUFFICIENT_BUFFER.
Windows XP: если буфер слишком мал для хранения имени модуля, функция возвращает nSize. Последним кодом ошибки остается ERROR_SUCCESS. Если nSize равно нулю, возвращаемое значение равно нулю, а последний код ошибки — ERROR_SUCCESS.
Если функция не работает, возвращаемое значение равно 0 (ноль). Чтобы получить расширенную информацию об ошибке, вызовите GetLastError.
А затем используйте комбинацию возвращаемого значения и вызова GetLastError (), чтобы определить, есть ли у вас полный путь.
Если у вас есть полный путь (ERROR_SUCCESS
) А ТАКЖЕ return-value == nSize
тогда вы не должны предполагать, что он завершен нулем.
На мой взгляд, это говорит о том, что мы никогда не предполагаем, что оно завершено нулем. Интерфейс сломан. Буфер, который вы посылаете функции, должен быть на один символ больше nSize. Тогда вы можете обнулить.
Начиная с 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;
}
Других решений пока нет …