[PATCH 1/2] kernel32/tests: Add some tests for GetFileMUIInfo().

Dmitry Timoshkov dmitry at baikal.ru
Thu Jul 21 09:49:43 CDT 2022


MUI_RC_CONFIG layout is based on the description from
http://hostagebrain.blogspot.com/2015/11/multilingual-user-interface.html

Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/kernel32/tests/resource.c | 235 ++++++++++++++++++++++++++++++++-
 1 file changed, 234 insertions(+), 1 deletion(-)

diff --git a/dlls/kernel32/tests/resource.c b/dlls/kernel32/tests/resource.c
index 6c5bc99c0c5..626645a8979 100644
--- a/dlls/kernel32/tests/resource.c
+++ b/dlls/kernel32/tests/resource.c
@@ -2,6 +2,7 @@
  * Unit test suite for resource functions.
  *
  * Copyright 2006 Mike McCormack
+ * Copyright 2022 Dmitry Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,8 +19,10 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include <windows.h>
+#include <stdarg.h>
 #include <stdio.h>
+#include <assert.h>
+#include <windows.h>
 
 #include "wine/test.h"
 
@@ -520,10 +523,240 @@ static void test_internal_structure(void)
     ok( EndUpdateResourceW( res, TRUE ), "EndUpdateResourceW failed\n");
 }
 
