Signed-off-by: Dmitry Timoshkov <dmitry(a)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