mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Added patches with various PE loader fixes for 8k demos.
This commit is contained in:
parent
2660a14433
commit
634b0e2877
@ -0,0 +1,53 @@
|
||||
From 003af598b273d00e79add3fae33aa6e3d008d93f Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Mon, 2 Jan 2017 15:34:21 +0800
|
||||
Subject: server: All fields up to CheckSum are mandatory regardless of
|
||||
SizeOfOptionalHeader value.
|
||||
|
||||
---
|
||||
server/mapping.c | 13 ++++++++++---
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/server/mapping.c b/server/mapping.c
|
||||
index 7fce12f953d..44fbe637933 100644
|
||||
--- a/server/mapping.c
|
||||
+++ b/server/mapping.c
|
||||
@@ -470,11 +470,10 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s
|
||||
if (dos.e_magic != IMAGE_DOS_SIGNATURE) return STATUS_INVALID_IMAGE_NOT_MZ;
|
||||
pos = dos.e_lfanew;
|
||||
|
||||
+ /* zero out header in the case it's not present or partial */
|
||||
+ memset( &nt, 0, sizeof(nt) );
|
||||
size = pread( unix_fd, &nt, sizeof(nt), pos );
|
||||
if (size < sizeof(nt.Signature) + sizeof(nt.FileHeader)) return STATUS_INVALID_IMAGE_FORMAT;
|
||||
- /* zero out Optional header in the case it's not present or partial */
|
||||
- size = min( size, sizeof(nt.Signature) + sizeof(nt.FileHeader) + nt.FileHeader.SizeOfOptionalHeader );
|
||||
- if (size < sizeof(nt)) memset( (char *)&nt + size, 0, sizeof(nt) - size );
|
||||
if (nt.Signature != IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
if (*(WORD *)&nt.Signature == IMAGE_OS2_SIGNATURE) return STATUS_INVALID_IMAGE_NE_FORMAT;
|
||||
@@ -513,6 +512,10 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s
|
||||
switch (nt.opt.hdr32.Magic)
|
||||
{
|
||||
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
|
||||
+ /* All fields up to CheckSum are mandatory regardless of SizeOfOptionalHeader value */
|
||||
+ size = max( nt.FileHeader.SizeOfOptionalHeader, offsetof(IMAGE_OPTIONAL_HEADER32, CheckSum) );
|
||||
+ if (size < sizeof(nt.opt.hdr32)) memset( (char *)&nt.opt.hdr32 + size, 0, sizeof(nt.opt.hdr32) - size );
|
||||
+
|
||||
mapping->image.base = nt.opt.hdr32.ImageBase;
|
||||
mapping->image.entry_point = nt.opt.hdr32.ImageBase + nt.opt.hdr32.AddressOfEntryPoint;
|
||||
mapping->image.map_size = ROUND_SIZE( nt.opt.hdr32.SizeOfImage );
|
||||
@@ -527,6 +530,10 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s
|
||||
mapping->image.checksum = nt.opt.hdr32.CheckSum;
|
||||
break;
|
||||
case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
|
||||
+ /* All fields up to CheckSum are mandatory regardless of SizeOfOptionalHeader value */
|
||||
+ size = max( nt.FileHeader.SizeOfOptionalHeader, offsetof(IMAGE_OPTIONAL_HEADER64, CheckSum) );
|
||||
+ if (size < sizeof(nt.opt.hdr64)) memset( (char *)&nt.opt.hdr64 + size, 0, sizeof(nt.opt.hdr64) - size );
|
||||
+
|
||||
mapping->image.base = nt.opt.hdr64.ImageBase;
|
||||
mapping->image.entry_point = nt.opt.hdr64.ImageBase + nt.opt.hdr64.AddressOfEntryPoint;
|
||||
mapping->image.map_size = ROUND_SIZE( nt.opt.hdr64.SizeOfImage );
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,31 @@
|
||||
From bbc0ffba68c07dbd27ba4c33b8b6f1a66783b8ff Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Mon, 2 Jan 2017 15:35:41 +0800
|
||||
Subject: ntdll: If PE image size is larger than the backed file size then
|
||||
treat file as removable.
|
||||
|
||||
---
|
||||
dlls/ntdll/virtual.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
|
||||
index bdf94063871..1a60fec7cfd 100644
|
||||
--- a/dlls/ntdll/virtual.c
|
||||
+++ b/dlls/ntdll/virtual.c
|
||||
@@ -1163,6 +1163,13 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
|
||||
/* unaligned sections, this happens for native subsystem binaries */
|
||||
/* in that case Windows simply maps in the whole file */
|
||||
|
||||
+ /* if the image size is larger than the backed file size we can't mmap it */
|
||||
+ if (total_size > ROUND_SIZE( 0, st.st_size ))
|
||||
+ {
|
||||
+ close_handle( dup_mapping );
|
||||
+ dup_mapping = 0;
|
||||
+ }
|
||||
+
|
||||
if (map_file_into_view( view, fd, 0, total_size, 0, VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
|
||||
!dup_mapping ) != STATUS_SUCCESS) goto error;
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,38 @@
|
||||
From 3f4b08acc72791d1c9bb244c39f0721b8da180de Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Mon, 2 Jan 2017 15:38:48 +0800
|
||||
Subject: kernel32: On process entry store PEB address in %ebx.
|
||||
|
||||
8k demo custom PE loader depends on this.
|
||||
---
|
||||
dlls/kernel32/process.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
|
||||
index fdf272f61b0..231844b80a7 100644
|
||||
--- a/dlls/kernel32/process.c
|
||||
+++ b/dlls/kernel32/process.c
|
||||
@@ -1073,12 +1073,19 @@ __ASM_GLOBAL_FUNC( call_process_entry,
|
||||
__ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
|
||||
"movl %esp,%ebp\n\t"
|
||||
__ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
|
||||
+ "pushl %ebx\n\t"
|
||||
+ __ASM_CFI(".cfi_rel_offset %ebx,-4\n\t")
|
||||
+ "subl $12,%esp\n\t"
|
||||
"pushl 4(%ebp)\n\t" /* deliberately mis-align the stack by 8, Doom 3 needs this */
|
||||
"pushl 4(%ebp)\n\t" /* Driller expects readable address at this offset */
|
||||
"pushl 4(%ebp)\n\t"
|
||||
"pushl 8(%ebp)\n\t"
|
||||
+ "movl 8(%ebp),%ebx\n\t"
|
||||
"call *12(%ebp)\n\t"
|
||||
- "leave\n\t"
|
||||
+ "leal -4(%ebp),%esp\n\t"
|
||||
+ "popl %ebx\n\t"
|
||||
+ __ASM_CFI(".cfi_same_value %ebx\n\t")
|
||||
+ "popl %ebp\n\t"
|
||||
__ASM_CFI(".cfi_def_cfa %esp,4\n\t")
|
||||
__ASM_CFI(".cfi_same_value %ebp\n\t")
|
||||
"ret" )
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,25 @@
|
||||
From 0aaa4c217073d55d35e7c85bd8ca44b19bb31ede Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Mon, 2 Jan 2017 15:47:52 +0800
|
||||
Subject: kernel32/tests: Fix a module reference leak leading to an undeletable
|
||||
temporary file.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/loader.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
|
||||
index 4f72c3e599b..9ddfd8d7922 100644
|
||||
--- a/dlls/kernel32/tests/loader.c
|
||||
+++ b/dlls/kernel32/tests/loader.c
|
||||
@@ -1457,6 +1457,7 @@ static void test_import_resolution(void)
|
||||
ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
|
||||
(void *)ptr->thunks[0].u1.Function, data.module, data.function.name );
|
||||
ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index );
|
||||
+ FreeLibrary( mod2 );
|
||||
FreeLibrary( mod );
|
||||
break;
|
||||
case 2: /* load without IMAGE_FILE_DLL doesn't resolve imports */
|
||||
--
|
||||
2.11.0
|
||||
|
@ -0,0 +1,112 @@
|
||||
From b2443dc0deaec8c5e7d70f1bf2004181d2240177 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||||
Date: Mon, 2 Jan 2017 15:50:01 +0800
|
||||
Subject: kernel32/tests: Add a PE test image that resembles format of some of
|
||||
8k demos.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/loader.c | 39 +++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 37 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
|
||||
index 9ddfd8d7922..a74647b3d40 100644
|
||||
--- a/dlls/kernel32/tests/loader.c
|
||||
+++ b/dlls/kernel32/tests/loader.c
|
||||
@@ -184,7 +184,7 @@ static DWORD create_test_dll( const IMAGE_DOS_HEADER *dos_header, UINT dos_size,
|
||||
{
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = WriteFile(hfile, &nt_header->OptionalHeader,
|
||||
- min(nt_header->FileHeader.SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER)),
|
||||
+ sizeof(IMAGE_OPTIONAL_HEADER),
|
||||
&dummy, NULL);
|
||||
ok(ret, "WriteFile error %d\n", GetLastError());
|
||||
if (nt_header->FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER))
|
||||
@@ -200,6 +200,8 @@ static DWORD create_test_dll( const IMAGE_DOS_HEADER *dos_header, UINT dos_size,
|
||||
assert(nt_header->FileHeader.NumberOfSections <= 1);
|
||||
if (nt_header->FileHeader.NumberOfSections)
|
||||
{
|
||||
+ SetFilePointer(hfile, dos_size + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + nt_header->FileHeader.SizeOfOptionalHeader, NULL, FILE_BEGIN);
|
||||
+
|
||||
section.SizeOfRawData = 10;
|
||||
|
||||
if (nt_header->OptionalHeader.SectionAlignment >= page_size)
|
||||
@@ -224,6 +226,17 @@ static DWORD create_test_dll( const IMAGE_DOS_HEADER *dos_header, UINT dos_size,
|
||||
ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL);
|
||||
ok(ret, "WriteFile error %d\n", GetLastError());
|
||||
}
|
||||
+
|
||||
+ /* Minimal PE image that Windows7+ is able to load: 268 bytes */
|
||||
+ size = GetFileSize(hfile, NULL);
|
||||
+ if (size < 268)
|
||||
+ {
|
||||
+ file_align = 268 - size;
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ret = WriteFile(hfile, filler, file_align, &dummy, NULL);
|
||||
+ ok(ret, "WriteFile error %d\n", GetLastError());
|
||||
+ }
|
||||
+
|
||||
size = GetFileSize(hfile, NULL);
|
||||
CloseHandle(hfile);
|
||||
return size;
|
||||
@@ -294,7 +307,8 @@ static void query_image_section( int id, const char *dll_name, const IMAGE_NT_HE
|
||||
image.LoaderFlags, nt_header->OptionalHeader.LoaderFlags );
|
||||
ok( image.ImageFileSize == file_size || broken(!image.ImageFileSize), /* winxpsp1 */
|
||||
"%u: ImageFileSize wrong %08x / %08x\n", id, image.ImageFileSize, file_size );
|
||||
- ok( image.CheckSum == nt_header->OptionalHeader.CheckSum, "%u: CheckSum wrong %08x / %08x\n", id,
|
||||
+ ok( image.CheckSum == nt_header->OptionalHeader.CheckSum || broken(truncated),
|
||||
+ "%u: CheckSum wrong %08x / %08x\n", id,
|
||||
image.CheckSum, nt_header->OptionalHeader.CheckSum );
|
||||
/* FIXME: needs more work: */
|
||||
/* image.GpValue */
|
||||
@@ -444,6 +458,7 @@ static void test_Loader(void)
|
||||
/* Mandatory are all fields up to SizeOfHeaders, everything else
|
||||
* is really optional (at least that's true for XP).
|
||||
*/
|
||||
+#if 0 /* 32-bit Windows 8 crashes inside of LoadLibrary */
|
||||
{ sizeof(dos_header),
|
||||
1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
|
||||
sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER) + 0x10,
|
||||
@@ -451,6 +466,7 @@ static void test_Loader(void)
|
||||
{ ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT, ERROR_INVALID_ADDRESS,
|
||||
ERROR_NOACCESS }
|
||||
},
|
||||
+#endif
|
||||
{ sizeof(dos_header),
|
||||
0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
|
||||
0xd0, /* beyond of the end of file */
|
||||
@@ -519,6 +535,14 @@ static void test_Loader(void)
|
||||
0x40, /* minimal image size that Windows7 accepts */
|
||||
0,
|
||||
{ ERROR_SUCCESS }
|
||||
+ },
|
||||
+ /* the following data mimics the PE image which 8k demos have */
|
||||
+ { 0x04,
|
||||
+ 0, 0x08,
|
||||
+ 0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
|
||||
+ 0x200000,
|
||||
+ 0x40,
|
||||
+ { ERROR_SUCCESS }
|
||||
}
|
||||
};
|
||||
int i;
|
||||
@@ -709,6 +733,17 @@ static void test_Loader(void)
|
||||
ret = FreeLibrary(hlib_as_data_file);
|
||||
ok(ret, "FreeLibrary error %d\n", GetLastError());
|
||||
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ret = DeleteFileA(dll_name);
|
||||
+ ok(ret, "DeleteFile error %d\n", GetLastError());
|
||||
+
|
||||
+ nt_header.OptionalHeader.AddressOfEntryPoint = 0x12345678;
|
||||
+ file_size = create_test_dll( &dos_header, td[i].size_of_dos_header, &nt_header, dll_name );
|
||||
+ if (!file_size)
|
||||
+ {
|
||||
+ ok(0, "could not create %s\n", dll_name);
|
||||
+ break;
|
||||
+ }
|
||||
query_image_section( i, dll_name, &nt_header );
|
||||
}
|
||||
else
|
||||
--
|
||||
2.11.0
|
||||
|
2
patches/kernel32-PE_Loader_Fixes/definition
Normal file
2
patches/kernel32-PE_Loader_Fixes/definition
Normal file
@ -0,0 +1,2 @@
|
||||
Fixes: [42125] Various PE loader fixes for 8k demos
|
||||
Depends: kernel32-Misalign_Workaround
|
@ -183,6 +183,7 @@ patch_enable_all ()
|
||||
enable_kernel32_MoveFile="$1"
|
||||
enable_kernel32_Named_Pipe="$1"
|
||||
enable_kernel32_NeedCurrentDirectoryForExePath="$1"
|
||||
enable_kernel32_PE_Loader_Fixes="$1"
|
||||
enable_kernel32_Profile="$1"
|
||||
enable_kernel32_SCSI_Sysfs="$1"
|
||||
enable_kernel32_SetFileCompletionNotificationModes="$1"
|
||||
@ -744,6 +745,9 @@ patch_enable ()
|
||||
kernel32-NeedCurrentDirectoryForExePath)
|
||||
enable_kernel32_NeedCurrentDirectoryForExePath="$2"
|
||||
;;
|
||||
kernel32-PE_Loader_Fixes)
|
||||
enable_kernel32_PE_Loader_Fixes="$2"
|
||||
;;
|
||||
kernel32-Profile)
|
||||
enable_kernel32_Profile="$2"
|
||||
;;
|
||||
@ -2351,6 +2355,13 @@ if test "$enable_ntdll_CLI_Images" -eq 1; then
|
||||
enable_mscoree_CorValidateImage=1
|
||||
fi
|
||||
|
||||
if test "$enable_kernel32_PE_Loader_Fixes" -eq 1; then
|
||||
if test "$enable_kernel32_Misalign_Workaround" -gt 1; then
|
||||
abort "Patchset kernel32-Misalign_Workaround disabled, but kernel32-PE_Loader_Fixes depends on that."
|
||||
fi
|
||||
enable_kernel32_Misalign_Workaround=1
|
||||
fi
|
||||
|
||||
if test "$enable_kernel32_Named_Pipe" -eq 1; then
|
||||
if test "$enable_server_Desktop_Refcount" -gt 1; then
|
||||
abort "Patchset server-Desktop_Refcount disabled, but kernel32-Named_Pipe depends on that."
|
||||
@ -4619,6 +4630,32 @@ if test "$enable_kernel32_NeedCurrentDirectoryForExePath" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset kernel32-PE_Loader_Fixes
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * kernel32-Misalign_Workaround
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#42125] Various PE loader fixes for 8k demos
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/kernel32/process.c, dlls/kernel32/tests/loader.c, dlls/ntdll/virtual.c, server/mapping.c
|
||||
# |
|
||||
if test "$enable_kernel32_PE_Loader_Fixes" -eq 1; then
|
||||
patch_apply kernel32-PE_Loader_Fixes/0001-server-All-fields-up-to-CheckSum-are-mandatory-regar.patch
|
||||
patch_apply kernel32-PE_Loader_Fixes/0002-ntdll-If-PE-image-size-is-larger-than-the-backed-fil.patch
|
||||
patch_apply kernel32-PE_Loader_Fixes/0003-kernel32-On-process-entry-store-PEB-address-in-ebx.patch
|
||||
patch_apply kernel32-PE_Loader_Fixes/0004-kernel32-tests-Fix-a-module-reference-leak-leading-t.patch
|
||||
patch_apply kernel32-PE_Loader_Fixes/0005-kernel32-tests-Add-a-PE-test-image-that-resembles-fo.patch
|
||||
(
|
||||
echo '+ { "Dmitry Timoshkov", "server: All fields up to CheckSum are mandatory regardless of SizeOfOptionalHeader value.", 1 },';
|
||||
echo '+ { "Dmitry Timoshkov", "ntdll: If PE image size is larger than the backed file size then treat file as removable.", 1 },';
|
||||
echo '+ { "Dmitry Timoshkov", "kernel32: On process entry store PEB address in %ebx.", 1 },';
|
||||
echo '+ { "Dmitry Timoshkov", "kernel32/tests: Fix a module reference leak leading to an undeletable temporary file.", 1 },';
|
||||
echo '+ { "Dmitry Timoshkov", "kernel32/tests: Add a PE test image that resembles format of some of 8k demos.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset kernel32-Profile
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
Loading…
Reference in New Issue
Block a user