The utility muirct.exe for some reason accesses the opaque HANDLE that is returned by BeginUpdateResource, it assumes a certain structure in which (on 32bit systems) there is a pointer to the wide repesentation of the file name in offset 0x18 (0x30 on 64bit).
Refer to: muirct!BldToolsEndUpdateResourceW called from muirct!CopyChecksumToFile
Sample execution: MUIRCT.EXE -c "ui.exe" -e "de-DE\ui.exe.mui"
Signed-off-by: Jon Doron arilou@gmail.com --- dlls/kernel32/resource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/resource.c b/dlls/kernel32/resource.c index 73f3cca363..59bc7a8cdc 100644 --- a/dlls/kernel32/resource.c +++ b/dlls/kernel32/resource.c @@ -635,7 +635,8 @@ DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
typedef struct { - LPWSTR pFileName; + void *Reserved[6]; + LPWSTR pFileName; /* Must be in offset 0x18 on 32bit and 0x30 on 64bit */ BOOL bDeleteExistingResources; struct list root; } QUEUEDUPDATES;
For some reason muirct.exe is aware of the opaque structure used by BeginUpdateResource, it access the filename field of the opaque structure during it's processing.
MS documentation for the muirct utility: https://docs.microsoft.com/en-us/windows/desktop/intl/resource-utilities
Sample execution: MUIRCT.EXE -c "ui.exe" -e "de-DE\ui.exe.mui"
Signed-off-by: Jon Doron arilou@gmail.com --- dlls/kernel32/tests/resource.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/dlls/kernel32/tests/resource.c b/dlls/kernel32/tests/resource.c index 74066cfba3..87a49e209e 100644 --- a/dlls/kernel32/tests/resource.c +++ b/dlls/kernel32/tests/resource.c @@ -24,6 +24,7 @@ #include "wine/test.h"
static const char filename[] = "test_.exe"; +static const WCHAR filenameW[] = {'t','e','s','t','_','.','e','x','e',0}; static DWORD GLE;
enum constants { @@ -463,6 +464,38 @@ static void test_find_resource(void) ok( GetLastError() == ERROR_RESOURCE_LANG_NOT_FOUND, "wrong error %u\n", GetLastError() ); }
+struct list +{ + struct list *next; + struct list *prev; +}; + +typedef struct +{ + void *Reserved[6]; + LPWSTR pFileName; /* Must be in offset 0x18 on 32bit and 0x30 on 64bit */ + BOOL bDeleteExistingResources; + struct list root; +} QUEUEDUPDATES; + +static void test_resource_internal_structure_offsets(void) +{ + HANDLE res; + QUEUEDUPDATES *res_data; + WCHAR *res_filenameW; + + res = BeginUpdateResourceW( (PWCHAR)filenameW, FALSE ); + ok( res != NULL, "BeginUpdateResourceW failed\n" ); + res_data = (QUEUEDUPDATES *)GlobalLock(res); + ok( res_data != NULL, "GlobalLock failed\n" ); + res_filenameW = (PWCHAR)GlobalLock( (HGLOBAL)res_data->pFileName ); + ok( res_filenameW != NULL, "GlobalLock for res_filenameW failed\n" ); + ok( !lstrcmpW(res_filenameW, (PWCHAR)filenameW), "Filename fields do not match\n" ); + ok( GlobalUnlock( res_filenameW ), "GlobalUnlock res_filenamed failed\n" ); + ok( GlobalUnlock( res_data ), "GlobalUnlock res_data failed\n" ); + ok( EndUpdateResourceW( res, TRUE ), "EndUpdateResourceW failed\n"); +} + START_TEST(resource) { DWORD i; @@ -482,6 +515,7 @@ START_TEST(resource) { const struct _sec_variants *sec = &sec_variants[i]; build_exe( &sec->build ); + test_resource_internal_structure_offsets(); update_resources_none(); check_exe( &sec->chk_none ); update_resources_delete();
On 07/22/2018 08:16 AM, Jon Doron wrote:
For some reason muirct.exe is aware of the opaque structure used by BeginUpdateResource, it access the filename field of the opaque structure during it's processing.
MS documentation for the muirct utility: https://docs.microsoft.com/en-us/windows/desktop/intl/resource-utilities
Sample execution: MUIRCT.EXE -c "ui.exe" -e "de-DE\ui.exe.mui"
Signed-off-by: Jon Doron arilou@gmail.com
dlls/kernel32/tests/resource.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/dlls/kernel32/tests/resource.c b/dlls/kernel32/tests/resource.c index 74066cfba3..87a49e209e 100644 --- a/dlls/kernel32/tests/resource.c +++ b/dlls/kernel32/tests/resource.c @@ -24,6 +24,7 @@ #include "wine/test.h"
static const char filename[] = "test_.exe"; +static const WCHAR filenameW[] = {'t','e','s','t','_','.','e','x','e',0}; static DWORD GLE;
enum constants { @@ -463,6 +464,38 @@ static void test_find_resource(void) ok( GetLastError() == ERROR_RESOURCE_LANG_NOT_FOUND, "wrong error %u\n", GetLastError() ); }
+struct list +{
- struct list *next;
- struct list *prev;
+};
+typedef struct +{
- void *Reserved[6];
- LPWSTR pFileName; /* Must be in offset 0x18 on 32bit and 0x30 on 64bit */
- BOOL bDeleteExistingResources;
- struct list root;
+} QUEUEDUPDATES;
You only need first two fields, the rest is wine-specific. Also comment is redundant imho, and 'Reserved' means 'Unknown' here.
+static void test_resource_internal_structure_offsets(void) +{
- HANDLE res;
- QUEUEDUPDATES *res_data;
- WCHAR *res_filenameW;
- res = BeginUpdateResourceW( (PWCHAR)filenameW, FALSE );
- ok( res != NULL, "BeginUpdateResourceW failed\n" );
- res_data = (QUEUEDUPDATES *)GlobalLock(res);
- ok( res_data != NULL, "GlobalLock failed\n" );
- res_filenameW = (PWCHAR)GlobalLock( (HGLOBAL)res_data->pFileName );
- ok( res_filenameW != NULL, "GlobalLock for res_filenameW failed\n" );
- ok( !lstrcmpW(res_filenameW, (PWCHAR)filenameW), "Filename fields do not match\n" );
- ok( GlobalUnlock( res_filenameW ), "GlobalUnlock res_filenamed failed\n" );
- ok( GlobalUnlock( res_data ), "GlobalUnlock res_data failed\n" );
- ok( EndUpdateResourceW( res, TRUE ), "EndUpdateResourceW failed\n");
+}
- START_TEST(resource) { DWORD i;
@@ -482,6 +515,7 @@ START_TEST(resource) { const struct _sec_variants *sec = &sec_variants[i]; build_exe( &sec->build );
test_resource_internal_structure_offsets(); update_resources_none(); check_exe( &sec->chk_none ); update_resources_delete();