From: Fabian Maurer Subject: [PATCH] user32: LoadImage should search image in PE directory, not the working directory Message-Id: <20181124192514.20091-1-dark.shadow4@web.de> Date: Sat, 24 Nov 2018 20:25:14 +0100 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46186 Signed-off-by: Fabian Maurer --- dlls/user32/cursoricon.c | 15 ++++++++- dlls/user32/tests/cursoricon.c | 56 ++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index f11f5e45ed..4d803e7818 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -3039,11 +3039,24 @@ HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type, INT desiredx, INT desiredy, UINT loadflags ) { int depth; + WCHAR path[MAX_PATH]; TRACE_(resource)("(%p,%s,%d,%d,%d,0x%08x)\n", hinst,debugstr_w(name),type,desiredx,desiredy,loadflags); - if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED; + if (loadflags & LR_LOADFROMFILE) { + loadflags &= ~LR_SHARED; + + /* Relative paths are relative to the PE directory - not the current working directory */ + if (name != NULL && lstrlenW(name) > 2 && name[0] != '\\' && name[1] != ':') { + WCHAR *part_filename; + GetModuleFileNameW(hinst, path, ARRAY_SIZE(path)); + part_filename = strrchrW(path, '\\') + 1; + *part_filename = '\0'; + strcatW(path, name); + name = path; + } + } switch (type) { case IMAGE_BITMAP: return BITMAP_Load( hinst, name, desiredx, desiredy, loadflags ); diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index 8404ee71ab..a4af988720 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -1203,6 +1203,59 @@ static void create_ico_file(const char *filename, const test_icon_entries_t *tes HeapFree(GetProcessHeap(), 0, buf); } +static void test_LoadImageWorkingDirectory(void) +{ + char working_dir[MAX_PATH]; + char temp_dir[MAX_PATH]; + DWORD bytes_written; + HANDLE handle; + BOOL ret; + static const test_icon_entries_t icon_desc = {32, 32}; + + GetCurrentDirectoryA(ARRAY_SIZE(working_dir), working_dir); + GetTempPathA(ARRAY_SIZE(temp_dir), temp_dir); + + strcat(temp_dir, "wine-test-dir"); + + CreateDirectoryA(temp_dir, NULL); + + /* Create Files */ + create_ico_file("icon.ico", &icon_desc, 1); + + handle = CreateFileA("test.bmp", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + ok(handle != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError()); + ret = WriteFile(handle, bmpimage, sizeof(bmpimage), &bytes_written, NULL); + ok(ret && bytes_written == sizeof(bmpimage), "Test file created improperly.\n"); + CloseHandle(handle); + + SetCurrentDirectoryA(temp_dir); + + /* Test cursor */ + handle = LoadImageA(NULL, "icon.ico", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE); + ok(handle != NULL, "LoadImage() failed.\n"); + + ret = DestroyCursor(handle); + ok(ret, "DestroyCusor failed: %d\n", GetLastError()); + + /* Test image */ + handle = LoadImageA(NULL, "test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + ok(handle != NULL, "LoadImageA failed.\n"); + + ret = DeleteObject(handle); + ok(ret, "DeleteObject failed: %d\n", GetLastError()); + + /* Cleanup */ + SetCurrentDirectoryA(working_dir); + + ret = DeleteFileA("test.bmp"); + ok(ret, "DeleteFileA failed: %d\n", GetLastError()); + ret = DeleteFileA("icon.ico"); + ok(ret, "RemoveDirectoryA failed: %d\n", GetLastError()); + + ret = RemoveDirectoryA(temp_dir); + ok(ret, "RemoveDirectoryA failed: %d\n", GetLastError()); +} + static void test_LoadImage(void) { HANDLE handle; @@ -1326,6 +1379,9 @@ static void test_LoadImage(void) bitmap_header->biSize = sizeof(BITMAPINFOHEADER); test_LoadImageFile("Cursor (invalid dwDIBOffset)", invalid_dwDIBOffset, sizeof(invalid_dwDIBOffset), "cur", 0); + + /* Test if images are properly loaded - from executable directory instead of current working directory */ + test_LoadImageWorkingDirectory(); } static void test_CreateIconFromResource(void) -- 2.19.2