[PATCH] kernel32/tests: Test CreateFileMapping with a foreign architecture dll

André Hentschel nerv at dawncrow.de
Sun Jan 7 10:03:50 CST 2018


This was written with project Hangover in mind, we hoped that we can get rid of https://github.com/AndreRH/wine/commit/8935bdf941f5f2866c2fa4695eb15d94337fae9e
Sadly this seems not to be the case, as Wine already behaves like modern Windows here

Signed-off-by: André Hentschel <nerv at dawncrow.de>
---
 dlls/kernel32/tests/virtual.c | 96 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 92 insertions(+), 4 deletions(-)

diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
index 4a449fd..56eb456 100644
--- a/dlls/kernel32/tests/virtual.c
+++ b/dlls/kernel32/tests/virtual.c
@@ -1608,10 +1608,79 @@ static void test_NtAreMappedFilesTheSame(void)
     DeleteFileA( testfile );
 }
 
+static BOOL create_foreign_dll( LPCSTR filename )
+{
+    IMAGE_DOS_HEADER *dos;
+    IMAGE_NT_HEADERS *nt;
+    IMAGE_SECTION_HEADER *sec;
+    BYTE *buffer;
+    DWORD lfanew = sizeof(*dos);
+    DWORD size = lfanew + sizeof(*nt) + sizeof(*sec);
+    DWORD written;
+    BOOL ret;
+
+    HANDLE file = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+    if (file == INVALID_HANDLE_VALUE) return FALSE;
+
+    buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
+
+    dos = (IMAGE_DOS_HEADER *)buffer;
+    dos->e_magic    = IMAGE_DOS_SIGNATURE;
+    dos->e_cblp     = sizeof(*dos);
+    dos->e_cp       = 1;
+    dos->e_cparhdr  = lfanew / 16;
+    dos->e_minalloc = 0;
+    dos->e_maxalloc = 0xffff;
+    dos->e_ss       = 0x0000;
+    dos->e_sp       = 0x00b8;
+    dos->e_lfarlc   = lfanew;
+    dos->e_lfanew   = lfanew;
+
+    nt = (IMAGE_NT_HEADERS *)(buffer + lfanew);
+    nt->Signature = IMAGE_NT_SIGNATURE;
+#if defined __aarch64__
+    nt->FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64;
+#else
+    nt->FileHeader.Machine = IMAGE_FILE_MACHINE_ARM64;
+#endif
+    nt->FileHeader.NumberOfSections = 1;
+    nt->FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
+    nt->FileHeader.Characteristics = IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE;
+    nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
+    nt->OptionalHeader.MajorLinkerVersion = 1;
+    nt->OptionalHeader.MinorLinkerVersion = 0;
+    nt->OptionalHeader.ImageBase = 0x10000000;
+    nt->OptionalHeader.SectionAlignment = 0x1000;
+    nt->OptionalHeader.FileAlignment = 0x1000;
+    nt->OptionalHeader.MajorOperatingSystemVersion = 1;
+    nt->OptionalHeader.MinorOperatingSystemVersion = 0;
+    nt->OptionalHeader.MajorImageVersion = 1;
+    nt->OptionalHeader.MinorImageVersion = 0;
+    nt->OptionalHeader.MajorSubsystemVersion = 4;
+    nt->OptionalHeader.MinorSubsystemVersion = 0;
+    nt->OptionalHeader.SizeOfImage = 0x2000;
+    nt->OptionalHeader.SizeOfHeaders = size;
+    nt->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
+    nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
+
+    sec = (IMAGE_SECTION_HEADER *)(nt + 1);
+    memcpy( sec->Name, ".rodata", sizeof(".rodata") );
+    sec->Misc.VirtualSize = 0x1000;
+    sec->VirtualAddress   = 0x1000;
+    sec->SizeOfRawData    = 0;
+    sec->PointerToRawData = 0;
+    sec->Characteristics  = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
+
+    ret = WriteFile( file, buffer, size, &written, NULL ) && written == size;
+    HeapFree( GetProcessHeap(), 0, buffer );
+    CloseHandle( file );
+    return ret;
+}
+
 static void test_CreateFileMapping(void)
 {
-    HANDLE handle, handle2, file[3];
-    char path[MAX_PATH], filename[MAX_PATH];
+    HANDLE handle, handle2, file[4];
+    char path[MAX_PATH], filename[MAX_PATH], filename2[MAX_PATH];
     unsigned int i;
     NTSTATUS status;
 
@@ -1664,6 +1733,14 @@ static void test_CreateFileMapping(void)
         { 2, SEC_IMAGE | SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER },
         { 2, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER },
         { 2, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER },
+        /* foreign PE image file */
+        { 3, SEC_IMAGE, ERROR_BAD_EXE_FORMAT, SEC_FILE | SEC_IMAGE },
+        { 3, SEC_IMAGE | SEC_FILE, ERROR_INVALID_PARAMETER }, /* 45 */
+        { 3, SEC_IMAGE | SEC_NOCACHE, ERROR_BAD_EXE_FORMAT, SEC_FILE | SEC_IMAGE },
+        { 3, SEC_IMAGE | SEC_LARGE_PAGES, ERROR_INVALID_PARAMETER },
+        { 3, SEC_IMAGE | SEC_WRITECOMBINE, ERROR_INVALID_PARAMETER },
+        { 3, SEC_IMAGE | SEC_RESERVE, ERROR_INVALID_PARAMETER },
+        { 3, SEC_IMAGE | SEC_COMMIT, ERROR_INVALID_PARAMETER }, /* 50 */
     };
 
     /* test case sensitivity */