+typedef struct
+{
+    DWORD dwSignature;
+    DWORD dwSize;
+    DWORD dwVersion;
+    DWORD unknown1;
+    DWORD unknown2;
+    DWORD unknown3;
+    DWORD dwFileType;
+    BYTE pServiceChecksum[16];
+    BYTE pChecksum[16];
+    DWORD unknown4[6];
+    DWORD dwTypeNameMainOffset;
+    DWORD dwTypeNameMainSize;
+    DWORD dwTypeIDMainOffset;
+    DWORD dwTypeIDMainSize;
+    DWORD dwTypeNameMUIOffset;
+    DWORD dwTypeNameMUISize;
+    DWORD dwTypeIDMUIOffset;
+    DWORD dwTypeIDMUISize;
+    DWORD unknown5;
+    DWORD unknown6;
+    DWORD dwLanguageNameOffset;
+    DWORD dwLanguageNameSize;
+} MUI_RC_CONFIG;
+
+static void *offset_to_data(void *base, DWORD offset)
+{
+    return (char *)base + offset;
+}
+
+static void test_GetFileMUIInfo(void)
+{
+#define MUI_QUERY_ALL (MUI_QUERY_TYPE | MUI_QUERY_CHECKSUM | MUI_QUERY_LANGUAGE_NAME | MUI_QUERY_RESOURCE_TYPES)
+    static const BYTE zero[8];
+    static const WCHAR path[] = L"urlmon.dll";
+    char buf[1024];
+    HRSRC rsrc;
+    MUI_RC_CONFIG *rc_cfg;
+    char *p1, *p2;
+    FILEMUIINFO *info = (FILEMUIINFO *)buf;
+    DWORD size, full_size;
+    HMODULE module;
+    int ret;
+
+    module = LoadLibraryExW(path, 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE);
+    ok(module != NULL, "LoadLibraryEx error %lu\n", GetLastError());
+    rsrc = FindResourceW(module, MAKEINTRESOURCEW(1), L"MUI");
+    todo_wine
+    ok(rsrc != 0, "MUI resource not found\n");
+    if (!rsrc)
+    {
+        skip("MUI resource not found\n");
+        FreeLibrary(module);
+        return;
+    }
+    rc_cfg = LockResource(LoadResource(module, rsrc));
+    ok(rc_cfg->dwVersion == MAKELONG(0,1), "got %08lx\n", rc_cfg->dwVersion);
+    ok(rc_cfg->dwFileType == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN, "got %08lx\n", rc_cfg->dwFileType);
+
+    SetLastError(0xdeadbeef);
+    ret = GetFileMUIInfo(0, path, NULL, NULL);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
+
+    info->dwSize = sizeof(*info);
+    SetLastError(0xdeadbeef);
+    ret = GetFileMUIInfo(0, path, info, NULL);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
+
+    size = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = GetFileMUIInfo(MUI_QUERY_ALL, path, NULL, &size);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
+
+    size = 0;
+    ret = GetFileMUIInfo(0, path, NULL, &size);
+    ok(ret, "GetFileMUIInfo error %lu\n", GetLastError());
+    ok(size == sizeof(FILEMUIINFO), "got %lu bytes\n", size);
+
+    memset(info, 0, sizeof(*info));
+    size = info->dwSize = sizeof(*info) - 1;
+    SetLastError(0xdeadbeef);
+    ret = GetFileMUIInfo(0, path, info, &size);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
+
+    memset(info, 0, sizeof(*info));
+    size = info->dwSize = sizeof(*info);
+    ret = GetFileMUIInfo(0, path, info, &size);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
+    ok(!size, "got %lu\n", size);
+    ok(info->dwSize == sizeof(*info), "got %lu\n", info->dwSize);
+    ok(!info->dwVersion, "got %08lx\n", info->dwVersion);
+
+    memset(info, 0, sizeof(*info));
+    size = info->dwSize = sizeof(*info);
+    info->dwVersion = MUI_FILEINFO_VERSION;
+    ret = GetFileMUIInfo(0, path, info, &size);
+    ok(ret, "GetFileMUIInfo error %lu\n", GetLastError());
+
+    memset(buf, 0, sizeof(buf));
+    size = info->dwSize = 1;
+    info->dwVersion = MUI_FILEINFO_VERSION;
+    info->dwFileType = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = GetFileMUIInfo(0, path, info, &size);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
+    ok(info->dwVersion == MUI_FILEINFO_VERSION, "got %08lx\n", info->dwVersion);
+    ok(info->dwFileType == 0xdeadbeef, "got %08lx\n", info->dwFileType);
+
+    memset(buf, 0, sizeof(buf));
+    info->dwSize = sizeof(*info);
+    size = sizeof(*info) + 1;
+    info->dwVersion = MUI_FILEINFO_VERSION;
+    info->dwFileType = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = GetFileMUIInfo(0, path, info, &size);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
+    ok(info->dwVersion == MUI_FILEINFO_VERSION, "got %08lx\n", info->dwVersion);
+    ok(info->dwFileType == 0xdeadbeef, "got %08lx\n", info->dwFileType);
+
+    full_size = 0;
+    SetLastError(0xdeadbeef);
+    ret = GetFileMUIInfo(MUI_QUERY_ALL, path, NULL, &full_size);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
+
+    memset(buf, 0, sizeof(buf));
+    info->dwSize = size = sizeof(*info);
+    info->dwVersion = 0;
+    info->dwFileType = 0xdeadbeef;
+    memcpy(info->abBuffer, "deadbeef", 8);
+    SetLastError(0xdeadbeef);
+    ret = GetFileMUIInfo(MUI_QUERY_ALL, path, info, &size);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
+    ok(info->dwVersion == 0, "got %08lx\n", info->dwVersion);
+    ok(info->dwFileType == 0, "got %08lx\n", info->dwFileType);
+    ok(!memcmp(info->abBuffer, zero, 8), "got %.8s\n", info->abBuffer);
+
+    memset(buf, 0, sizeof(buf));
+    info->dwSize = size = sizeof(*info);
+    info->dwVersion = 0xdeadbeef;
+    info->dwFileType = 0xdeadbeef;
+    memcpy(info->abBuffer, "deadbeef", 8);
+    SetLastError(0xdeadbeef);
+    ret = GetFileMUIInfo(MUI_QUERY_ALL, path, info, &size);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
+    ok(info->dwVersion == 0xdeadbeef, "got %08lx\n", info->dwVersion);
+    ok(info->dwFileType == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN, "got %08lx\n", info->dwFileType);
+    ok(!memcmp(info->abBuffer, zero, 8), "got %.8s\n", info->abBuffer);
+
+    memset(buf, 0, sizeof(buf));
+    info->dwSize = size = sizeof(*info);
+    info->dwVersion = 0xdeadbeef;
+    info->dwFileType = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = GetFileMUIInfo(MUI_QUERY_ALL, path, info, &size);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
+    ok(info->dwVersion == 0xdeadbeef, "got %08lx\n", info->dwVersion);
+    ok(info->dwFileType == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN, "got %08lx\n", info->dwFileType);
+
+    memset(buf, 0, sizeof(buf));
+    info->dwSize = size = full_size;
+    info->dwVersion = 0;
+    info->dwFileType = 0xdeadbeef;
+    ret = GetFileMUIInfo(MUI_QUERY_ALL, path, info, &size);
+    ok(!ret, "GetFileMUIInfo should fail\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
+    ok(size == 0, "got %08lx\n", size);
+    ok(info->dwVersion == 0, "got %08lx\n", info->dwVersion);
+    ok(info->dwFileType == 0, "got %08lx\n", info->dwFileType);
+    ok(!memcmp(info->abBuffer, zero, 8), "got %.8s\n", info->abBuffer);
+
+    memset(buf, 0, sizeof(buf));
+    info->dwSize = size = full_size;
+    info->dwVersion = MUI_FILEINFO_VERSION;
+    info->dwFileType = 0xdeadbeef;
+    ret = GetFileMUIInfo(MUI_QUERY_ALL, path, info, &size);
+    ok(ret || broken(GetLastError() == ERROR_INSUFFICIENT_BUFFER) /* Some Win10 versions */, "GetFileMUIInfo error %lu\n", GetLastError());
+    while (!ret) /* Try to recover from Win10 breakage */
+    {
+        size += 2;
+        assert(size <= sizeof(buf));
+        info->dwSize = size;
+        ret = GetFileMUIInfo(MUI_QUERY_ALL, path, info, &size);
+    }
+    ok(info->dwVersion == MUI_FILEINFO_VERSION, "got %08lx\n", info->dwVersion);
+    ok(info->dwFileType == MUI_FILETYPE_LANGUAGE_NEUTRAL_MAIN, "got %08lx\n", info->dwFileType);
+
+    ok(!memcmp(info->pChecksum, rc_cfg->pChecksum, 16), "Checksum doesn't match\n");
+    ok(!memcmp(info->pServiceChecksum, rc_cfg->pServiceChecksum, 16), "ServiceChecksum doesn't match\n");
+
+    p1 = offset_to_data(rc_cfg, rc_cfg->dwLanguageNameOffset);
+    p2 = offset_to_data(info, info->dwLanguageNameOffset);
+    ok(!memcmp(p1, p2, rc_cfg->dwLanguageNameSize), "LanguageName doesn't match\n");
+
+    p1 = offset_to_data(rc_cfg, rc_cfg->dwTypeNameMainOffset);
+    p2 = offset_to_data(info, info->dwTypeNameMainOffset);
+    ok(!memcmp(p1, p2, rc_cfg->dwTypeNameMainSize), "TypeNameMain doesn't match\n");
+
+    p1 = offset_to_data(rc_cfg, rc_cfg->dwTypeIDMainOffset);
+    p2 = offset_to_data(info, info->dwTypeIDMainOffset);
+    ok(rc_cfg->dwTypeIDMainSize == info->dwTypeIDMainSize * sizeof(DWORD), "dwTypeIDMainSize %#08lx != %08lx\n",
+       rc_cfg->dwTypeIDMainSize, info->dwTypeIDMainSize);
+    ok(!memcmp(p1, p2, rc_cfg->dwTypeIDMainSize), "TypeIDMain doesn't match\n");
+
+    p1 = offset_to_data(rc_cfg, rc_cfg->dwTypeIDMUIOffset);
+    p2 = offset_to_data(info, info->dwTypeIDMUIOffset);
+    ok(rc_cfg->dwTypeIDMUISize == info->dwTypeIDMUISize * sizeof(DWORD), "dwTypeIDMUISize %#08lx != %08lx\n",
+       rc_cfg->dwTypeIDMUISize, info->dwTypeIDMUISize);
+    ok(!memcmp(p1, p2, rc_cfg->dwTypeIDMUISize), "TypeIDMUI doesn't match\n");
+
+    p1 = offset_to_data(rc_cfg, rc_cfg->dwTypeNameMUIOffset);
+    p2 = offset_to_data(info, info->dwTypeNameMUIOffset);
+    ok(!memcmp(p1, p2, rc_cfg->dwTypeNameMUISize), "TypeNameMUI doesn't match\n");
+
+    FreeLibrary(module);
+}
+
 START_TEST(resource)
 {
     DWORD i;
 
+    test_GetFileMUIInfo();
+
     DeleteFileA( filename );
     update_missing_exe();
 
-- 
2.37.1




More information about the wine-devel mailing list