Open strangebug opened 4 years ago
@daurnimator pointed out that we shouldn't strip the prefix \??\
because it allows support for NTFS long filename.
Unfortunately the function LoadLibraryW
does not support this syntax, in order to pass long filename to that function we need to use the prefix \\?\
.
Excerpt from the documentation, the full version is available here.
The Windows API has many functions that also have Unicode versions to permit an extended-length path for a maximum total path length of 32,767 characters. This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function (this value is commonly 255 characters). To specify an extended-length path, use the "\\?\" prefix. For example, "\\?\D:\very long path".
Here a simple code to demonstrate the issue
// compile with: cl main.cpp /link ole32.lib
#include <stdio.h>
#include <windows.h>
DWORD TryLoadLibrary(LPCWSTR lpLibFileName) {
HMODULE module = LoadLibraryW(lpLibFileName);
DWORD err_code = GetLastError();
if (err_code == 0) {
FreeLibrary(module);
}
return err_code;
}
int main() {
LPCWSTR path = L"D:\\devel\\SDL2-2.0.12\\lib\\x64\\SDL2.dll";
LPCWSTR path_with_nt_prefix = L"\\??\\D:\\devel\\SDL2-2.0.12\\lib\\x64\\SDL2.dll";
LPCWSTR path_with_prefix = L"\\\\?\\D:\\devel\\SDL2-2.0.12\\lib\\x64\\SDL2.dll";
DWORD err_code;
err_code = TryLoadLibrary(path);
wprintf_s(L"LoadLibraryW( %s ) then GetLastError: %d\n", path, int(err_code));
err_code = TryLoadLibrary(path_with_nt_prefix);
wprintf_s(L"LoadLibraryW( %s ) then GetLastError: %d\n", path_with_nt_prefix, int(err_code));
err_code = TryLoadLibrary(path_with_prefix);
wprintf_s(L"LoadLibraryW( %s ) then GetLastError: %d\n", path_with_prefix, int(err_code));
}
This code ouput the following
LoadLibraryW( D:\devel\SDL2-2.0.12\lib\x64\SDL2.dll ) then GetLastError: 0
LoadLibraryW( \??\D:\devel\SDL2-2.0.12\lib\x64\SDL2.dll ) then GetLastError: 126
LoadLibraryW( \\?\D:\devel\SDL2-2.0.12\lib\x64\SDL2.dll ) then GetLastError: 0
Just for posterity, here's a link to LoadLibraryExW
implemented in ReactOS which might be useful when we move from kernel32.LoadLibraryW
to our own wrapper of NT syscalls which will also fix this issue: LoadLibraryExW.
Windows only,
WindowsDynLib.openW
assumes that the path will start with \??\. This prevents loading of dll using relative path or the module name.All the following forms should work
But I get the following error
Zig: 0.6.0+3aa259d11 Platform: Windows 10 Pro See: lib/std/dynamic_library.zig