@@ -1716,17 +1793,26 @@ static void test_CreateFileMapping(void)
     file[2] = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
     ok( file[2] != INVALID_HANDLE_VALUE, "CreateFile error %u\n", GetLastError() );
 
+    GetTempPathA( MAX_PATH, path );
+    GetTempFileNameA( path, "foreign", 0, filename2 );
+    ok(create_foreign_dll(filename2), "Creation of foreign dll failed\n");
+    file[3] = CreateFileA( filename2, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
+
     for (i = 0; i < sizeof(sec_flag_tests) / sizeof(sec_flag_tests[0]); i++)
     {
         DWORD flags = sec_flag_tests[i].flags;
-        DWORD perm = sec_flag_tests[i].file == 2 ? PAGE_READONLY : PAGE_READWRITE;
+        DWORD perm = sec_flag_tests[i].file >= 2 ? PAGE_READONLY : PAGE_READWRITE;
         SetLastError( 0xdeadbeef );
         handle = CreateFileMappingA( file[sec_flag_tests[i].file], NULL,
                                      flags | perm, 0, 0x1000, "Wine Test Mapping" );
         if (sec_flag_tests[i].error)
         {
+            /* SEC_IMAGE_NO_EXECUTE produces ERROR_INVALID_PARAMETER on older Windows */
+            BOOL wrong_err = ((flags & SEC_IMAGE_NO_EXECUTE) == SEC_IMAGE_NO_EXECUTE) &&
+                             (GetLastError() == ERROR_INVALID_PARAMETER);
             ok( !handle, "%u: CreateFileMapping succeeded\n", i );
-            ok( GetLastError() == sec_flag_tests[i].error, "%u: wrong error %u\n", i, GetLastError());
+            ok( GetLastError() == sec_flag_tests[i].error || broken(wrong_err),
+                "%u: wrong error %u\n", i, GetLastError());
         }
         else
         {
@@ -1754,7 +1840,9 @@ static void test_CreateFileMapping(void)
     }
     CloseHandle( file[1] );
     CloseHandle( file[2] );
+    CloseHandle( file[3] );
     DeleteFileA( filename );
+    DeleteFileA( filename2 );
 }
 
 static void test_IsBadReadPtr(void)
-- 
2.7.4




More information about the wine-devel mailing list