From 16851b1c122e83549522ed01c3a303c2f2ca9097 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sat, 18 May 2019 09:29:04 +0200 Subject: [PATCH] setupapi: Extract the 16-bit fake dll from the 32-bit PE one. Signed-off-by: Alexandre Julliard --- dlls/setupapi/fakedll.c | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/dlls/setupapi/fakedll.c b/dlls/setupapi/fakedll.c index 260eb1e54ab..2802aedfe88 100644 --- a/dlls/setupapi/fakedll.c +++ b/dlls/setupapi/fakedll.c @@ -190,6 +190,50 @@ failed: return FALSE; } +static int is_valid_ptr( const void *data, SIZE_T size, const void *ptr, SIZE_T ptr_size ) +{ + if (ptr < data) return 0; + if ((char *)ptr - (char *)data >= size) return 0; + return (size - ((char *)ptr - (char *)data) >= ptr_size); +} + +/* extract the 16-bit NE dll from a PE builtin */ +static void extract_16bit_image( IMAGE_NT_HEADERS *nt, void **data, SIZE_T *size ) +{ + DWORD exp_size, *size_ptr; + IMAGE_DOS_HEADER *dos; + IMAGE_EXPORT_DIRECTORY *exports; + IMAGE_SECTION_HEADER *section = NULL; + WORD *ordinals; + DWORD *names, *functions; + int i; + + exports = RtlImageDirectoryEntryToData( *data, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size ); + if (!is_valid_ptr( *data, *size, exports, exp_size )) return; + ordinals = RtlImageRvaToVa( nt, *data, exports->AddressOfNameOrdinals, §ion ); + names = RtlImageRvaToVa( nt, *data, exports->AddressOfNames, §ion ); + functions = RtlImageRvaToVa( nt, *data, exports->AddressOfFunctions, §ion ); + if (!is_valid_ptr( *data, *size, ordinals, exports->NumberOfNames * sizeof(*ordinals) )) return; + if (!is_valid_ptr( *data, *size, names, exports->NumberOfNames * sizeof(*names) )) return; + + for (i = 0; i < exports->NumberOfNames; i++) + { + char *ename = RtlImageRvaToVa( nt, *data, names[i], §ion ); + if (strcmp( ename, "__wine_spec_dos_header" )) continue; + if (ordinals[i] >= exports->NumberOfFunctions) return; + if (!is_valid_ptr( *data, *size, functions, sizeof(*functions) )) return; + if (!functions[ordinals[i]]) return; + dos = RtlImageRvaToVa( nt, *data, functions[ordinals[i]], NULL ); + if (!is_valid_ptr( *data, *size, dos, sizeof(*dos) )) return; + if (dos->e_magic != IMAGE_DOS_SIGNATURE) return; + size_ptr = (DWORD *)dos->e_res2; + *size = min( *size_ptr, *size - ((const char *)dos - (const char *)*data) ); + *size_ptr = 0; + *data = dos; + break; + } +} + /* read in the contents of a file into the global file buffer */ /* return 1 on success, 0 on nonexistent file, -1 on other error */ static int read_file( const char *name, void **data, SIZE_T *size, BOOL expect_builtin ) @@ -238,6 +282,8 @@ static int read_file( const char *name, void **data, SIZE_T *size, BOOL expect_b st.st_size - header_size, header_size ) == st.st_size - header_size) { *data = file_buffer; + if (strlen(name) > 2 && !strcmp( name + strlen(name) - 2, "16" )) + extract_16bit_image( nt, data, size ); ret = 1; } done: