[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.
This commit is contained in:
Whindmar Saksit 2023-12-17 22:11:50 +01:00 committed by GitHub
parent 8f349ab3c2
commit 82c07abf1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 1 deletions

View file

@ -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;
}

View file

@ -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 */