[PATCH 2/2] kernel32: Implement GetFileMUIInfo.

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


Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/kernel32/tests/resource.c |   7 ++
 dlls/kernelbase/locale.c       | 145 ++++++++++++++++++++++++++++++++-
 2 files changed, 149 insertions(+), 3 deletions(-)

diff --git a/dlls/kernel32/tests/resource.c b/dlls/kernel32/tests/resource.c
index 626645a8979..f8a49990e6b 100644
--- a/dlls/kernel32/tests/resource.c
+++ b/dlls/kernel32/tests/resource.c
@@ -617,6 +617,7 @@ static void test_GetFileMUIInfo(void)
     ret = GetFileMUIInfo(0, path, info, &size);
     ok(!ret, "GetFileMUIInfo should fail\n");
     ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
+    todo_wine
     ok(!size, "got %lu\n", size);
     ok(info->dwSize == sizeof(*info), "got %lu\n", info->dwSize);
     ok(!info->dwVersion, "got %08lx\n", info->dwVersion);
@@ -653,7 +654,9 @@ static void test_GetFileMUIInfo(void)
     full_size = 0;
     SetLastError(0xdeadbeef);
     ret = GetFileMUIInfo(MUI_QUERY_ALL, path, NULL, &full_size);
+    todo_wine
     ok(!ret, "GetFileMUIInfo should fail\n");
+    todo_wine
     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
 
     memset(buf, 0, sizeof(buf));
@@ -666,7 +669,9 @@ static void test_GetFileMUIInfo(void)
     ok(!ret, "GetFileMUIInfo should fail\n");
     ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
     ok(info->dwVersion == 0, "got %08lx\n", info->dwVersion);
+    todo_wine
     ok(info->dwFileType == 0, "got %08lx\n", info->dwFileType);
+    todo_wine
     ok(!memcmp(info->abBuffer, zero, 8), "got %.8s\n", info->abBuffer);
 
     memset(buf, 0, sizeof(buf));
@@ -700,8 +705,10 @@ static void test_GetFileMUIInfo(void)
     ret = GetFileMUIInfo(MUI_QUERY_ALL, path, info, &size);
     ok(!ret, "GetFileMUIInfo should fail\n");
     ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError());
+    todo_wine
     ok(size == 0, "got %08lx\n", size);
     ok(info->dwVersion == 0, "got %08lx\n", info->dwVersion);
+    todo_wine
     ok(info->dwFileType == 0, "got %08lx\n", info->dwFileType);
     ok(!memcmp(info->abBuffer, zero, 8), "got %.8s\n", info->abBuffer);
 
diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c
index 0c20c858a7a..19c4707cec8 100644
--- a/dlls/kernelbase/locale.c
+++ b/dlls/kernelbase/locale.c
@@ -5699,15 +5699,154 @@ done:
 }
 
 
+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;
+
 /******************************************************************************
  *	GetFileMUIInfo   (kernelbase.@)
  */
 BOOL WINAPI /* DECLSPEC_HOTPATCH */ GetFileMUIInfo( DWORD flags, const WCHAR *path,
                                                     FILEMUIINFO *info, DWORD *size )
 {
-    FIXME( "stub: %lu, %s, %p, %p\n", flags, debugstr_w(path), info, size );
-    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
-    return FALSE;
+    HMODULE module;
+    HRSRC rsrc;
+    MUI_RC_CONFIG *rc_cfg;
+    DWORD rc_size;
+
+    TRACE( "(%08lx,%s,%p,%p)\n", flags, debugstr_w(path), info, size );
+
+    if (!size)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
+    if (info)
+    {
+        if (*size < sizeof(FILEMUIINFO))
+        {
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
+        if (*size != info->dwSize || !info->dwVersion)
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return FALSE;
+        }
+    }
+    else if (*size)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
+    module = LoadLibraryExW( path, 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE );
+    if (!module) return FALSE;
+
+    rsrc = FindResourceW( module, MAKEINTRESOURCEW(1), L"MUI" );
+    if (!rsrc)
+    {
+        FreeLibrary( module );
+        return FALSE;
+    }
+
+    rc_cfg = LockResource( LoadResource( module, rsrc ) );
+
+    rc_size = sizeof(*info);
+    if (flags & MUI_QUERY_RESOURCE_TYPES)
+    {
+        rc_size += rc_cfg->dwTypeNameMainSize;
+        rc_size += rc_cfg->dwTypeIDMainSize;
+        rc_size += rc_cfg->dwTypeNameMUISize;
+        rc_size += rc_cfg->dwTypeIDMUISize;
+    }
+    if (flags & MUI_QUERY_LANGUAGE_NAME)
+        rc_size += rc_cfg->dwLanguageNameSize;
+
+    if (info)
+    {
+        char *p = (char *)(info + 1);
+        DWORD offset = sizeof(*info);
+
+        memset( (char *)info + 8, 0, *size - 8 ); /* keep original dwSize/dwVersion */
+
+        if (flags & MUI_QUERY_TYPE)
+            info->dwFileType = rc_cfg->dwFileType;
+
+        if (flags & MUI_QUERY_CHECKSUM)
+        {
+            memcpy( info->pChecksum, rc_cfg->pChecksum, sizeof(info->pChecksum) );
+            memcpy( info->pServiceChecksum, rc_cfg->pServiceChecksum, sizeof(info->pServiceChecksum) );
+        }
+
+        if (*size < rc_size)
+        {
+            FreeLibrary( module );
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
+            return FALSE;
+        }
+
+        if (flags & MUI_QUERY_RESOURCE_TYPES)
+        {
+            info->dwTypeNameMainOffset = offset;
+            memcpy( p, (char *)rc_cfg + rc_cfg->dwTypeNameMainOffset, rc_cfg->dwTypeNameMainSize );
+            p += rc_cfg->dwTypeNameMainSize;
+            offset += rc_cfg->dwTypeNameMainSize;
+
+            info->dwTypeIDMainOffset = offset;
+            info->dwTypeIDMainSize = rc_cfg->dwTypeIDMainSize / sizeof(DWORD);
+            memcpy( p, (char *)rc_cfg + rc_cfg->dwTypeIDMainOffset, rc_cfg->dwTypeIDMainSize );
+            p += rc_cfg->dwTypeIDMainSize;
+            offset += rc_cfg->dwTypeIDMainSize;
+
+            info->dwTypeNameMUIOffset = offset;
+            memcpy( p, (char *)rc_cfg + rc_cfg->dwTypeNameMUIOffset, rc_cfg->dwTypeNameMUISize );
+            p += rc_cfg->dwTypeNameMUISize;
+            offset += rc_cfg->dwTypeNameMUISize;
+
+            info->dwTypeIDMUIOffset = offset;
+            info->dwTypeIDMUISize = rc_cfg->dwTypeIDMUISize / sizeof(DWORD);
+            memcpy( p, (char *)rc_cfg + rc_cfg->dwTypeIDMUIOffset, rc_cfg->dwTypeIDMUISize );
+            p += rc_cfg->dwTypeIDMUISize;
+            offset += rc_cfg->dwTypeIDMUISize;
+        }
+
+        if (flags & MUI_QUERY_LANGUAGE_NAME)
+        {
+            info->dwLanguageNameOffset = offset;
+            memcpy( p, (char *)rc_cfg + rc_cfg->dwLanguageNameOffset, rc_cfg->dwLanguageNameSize );
+        }
+    }
+    else
+        *size = rc_size;
+
+    FreeLibrary( module );
+
+    return TRUE;
 }
 
 
-- 
2.37.1




More information about the wine-devel mailing list