/* add version resources to the dll by copying them from the source module */ static BOOL add_version_resource( HMODULE module, struct dll_info *dll_info ) { BOOL ret = FALSE; DWORD rva_start = ~0U, rva_end = 0, dir_size, total_size; const IMAGE_RESOURCE_DIRECTORY *basedir; const BYTE *data_start, *root; BYTE *buffer; if (!module) return TRUE; if (LdrFindResourceDirectory_U( module, NULL, 0, &basedir ) != STATUS_SUCCESS) return TRUE; root = (const BYTE *)basedir; get_resource_data( basedir, root, &rva_start, &rva_end ); data_start = (const BYTE *)module + rva_start; if (data_start <= root) return FALSE; dir_size = data_start - root; if (!(buffer = HeapAlloc( GetProcessHeap(), 0, dir_size ))) return FALSE; memcpy( buffer, root, dir_size ); fixup_resources( (IMAGE_RESOURCE_DIRECTORY *)buffer, buffer, dll_info->mem_pos + dir_size - rva_start ); if (!xwrite( dll_info, buffer, dir_size, dll_info->file_pos )) goto done; if (!xwrite( dll_info, data_start, rva_end - rva_start, dll_info->file_pos + dir_size )) goto done; total_size = dir_size + rva_end - rva_start; add_directory( dll_info, IMAGE_DIRECTORY_ENTRY_RESOURCE, dll_info->mem_pos, total_size ); add_section( dll_info, ".rsrc", total_size, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ ); ret = TRUE; done: HeapFree( GetProcessHeap(), 0, buffer ); return ret; }
static int fixup_cnt_call(void** param, int param_no) { if (param_no==1) /* IP */ return fixup_is_dst(param, 1); if (param_no==2) /* port */ return fixup_is_dst(param, 2); if (param_no==3) /* group id */ return fixup_resources(param, 1); if (param_no==4) /* resources */ return fixup_resources(param, 2); return -1; }
static int fixup_cnt_call(void** param, int param_no) { if (param_no==1) /* IP */ return fixup_is_dst(param, 1); if (param_no==2) /* port */ return fixup_is_dst(param, 2); if (param_no==3) /* group id */ return fixup_resources(param, 1); if (param_no==4) /* resources */ return fixup_resources(param, 2); if (param_no==5) /* count or un-count */ return fixup_uint(param); LM_CRIT("error - wrong params count (%d)\n",param_no); return -1; }
/* fixup RVAs of resource data */ static void fixup_resources( IMAGE_RESOURCE_DIRECTORY *dir, BYTE *root, int delta ) { IMAGE_RESOURCE_DIRECTORY_ENTRY *entry; int i; entry = (IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1); for (i = 0; i < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; i++, entry++) { void *ptr = root + entry->u2.s3.OffsetToDirectory; if (entry->u2.s3.DataIsDirectory) fixup_resources( ptr, root, delta ); else { IMAGE_RESOURCE_DATA_ENTRY *data = ptr; if (data->OffsetToData) data->OffsetToData += delta; } } }
/* map a builtin dll in memory and fixup RVAs */ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr ) { #ifdef HAVE_MMAP IMAGE_DATA_DIRECTORY *dir; IMAGE_DOS_HEADER *dos; IMAGE_NT_HEADERS *nt; IMAGE_SECTION_HEADER *sec; BYTE *addr; DWORD code_start, data_start, data_end; const size_t page_size = getpagesize(); const size_t page_mask = page_size - 1; int delta, nb_sections = 2; /* code + data */ unsigned int i; size_t size = (sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) + nb_sections * sizeof(IMAGE_SECTION_HEADER)); assert( size <= page_size ); /* module address must be aligned on 64K boundary */ addr = (BYTE *)((nt_descr->OptionalHeader.ImageBase + 0xffff) & ~0xffff); if (wine_anon_mmap( addr, page_size, PROT_READ|PROT_WRITE, MAP_FIXED ) != addr) return NULL; dos = (IMAGE_DOS_HEADER *)addr; nt = (IMAGE_NT_HEADERS *)(dos + 1); sec = (IMAGE_SECTION_HEADER *)(nt + 1); /* Build the DOS and NT headers */ dos->e_magic = IMAGE_DOS_SIGNATURE; dos->e_cblp = 0x90; dos->e_cp = 3; dos->e_cparhdr = (sizeof(*dos)+0xf)/0x10; dos->e_minalloc = 0; dos->e_maxalloc = 0xffff; dos->e_ss = 0x0000; dos->e_sp = 0x00b8; dos->e_lfarlc = sizeof(*dos); dos->e_lfanew = sizeof(*dos); *nt = *nt_descr; delta = (const BYTE *)nt_descr - addr; code_start = page_size; data_start = delta & ~page_mask; data_end = (nt->OptionalHeader.SizeOfImage + delta + page_mask) & ~page_mask; fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 ); nt->FileHeader.NumberOfSections = nb_sections; nt->OptionalHeader.BaseOfCode = code_start; #ifndef _WIN64 nt->OptionalHeader.BaseOfData = data_start; #endif nt->OptionalHeader.SizeOfCode = data_start - code_start; nt->OptionalHeader.SizeOfInitializedData = data_end - data_start; nt->OptionalHeader.SizeOfUninitializedData = 0; nt->OptionalHeader.SizeOfImage = data_end; nt->OptionalHeader.ImageBase = (ULONG_PTR)addr; /* Build the code section */ memcpy( sec->Name, ".text", sizeof(".text") ); sec->SizeOfRawData = data_start - code_start; sec->Misc.VirtualSize = sec->SizeOfRawData; sec->VirtualAddress = code_start; sec->PointerToRawData = code_start; sec->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ); sec++; /* Build the data section */ memcpy( sec->Name, ".data", sizeof(".data") ); sec->SizeOfRawData = data_end - data_start; sec->Misc.VirtualSize = sec->SizeOfRawData; sec->VirtualAddress = data_start; sec->PointerToRawData = data_start; sec->Characteristics = (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ); sec++; for (i = 0; i < nt->OptionalHeader.NumberOfRvaAndSizes; i++) fixup_rva_dwords( &nt->OptionalHeader.DataDirectory[i].VirtualAddress, delta, 1 ); /* Build the import directory */ dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY]; if (dir->Size) { IMAGE_IMPORT_DESCRIPTOR *imports = (void *)(addr + dir->VirtualAddress); fixup_imports( imports, addr, delta ); } /* Build the resource directory */ dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_RESOURCE_DIRECTORY]; if (dir->Size) { void *ptr = (void *)(addr + dir->VirtualAddress); fixup_resources( ptr, ptr, delta ); } /* Build the export directory */ dir = &nt->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY]; if (dir->Size) { IMAGE_EXPORT_DIRECTORY *exports = (void *)(addr + dir->VirtualAddress); fixup_exports( exports, addr, delta ); } return addr; #else /* HAVE_MMAP */ return NULL; #endif /* HAVE_MMAP */ }