[PATCH v2 0/3] MR10291: Fix GetModuleFileName string termination
After Windows XP the string termination behavior of GetModuleFileName was changed to always terminate the path returned, even if the buffer is insufficient to contain the null terminator. -- v2: fix compilation error https://gitlab.winehq.org/wine/wine/-/merge_requests/10291
From: Trent Waddington <trent.waddington@tensorworks.com.au> --- dlls/kernel32/tests/loader.c | 61 ++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index 529b9de870d..dca4a253abd 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -1552,6 +1552,66 @@ static void test_filenames(void) DeleteFileA( long_path ); } +static void test_getmodulefilename_string_termination(void) +{ + WCHAR dll_name[MAX_PATH]; + int dll_name_len, i; + + dll_name[0] = 0; + GetModuleFileNameW(NULL, dll_name, MAX_PATH); + dll_name_len = wcslen(dll_name); + ok(dll_name_len > 0, "can't get path for NULL module\n"); + ok(dll_name_len < MAX_PATH, "unterminated path for NULL module\n"); + + memset(dll_name, 0x9, sizeof(dll_name)); + GetModuleFileNameW(NULL, dll_name, dll_name_len); + for (i = 0; i < MAX_PATH && dll_name[i]; i++) + ; + ok(i > 0, "can't get path for NULL module with short buffer\n"); + ok(i < MAX_PATH, "unterminated path for NULL module with short buffer\n"); + if (i < MAX_PATH) + ok(i == dll_name_len - 1, "incorrect path termination for NULL module with short buffer\n"); + + { + IMAGE_NT_HEADERS nt_header = nt_header_template; + char dll_name_a[MAX_PATH]; + HMODULE mod; + + nt_header.FileHeader.NumberOfSections = 1; + nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); + + nt_header.OptionalHeader.SectionAlignment = page_size; + nt_header.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; + nt_header.OptionalHeader.FileAlignment = page_size; + nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER); + nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + page_size; + + create_test_dll( &dos_header, sizeof(dos_header), &nt_header, dll_name_a ); + mod = LoadLibraryA( dll_name_a ); + ok(mod, "can't load test dll\n"); + if (mod) + { + dll_name[0] = 0; + GetModuleFileNameW(mod, dll_name, MAX_PATH); + dll_name_len = wcslen(dll_name); + ok(dll_name_len > 0, "can't get path for test module\n"); + ok(dll_name_len < MAX_PATH, "unterminated path for test module\n"); + + memset(dll_name, 0x9, sizeof(dll_name)); + GetModuleFileNameW(mod, dll_name, dll_name_len); + for (i = 0; i < MAX_PATH && dll_name[i]; i++) + ; + ok(i > 0, "can't get path for test module with short buffer\n"); + ok(i < MAX_PATH, "unterminated path for test module with short buffer\n"); + if (i < MAX_PATH) + ok(i == dll_name_len - 1, "incorrect path termination for test module with short buffer\n"); + + FreeLibrary( mod ); + } + DeleteFileA(dll_name_a); + } +} + /* Verify linking style of import descriptors */ static void test_ImportDescriptors(void) { @@ -4859,6 +4919,7 @@ START_TEST(loader) } test_filenames(); + test_getmodulefilename_string_termination(); test_ResolveDelayLoadedAPI(); test_ImportDescriptors(); test_section_access(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10291
From: Trent Waddington <trent.waddington@tensorworks.com.au> --- dlls/kernelbase/loader.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c index f4e1ca2e23a..2a2e7fcc35d 100644 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -308,7 +308,6 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetModuleFileNameW( HMODULE module, LPWSTR filena { len = min( size, win16_tib->exe_name->Length / sizeof(WCHAR) ); memcpy( filename, win16_tib->exe_name->Buffer, len * sizeof(WCHAR) ); - if (len < size) filename[len] = 0; goto done; } @@ -319,6 +318,10 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetModuleFileNameW( HMODULE module, LPWSTR filena SetLastError( RtlNtStatusToDosError( status )); done: TRACE( "%s\n", debugstr_wn(filename, len) ); + if (len < size) + filename[len] = 0; + else if (size > 0) + filename[size - 1] = 0; return len; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10291
From: Trent Waddington <trent.waddington@tensorworks.com.au> --- dlls/kernel32/tests/loader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index dca4a253abd..15adb42b89f 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -1588,8 +1588,8 @@ static void test_getmodulefilename_string_termination(void) create_test_dll( &dos_header, sizeof(dos_header), &nt_header, dll_name_a ); mod = LoadLibraryA( dll_name_a ); - ok(mod, "can't load test dll\n"); - if (mod) + ok(mod != NULL, "can't load test dll\n"); + if (mod != NULL) { dll_name[0] = 0; GetModuleFileNameW(mod, dll_name, MAX_PATH); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10291
participants (2)
-
Trent Waddington -
Trent Waddington (@trent.waddington)