https://git.reactos.org/?p=reactos.git;a=commitdiff;h=82c07abf1ab070208d3b83bb0f628caef41275da

commit 82c07abf1ab070208d3b83bb0f628caef41275da
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Sun Dec 17 22:11:50 2023 +0100
Commit:     GitHub <nore...@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 */

Reply via email to