https://git.reactos.org/?p=reactos.git;a=commitdiff;h=82c07abf1ab070208d3b8…
commit 82c07abf1ab070208d3b83bb0f628caef41275da
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Sun Dec 17 22:11:50 2023 +0100
Commit: GitHub <noreply(a)github.com>
CommitDate: Sun Dec 17 22:11:50 2023 +0100
[USER32] Support loading icons from data file module (#6065)
GetModuleFileName() fails on LOAD_LIBRARY_AS_DATAFILE causing LoadImage to fail.
Use a fake filename for LR_SHARED (with same format as Windows).
This may not be a good design, but it does match Windows' behaviour.
+ Added test.
---
modules/rostests/apitests/user32/LoadImage.c | 47 ++++++++++++++++++++++++++++
win32ss/user/user32/windows/cursoricon.c | 16 +++++++++-
2 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/modules/rostests/apitests/user32/LoadImage.c
b/modules/rostests/apitests/user32/LoadImage.c
index 64af37325d2..f46e4be7846 100644
--- a/modules/rostests/apitests/user32/LoadImage.c
+++ b/modules/rostests/apitests/user32/LoadImage.c
@@ -1,6 +1,50 @@
#include "precomp.h"
+static void test_LoadImage_DataFile(void)
+{
+ static const struct
+ {
+ int result;
+ LPCWSTR file;
+ int res_id;
+ UINT lr;
+ BOOL same_handle;
+ BOOL after_unload; /* LR_SHARED stays valid */
+ }
+ tests[] =
+ {
+ { 1, L"shell32.dll", 2, 0, 0, 0 },
+ { 1, L"shell32.dll", 2, LR_SHARED, 1, 1 },
+ { 0, L"shell32.dll", 0xfff0, 0, 1, 0 }, /* Icon should not
exist */
+ { 1, L"regedit.exe", 100, 0, 0, 0 },
+ { 1, L"regedit.exe", 100, LR_SHARED, 1, 1 }
+ };
+
+ SIZE_T i;
+ for (i = 0; i < ARRAY_SIZE(tests); ++i)
+ {
+ HANDLE handle1, handle2;
+ HMODULE hMod = LoadLibraryExW(tests[i].file, NULL, LOAD_LIBRARY_AS_DATAFILE);
+ if (!((SIZE_T)hMod & 3))
+ {
+ skip("Could not load library as datafile %ls\n", tests[i].file);
+ continue;
+ }
+
+ handle1 = LoadImage(hMod, MAKEINTRESOURCE(tests[i].res_id), IMAGE_ICON, 0, 0,
tests[i].lr);
+ ok(!!handle1 == !!tests[i].result, "Failed to load %ls,-%d from %p\n",
tests[i].file, tests[i].res_id, hMod);
+
+ handle2 = LoadImage(hMod, MAKEINTRESOURCE(tests[i].res_id), IMAGE_ICON, 0, 0,
tests[i].lr);
+ ok(!!(handle1 == handle2) == !!tests[i].same_handle, "Shared handles
don't match\n");
+
+ FreeLibrary(hMod);
+
+ handle1 = LoadImage(hMod, MAKEINTRESOURCE(tests[i].res_id), IMAGE_ICON, 0, 0,
tests[i].lr);
+ ok(!!handle1 == !!tests[i].after_unload, "LR_%x handle should %sload after
FreeLibrary\n", tests[i].lr, tests[i].after_unload ? "" : "not
");
+ }
+}
+
START_TEST(LoadImage)
{
char path[MAX_PATH];
@@ -77,6 +121,9 @@ START_TEST(LoadImage)
DeleteObject(ii.hbmMask);
if(ii.hbmColor) DeleteObject(ii.hbmColor);
+ /* LOAD_LIBRARY_AS_DATAFILE */
+ test_LoadImage_DataFile();
+
return;
}
diff --git a/win32ss/user/user32/windows/cursoricon.c
b/win32ss/user/user32/windows/cursoricon.c
index 1f6b71714aa..a3f8a48602e 100644
--- a/win32ss/user/user32/windows/cursoricon.c
+++ b/win32ss/user/user32/windows/cursoricon.c
@@ -1454,7 +1454,21 @@ CURSORICON_LoadImageW(
RtlInitUnicodeString(&ustrRsrc, lpszName);
}
- if(hinst)
+ if(LDR_IS_RESOURCE(hinst))
+ {
+ /* We don't have a real module for GetModuleFileName, construct a fake name
instead.
+ * GetIconInfoEx reveals the name used by Windows. */
+ LPCWSTR fakeNameFmt = sizeof(void*) > 4 ? L"\x01%016IX" :
L"\x01%08IX";
+ ustrModule.MaximumLength = 18 * sizeof(WCHAR);
+ ustrModule.Buffer = HeapAlloc(GetProcessHeap(), 0, ustrModule.MaximumLength);
+ if (!ustrModule.Buffer)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+ ustrModule.Length = wsprintfW(ustrModule.Buffer, fakeNameFmt, hinst) *
sizeof(WCHAR);
+ }
+ else if(hinst)
{
DWORD size = MAX_PATH;
/* Get the module name string */