From 3a3fd9f009e253b9943dcbc56324a0c935324d04 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 22 Feb 2011 11:19:47 -0500 Subject: SCUMM: Use the new PEResources class for HE cursors Putt-Putt Saves the Zoo HE72 still works fine for me --- engines/scumm/he/resource_he.cpp | 1038 ++++---------------------------------- engines/scumm/he/resource_he.h | 310 +----------- 2 files changed, 99 insertions(+), 1249 deletions(-) (limited to 'engines/scumm') diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp index 72e7052034..987ee1ebe3 100644 --- a/engines/scumm/he/resource_he.cpp +++ b/engines/scumm/he/resource_he.cpp @@ -4,7 +4,7 @@ * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * - * Parts of this code are heavily based on: + * Parts of this code are based on: * icoutils - A set of programs dealing with MS Windows icons and cursors. * Copyright (C) 1998-2001 Oskar Liljeblad * @@ -43,14 +43,6 @@ namespace Scumm { -#if defined(SCUMM_LITTLE_ENDIAN) -#define LE16(x) -#define LE32(x) -#elif defined(SCUMM_BIG_ENDIAN) -#define LE16(x) ((x) = TO_LE_16(x)) -#define LE32(x) ((x) = TO_LE_32(x)) -#endif - ResExtractor::ResExtractor(ScummEngine_v70he *scumm) : _vm(scumm) { @@ -126,912 +118,134 @@ void ResExtractor::setCursor(int id) { } -/* - * Static variables - */ -const char *res_types[] = { - /* 0x01: */ - "cursor", "bitmap", "icon", "menu", "dialog", "string", - "fontdir", "font", "accelerator", "rcdata", "messagelist", - "group_cursor", NULL, "group_icon", NULL, - /* the following are not defined in winbase.h, but found in wrc. */ - /* 0x10: */ - "version", "dlginclude", NULL, "plugplay", "vxd", - "anicursor", "aniicon" -}; -#define RES_TYPE_COUNT (sizeof(res_types)/sizeof(char *)) - Win32ResExtractor::Win32ResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) { } int Win32ResExtractor::extractResource(int resId, byte **data) { - char buf[20]; - - snprintf(buf, sizeof(buf), "%d", resId); - - return extractResource_("group_cursor", buf, data); -} - -int Win32ResExtractor::extractResource_(const char *resType, char *resName, byte **data) { - char *arg_language = NULL; - const char *arg_type = resType; - char *arg_name = resName; - int ressize = 0; - - _arg_raw = false; - - /* translate --type option from resource type string to integer */ - arg_type = res_type_string_to_id(arg_type); - - WinLibrary fi; - - /* initiate stuff */ - fi.memory = NULL; - fi.file = NULL; - if (_fileName.empty()) { // We are running for the first time _fileName = _vm->generateFilename(-3); - } - - /* get file size */ - fi.file = SearchMan.createReadStreamForMember(_fileName); - if (!fi.file) { - error("Cannot open file %s", _fileName.c_str()); - } - - fi.total_size = fi.file->size(); - if (fi.total_size == -1) { - error("Cannot get size of file %s", _fileName.c_str()); - goto cleanup; - } - if (fi.total_size == 0) { - error("%s: file has a size of 0", _fileName.c_str()); - goto cleanup; - } - - /* read all of file */ - fi.memory = (byte *)malloc(fi.total_size); - if (fi.file->read(fi.memory, fi.total_size) == 0) { - error("Cannot read from file %s", _fileName.c_str()); - goto cleanup; - } - - /* identify file and find resource table */ - if (!read_library(&fi)) { - /* error reported by read_library */ - goto cleanup; - } - - /* errors will be printed by the callback */ - ressize = do_resources(&fi, arg_type, arg_name, arg_language, data); - - /* free stuff and close file */ - cleanup: - delete fi.file; - free(fi.memory); - - return ressize; -} - - -/** - * Translate a numeric resource type to it's corresponding string type. - * (For informative-ness.) - */ -const char *Win32ResExtractor::res_type_id_to_string(int id) { - if (id == 241) - return "toolbar"; - if (id > 0 && id <= (int)RES_TYPE_COUNT) - return res_types[id-1]; - return NULL; -} - -/** - * Translate a resource type string to integer. - * (Used to convert the --type option.) - */ -const char *Win32ResExtractor::res_type_string_to_id(const char *type) { - static const char *res_type_ids[] = { - "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", "-10", - "-11", "-12", NULL, "-14", NULL, "-16", "-17", NULL, "-19", - "-20", "-21", "-22" - }; - int c; - - if (type == NULL) - return NULL; - - for (c = 0; c < (int)RES_TYPE_COUNT; c++) { - if (res_types[c] != NULL && !scumm_stricmp(type, res_types[c])) - return res_type_ids[c]; - } - - return type; -} - -/** - * Return the resource id quoted if it is a string, otherwise (i.e. if - * it is numeric) just return it. - */ -Common::String Win32ResExtractor::WinResource::getQuotedResourceId() const { - if (numeric_id || id[0] == '\0') - return id; - return '"' + Common::String(id) + '"'; -} - -int Win32ResExtractor::extract_resources(WinLibrary *fi, WinResource *wr, - WinResource *type_wr, WinResource *name_wr, - WinResource *lang_wr, byte **data) { - int size; - bool free_it; - const char *type; - int32 id; - - if (*data) { - error("Win32ResExtractor::extract_resources() more than one cursor"); - return 0; - } - - *data = extract_resource(fi, wr, &size, &free_it, type_wr->id, (lang_wr == NULL ? NULL : lang_wr->id), _arg_raw); - if (data == NULL) { - error("Win32ResExtractor::extract_resources() problem with resource extraction"); - return 0; - } - - /* get named resource type if possible */ - type = NULL; - if ((id = strtol(type_wr->id, 0, 10)) != 0) - type = res_type_id_to_string(id); - - if (lang_wr != NULL && lang_wr->id[0] != '\0') { - debugC(DEBUG_RESOURCE, "extractCursor(). Found cursor name: %s language: %s [size=%d]", - name_wr->getQuotedResourceId().c_str(), lang_wr->getQuotedResourceId().c_str(), size); - } else { - debugC(DEBUG_RESOURCE, "extractCursor(). Found cursor name: %s [size=%d]", - name_wr->getQuotedResourceId().c_str(), size); - } - return size; -} - -/** - * Extract a resource, returning pointer to data. - */ -byte *Win32ResExtractor::extract_resource(WinLibrary *fi, WinResource *wr, int *size, - bool *free_it, char *type, char *lang, bool raw) { - char *str; - int32 intval; - - /* just return pointer to data if raw */ - if (raw) { - *free_it = false; - /* get_resource_entry will print possible error */ - return get_resource_entry(fi, wr, size); - } - - /* find out how to extract */ - str = type; - if (str != NULL && (intval = strtol(STRIP_RES_ID_FORMAT(str), 0, 10))) { - if (intval == (int)RT_GROUP_ICON) { - *free_it = true; - return extract_group_icon_cursor_resource(fi, wr, lang, size, true); - } - if (intval == (int)RT_GROUP_CURSOR) { - *free_it = true; - return extract_group_icon_cursor_resource(fi, wr, lang, size, false); - } - } - - return NULL; -} - -/** - * Create a complete RT_GROUP_ICON resource, that can be written to - * an `.ico' file without modifications. Returns an allocated - * memory block that should be freed with free() once used. - * - * `root' is the offset in file that specifies the resource. - * `base' is the offset that string pointers are calculated from. - * `ressize' should point to an integer variable where the size of - * the returned memory block will be placed. - * `is_icon' indicates whether resource to be extracted is icon - * or cursor group. - */ -byte *Win32ResExtractor::extract_group_icon_cursor_resource(WinLibrary *fi, WinResource *wr, char *lang, - int *ressize, bool is_icon) { - Win32CursorIconDir *icondir; - Win32CursorIconFileDir *fileicondir; - byte *memory; - int c, offset, skipped; - int size; - - /* get resource data and size */ - icondir = (Win32CursorIconDir *)get_resource_entry(fi, wr, &size); - if (icondir == NULL) { - /* get_resource_entry will print error */ - return NULL; - } - - /* calculate total size of output file */ - RETURN_IF_BAD_POINTER(NULL, icondir->count); - skipped = 0; - for (c = 0; c < FROM_LE_16(icondir->count); c++) { - int level; - int iconsize; - char name[14]; - WinResource *fwr; - - RETURN_IF_BAD_POINTER(NULL, icondir->entries[c]); - /*debug("%d. bytes_in_res=%d width=%d height=%d planes=%d bit_count=%d", c, - FROM_LE_32(icondir->entries[c].bytes_in_res), - (is_icon ? icondir->entries[c].res_info.icon.width : FROM_LE_16(icondir->entries[c].res_info.cursor.width)), - (is_icon ? icondir->entries[c].res_info.icon.height : FROM_LE_16(icondir->entries[c].res_info.cursor.height)), - FROM_LE_16(icondir->entries[c].plane_count), - FROM_LE_16(icondir->entries[c].bit_count));*/ - - /* find the corresponding icon resource */ - snprintf(name, sizeof(name)/sizeof(char), "-%d", FROM_LE_16(icondir->entries[c].res_id)); - fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level); - if (fwr == NULL) { - error("%s: could not find `%s' in `%s' resource.", - _fileName.c_str(), &name[1], (is_icon ? "group_icon" : "group_cursor")); - return NULL; - } - - if (get_resource_entry(fi, fwr, &iconsize) != NULL) { - if (iconsize == 0) { - debugC(DEBUG_RESOURCE, "%s: icon resource `%s' is empty, skipping", _fileName.c_str(), name); - skipped++; - continue; - } - if ((uint32)iconsize != FROM_LE_32(icondir->entries[c].bytes_in_res)) { - debugC(DEBUG_RESOURCE, "%s: mismatch of size in icon resource `%s' and group (%d != %d)", - _fileName.c_str(), name, iconsize, FROM_LE_32(icondir->entries[c].bytes_in_res)); - } - size += iconsize; /* size += FROM_LE_32(icondir->entries[c].bytes_in_res); */ - - /* cursor resources have two additional WORDs that contain - * hotspot info */ - if (!is_icon) - size -= sizeof(uint16)*2; - } - } - offset = sizeof(Win32CursorIconFileDir) + (FROM_LE_16(icondir->count)-skipped) * sizeof(Win32CursorIconFileDirEntry); - size += offset; - *ressize = size; - - /* allocate that much memory */ - memory = (byte *)malloc(size); - fileicondir = (Win32CursorIconFileDir *)memory; - - /* transfer Win32CursorIconDir structure members */ - fileicondir->reserved = icondir->reserved; - fileicondir->type = icondir->type; - fileicondir->count = TO_LE_16(FROM_LE_16(icondir->count) - skipped); - - /* transfer each cursor/icon: Win32CursorIconDirEntry and data */ - skipped = 0; - for (c = 0; c < FROM_LE_16(icondir->count); c++) { - int level; - char name[14]; - WinResource *fwr; - byte *data; - - /* find the corresponding icon resource */ - snprintf(name, sizeof(name)/sizeof(char), "-%d", FROM_LE_16(icondir->entries[c].res_id)); - fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level); - if (fwr == NULL) { - error("%s: could not find `%s' in `%s' resource.", - _fileName.c_str(), &name[1], (is_icon ? "group_icon" : "group_cursor")); - return NULL; - } - - /* get data and size of that resource */ - data = (byte *)get_resource_entry(fi, fwr, &size); - if (data == NULL) { - /* get_resource_entry has printed error */ - return NULL; - } - if (size == 0) { - skipped++; - continue; - } - - /* copy ICONDIRENTRY (not including last dwImageOffset) */ - memcpy(&fileicondir->entries[c-skipped], &icondir->entries[c], - sizeof(Win32CursorIconFileDirEntry)-sizeof(uint32)); - - /* special treatment for cursors */ - if (!is_icon) { - fileicondir->entries[c-skipped].width = icondir->entries[c].res_info.cursor.width; - fileicondir->entries[c-skipped].height = TO_LE_16(FROM_LE_16(icondir->entries[c].res_info.cursor.height) / 2); - fileicondir->entries[c-skipped].color_count = 0; - fileicondir->entries[c-skipped].reserved = 0; - } - - /* set image offset and increase it */ - fileicondir->entries[c-skipped].dib_offset = TO_LE_32(offset); - - /* transfer resource into file memory */ - if (is_icon) { - memcpy(&memory[offset], data, FROM_LE_32(icondir->entries[c].bytes_in_res)); - } else { - fileicondir->entries[c-skipped].hotspot_x = ((uint16 *) data)[0]; - fileicondir->entries[c-skipped].hotspot_y = ((uint16 *) data)[1]; - memcpy(&memory[offset], data+sizeof(uint16)*2, - FROM_LE_32(icondir->entries[c].bytes_in_res)-sizeof(uint16)*2); - offset -= sizeof(uint16)*2; - } - - /* increase the offset pointer */ - offset += FROM_LE_32(icondir->entries[c].bytes_in_res); + if (!_exe.loadFromEXE(_fileName)) + error("Cannot open file %s", _fileName.c_str()); } - return memory; -} - -/** - * Check if a chunk of data (determined by offset and size) - * is within the bounds of the WinLibrary file. - * Usually not called directly. - */ -bool Win32ResExtractor::check_offset(byte *memory, int total_size, const char *name, void *offset, int size) { - int need_size = (int)((byte *)offset - memory + size); - - debugC(DEBUG_RESOURCE, "check_offset: size=%x vs %x offset=%x size=%x", - need_size, total_size, (uint)((byte *)offset - memory), size); + Common::SeekableReadStream *cursorGroup = _exe.getResource(Common::kPEGroupCursor, resId); - if (need_size < 0 || need_size > total_size) { - error("%s: premature end", name); - return false; - } + if (!cursorGroup) + error("Could not find cursor group %d", resId); - return true; -} + cursorGroup->skip(4); + uint16 count = cursorGroup->readUint16LE(); + assert(count > 0); + cursorGroup->skip(12); + resId = cursorGroup->readUint16LE(); -/** - * Do something for each resource matching type, name and lang. - */ -int Win32ResExtractor::do_resources(WinLibrary *fi, const char *type, char *name, char *lang, byte **data) { - WinResource *type_wr; - WinResource *name_wr; - WinResource *lang_wr; - int size; + delete cursorGroup; - type_wr = (WinResource *)calloc(3, sizeof(WinResource)); - name_wr = type_wr + 1; - lang_wr = type_wr + 2; + Common::SeekableReadStream *cursor = _exe.getResource(Common::kPECursor, resId); - size = do_resources_recurs(fi, NULL, type_wr, name_wr, lang_wr, type, name, lang, data); + if (!cursor) + error("Could not find cursor %d", resId); - free(type_wr); + int size = cursor->size(); + *data = (byte *)malloc(size); + cursor->read(*data, size); + delete cursor; return size; } -/* what is each entry in this directory level for? type, name or language? */ -#define WINRESOURCE_BY_LEVEL(x) ((x)==0 ? type_wr : ((x)==1 ? name_wr : lang_wr)) - -/* does the id of this entry match the specified id? */ -#define LEVEL_MATCHES(x) (x == NULL || x ## _wr->id[0] == '\0' || compare_resource_id(x ## _wr, x)) - -int Win32ResExtractor::do_resources_recurs(WinLibrary *fi, WinResource *base, - WinResource *type_wr, WinResource *name_wr, WinResource *lang_wr, - const char *type, char *name, char *lang, byte **data) { - int c, rescnt; - WinResource *wr; - uint32 size = 0; - - /* get a list of all resources at this level */ - wr = list_resources(fi, base, &rescnt); - if (wr == NULL) { - return size; - } - - /* process each resource listed */ - for (c = 0; c < rescnt; c++) { - /* (over)write the corresponding WinResource holder with the current */ - memcpy(WINRESOURCE_BY_LEVEL(wr[c].level), wr+c, sizeof(WinResource)); - - /* go deeper unless there is something that does NOT match */ - if (LEVEL_MATCHES(type) && LEVEL_MATCHES(name) && LEVEL_MATCHES(lang)) { - if (wr->is_directory) - size = do_resources_recurs(fi, wr+c, type_wr, name_wr, lang_wr, type, name, lang, data); - else - size = extract_resources(fi, wr+c, type_wr, name_wr, lang_wr, data); - } - } - - /* since we're moving back one level after this, unset the - * WinResource holder used on this level */ - memset(WINRESOURCE_BY_LEVEL(wr[0].level), 0, sizeof(WinResource)); - - return size; -} - -bool Win32ResExtractor::compare_resource_id(WinResource *wr, const char *id) { - if (wr->numeric_id) { - int32 cmp1, cmp2; - if (id[0] == '+') - return false; - if (id[0] == '-') - id++; - cmp1 = strtol(wr->id, 0, 10); - cmp2 = strtol(id, 0, 10); - if (!cmp1 || !cmp2 || cmp1 != cmp2) - return false; - } else { - if (id[0] == '-') - return false; - if (id[0] == '+') - id++; - if (strcmp(wr->id, id)) - return false; - } - - return true; -} - -bool Win32ResExtractor::decode_pe_resource_id(WinLibrary *fi, WinResource *wr, uint32 value) { - if (value & IMAGE_RESOURCE_NAME_IS_STRING) { /* numeric id */ - int c, len; - uint16 *mem = (uint16 *) - (fi->first_resource + (value & ~IMAGE_RESOURCE_NAME_IS_STRING)); - - /* copy each char of the string, and terminate it */ - RETURN_IF_BAD_POINTER(false, *mem); - len = FROM_LE_16(mem[0]); - RETURN_IF_BAD_OFFSET(false, &mem[1], sizeof(uint16) * len); - - len = MIN(FROM_LE_16(mem[0]), (uint16)WINRES_ID_MAXLEN); - for (c = 0; c < len; c++) - wr->id[c] = FROM_LE_16(mem[c+1]) & 0x00FF; - wr->id[len] = '\0'; - wr->numeric_id = false; - } else { /* Unicode string id */ - /* translate id into a string */ - snprintf(wr->id, WINRES_ID_MAXLEN, "%d", value); - wr->numeric_id = true; - } - - return true; -} - -byte *Win32ResExtractor::get_resource_entry(WinLibrary *fi, WinResource *wr, int *size) { - byte *result; - - Win32ImageResourceDataEntry *dataent; - - dataent = (Win32ImageResourceDataEntry *) wr->children; - RETURN_IF_BAD_POINTER(NULL, *dataent); - *size = FROM_LE_32(dataent->size); - - result = fi->memory + FROM_LE_32(dataent->offset_to_data); - - RETURN_IF_BAD_OFFSET(NULL, result, *size); - - return result; -} - -Win32ResExtractor::WinResource *Win32ResExtractor::list_pe_resources(WinLibrary *fi, Win32ImageResourceDirectory *pe_res, int level, int *count) { - WinResource *wr; - int c, rescnt; - Win32ImageResourceDirectoryEntry *dirent - = (Win32ImageResourceDirectoryEntry *)(pe_res + 1); - - /* count number of `type' resources */ - RETURN_IF_BAD_POINTER(NULL, *dirent); - rescnt = FROM_LE_16(pe_res->number_of_named_entries) + FROM_LE_16(pe_res->number_of_id_entries); - *count = rescnt; - - /* allocate WinResource's */ - wr = (WinResource *)malloc(sizeof(WinResource) * rescnt); - - /* fill in the WinResource's */ - for (c = 0; c < rescnt; c++) { - RETURN_IF_BAD_POINTER(NULL, dirent[c]); - wr[c].this_ = pe_res; - wr[c].level = level; - wr[c].is_directory = ((FROM_LE_32(dirent[c].offset_to_data) & IMAGE_RESOURCE_DATA_IS_DIRECTORY) != 0); - wr[c].children = fi->first_resource + (FROM_LE_32(dirent[c].offset_to_data) & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY); - - /* fill in wr->id, wr->numeric_id */ - if (!decode_pe_resource_id(fi, wr + c, FROM_LE_32(dirent[c].name))) { - free(wr); - return NULL; - } - } - - return wr; -} - - -/** - * Return an array of WinResource's in the current - * resource level specified by _res-> - */ -Win32ResExtractor::WinResource *Win32ResExtractor::list_resources(WinLibrary *fi, WinResource *res, int *count) { - if (res != NULL && !res->is_directory) - return NULL; - - return list_pe_resources(fi, (Win32ImageResourceDirectory *) - (res == NULL ? fi->first_resource : res->children), - (res == NULL ? 0 : res->level+1), - count); -} - -/** - * Read header and get resource directory offset in a Windows library - * (AKA module). - */ -bool Win32ResExtractor::read_library(WinLibrary *fi) { - /* check for DOS header signature `MZ' */ - RETURN_IF_BAD_POINTER(false, MZ_HEADER(fi->memory)->magic); - if (FROM_LE_16(MZ_HEADER(fi->memory)->magic) == IMAGE_DOS_SIGNATURE) { - DOSImageHeader *mz_header = MZ_HEADER(fi->memory); - - RETURN_IF_BAD_POINTER(false, mz_header->lfanew); - - // Apply endian fix (currently only lfanew is used from the DOSImageHeader, - // so we don't bother to 'fix' the rest). - LE32(mz_header->lfanew); - - if (mz_header->lfanew < sizeof(DOSImageHeader)) { - error("%s: not a Windows library", _fileName.c_str()); - return false; - } - } - - /* check for NT header signature `PE' */ - RETURN_IF_BAD_POINTER(false, PE_HEADER(fi->memory)->signature); - if (FROM_LE_32(PE_HEADER(fi->memory)->signature) == IMAGE_NT_SIGNATURE) { - Win32ImageNTHeaders *pe_header; - int d; +#define ROW_BYTES(bits) ((((bits) + 31) >> 5) << 2) - // Fix image header endianess - fix_win32_image_header_endian(PE_HEADER(fi->memory)); +int Win32ResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h, + int *hotspot_x, int *hotspot_y, int *keycolor, byte **pal, int *palSize) { - /* allocate new memory */ - fi->total_size = calc_vma_size(fi); - if (fi->total_size == 0) { - /* calc_vma_size has reported error */ - return false; - } - byte *ptr = (byte *)realloc(fi->memory, fi->total_size); - assert(ptr); - fi->memory = ptr; - - /* relocate memory, start from last section */ - pe_header = PE_HEADER(fi->memory); - RETURN_IF_BAD_POINTER(false, pe_header->file_header.number_of_sections); - - /* we don't need to do OFFSET checking for the sections. - * calc_vma_size has already done that */ - for (d = pe_header->file_header.number_of_sections - 1; d >= 0; d--) { - Win32ImageSectionHeader *pe_sec = PE_SECTIONS(fi->memory) + d; - - if (pe_sec->characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) - continue; - - //if (pe_sec->virtual_address + pe_sec->size_of_raw_data > fi->total_size) - - RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->virtual_address, pe_sec->size_of_raw_data); - RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->pointer_to_raw_data, pe_sec->size_of_raw_data); - if (FROM_LE_32(pe_sec->virtual_address) != pe_sec->pointer_to_raw_data) { - memmove(fi->memory + pe_sec->virtual_address, - fi->memory + pe_sec->pointer_to_raw_data, - pe_sec->size_of_raw_data); - } - } + Common::MemoryReadStream *in = new Common::MemoryReadStream(data, datasize); - /* find resource directory */ - RETURN_IF_BAD_POINTER(false, pe_header->optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_RESOURCE]); - Win32ImageDataDirectory *dir = pe_header->optional_header.data_directory + IMAGE_DIRECTORY_ENTRY_RESOURCE; - if (dir->size == 0) { - error("%s: file contains no resources", _fileName.c_str()); - return false; - } + *hotspot_x = in->readUint16LE(); + *hotspot_y = in->readUint16LE(); - fix_win32_image_data_directory(dir); + Win32BitmapInfoHeader bitmap; - fi->first_resource = fi->memory + dir->virtual_address; - return true; - } + in->read(&bitmap, sizeof(Win32BitmapInfoHeader)); - /* other (unknown) header signature was found */ - error("%s: not a Windows library", _fileName.c_str()); - return false; -} + fix_win32_bitmap_info_header_endian(&bitmap); + if (bitmap.size < sizeof(Win32BitmapInfoHeader)) + error("bitmap header is too short"); -/** - * Calculate the total amount of memory needed for a 32-bit Windows - * module. Returns -1 if file was too small. - */ -int Win32ResExtractor::calc_vma_size(WinLibrary *fi) { - Win32ImageSectionHeader *seg; - int c, segcount, size; - - size = 0; - RETURN_IF_BAD_POINTER(-1, PE_HEADER(fi->memory)->file_header.number_of_sections); - segcount = PE_HEADER(fi->memory)->file_header.number_of_sections; - - /* If there are no segments, just process file like it is. - * This is (probably) not the right thing to do, but problems - * will be delt with later anyway. - */ - if (segcount == 0) - return fi->total_size; - - seg = PE_SECTIONS(fi->memory); - RETURN_IF_BAD_POINTER(-1, *seg); - for (c = 0; c < segcount; c++) { - RETURN_IF_BAD_POINTER(0, *seg); - fix_win32_image_section_header(seg); - - size = MAX((uint32)size, seg->virtual_address + seg->size_of_raw_data); - /* I have no idea what misc.virtual_size is for... */ - size = MAX((uint32)size, seg->virtual_address + seg->misc.virtual_size); - seg++; - } + if (bitmap.compression != 0) + error("compressed image data not supported"); - return size; -} + if (bitmap.x_pels_per_meter != 0) + error("x_pels_per_meter field in bitmap should be zero"); -Win32ResExtractor::WinResource *Win32ResExtractor::find_with_resource_array(WinLibrary *fi, WinResource *wr, const char *id) { - int c, rescnt; - WinResource *return_wr; + if (bitmap.y_pels_per_meter != 0) + error("y_pels_per_meter field in bitmap should be zero"); - wr = list_resources(fi, wr, &rescnt); - if (wr == NULL) - return NULL; + if (bitmap.clr_important != 0) + error("clr_important field in bitmap should be zero"); - for (c = 0; c < rescnt; c++) { - if (compare_resource_id(&wr[c], id)) { - /* duplicate WinResource and return it */ - return_wr = (WinResource *)malloc(sizeof(WinResource)); - memcpy(return_wr, &wr[c], sizeof(WinResource)); + if (bitmap.planes != 1) + error("planes field in bitmap should be one"); - /* free old WinResource */ - free(wr); - return return_wr; - } + Win32RGBQuad *palette = NULL; + uint32 palette_count = 0; + if (bitmap.clr_used != 0 || bitmap.bit_count < 24) { + palette_count = (bitmap.clr_used != 0 ? bitmap.clr_used : 1 << bitmap.bit_count); + palette = (Win32RGBQuad *)malloc(sizeof(Win32RGBQuad) * palette_count); + in->read(palette, sizeof(Win32RGBQuad) * palette_count); } - return NULL; -} + uint32 width = bitmap.width; + uint32 height = ABS(bitmap.height) / 2; -Win32ResExtractor::WinResource *Win32ResExtractor::find_resource(WinLibrary *fi, const char *type, const char *name, const char *language, int *level) { - WinResource *wr; + uint32 image_size = height * ROW_BYTES(width * bitmap.bit_count); + uint32 mask_size = height * ROW_BYTES(width); - *level = 0; - if (type == NULL) - return NULL; - wr = find_with_resource_array(fi, NULL, type); - if (wr == NULL || !wr->is_directory) - return wr; - - *level = 1; - if (name == NULL) - return wr; - wr = find_with_resource_array(fi, wr, name); - if (wr == NULL || !wr->is_directory) - return wr; - - *level = 2; - if (language == NULL) - return wr; - wr = find_with_resource_array(fi, wr, language); - return wr; -} - -#define ROW_BYTES(bits) ((((bits) + 31) >> 5) << 2) - - -int Win32ResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h, - int *hotspot_x, int *hotspot_y, int *keycolor, byte **pal, int *palSize) { - Win32CursorIconFileDir dir; - Win32CursorIconFileDirEntry *entries = NULL; - uint32 offset; - uint32 c, d; - int completed; - int matched = 0; - Common::MemoryReadStream *in = new Common::MemoryReadStream(data, datasize); - - if (!in->read(&dir, sizeof(Win32CursorIconFileDir)- sizeof(Win32CursorIconFileDirEntry))) - goto cleanup; - fix_win32_cursor_icon_file_dir_endian(&dir); - - if (dir.reserved != 0) { - error("not an icon or cursor file (reserved non-zero)"); - goto cleanup; - } - if (dir.type != 1 && dir.type != 2) { - error("not an icon or cursor file (wrong type)"); - goto cleanup; - } + byte *image_data = (byte *)malloc(image_size); + in->read(image_data, image_size); - entries = (Win32CursorIconFileDirEntry *)malloc(dir.count * sizeof(Win32CursorIconFileDirEntry)); - for (c = 0; c < dir.count; c++) { - if (!in->read(&entries[c], sizeof(Win32CursorIconFileDirEntry))) - goto cleanup; - fix_win32_cursor_icon_file_dir_entry_endian(&entries[c]); - if (entries[c].reserved != 0) - error("reserved is not zero"); - } + byte *mask_data = (byte *)malloc(mask_size); + in->read(mask_data, mask_size); - offset = sizeof(Win32CursorIconFileDir) + (dir.count - 1) * (sizeof(Win32CursorIconFileDirEntry)); - - for (completed = 0; completed < dir.count; ) { - uint32 min_offset = 0x7fffffff; - int previous = completed; - - for (c = 0; c < dir.count; c++) { - if (entries[c].dib_offset == offset) { - Win32BitmapInfoHeader bitmap; - Win32RGBQuad *palette = NULL; - uint32 palette_count = 0; - uint32 image_size, mask_size; - uint32 width, height; - byte *image_data = NULL, *mask_data = NULL; - byte *row = NULL; - - if (!in->read(&bitmap, sizeof(Win32BitmapInfoHeader))) - goto local_cleanup; - - fix_win32_bitmap_info_header_endian(&bitmap); - if (bitmap.size < sizeof(Win32BitmapInfoHeader)) { - error("bitmap header is too short"); - goto local_cleanup; - } - if (bitmap.compression != 0) { - error("compressed image data not supported"); - goto local_cleanup; - } - if (bitmap.x_pels_per_meter != 0) - error("x_pels_per_meter field in bitmap should be zero"); - if (bitmap.y_pels_per_meter != 0) - error("y_pels_per_meter field in bitmap should be zero"); - if (bitmap.clr_important != 0) - error("clr_important field in bitmap should be zero"); - if (bitmap.planes != 1) - error("planes field in bitmap should be one"); - if (bitmap.size != sizeof(Win32BitmapInfoHeader)) { - uint32 skip = bitmap.size - sizeof(Win32BitmapInfoHeader); - error("skipping %d bytes of extended bitmap header", skip); - in->seek(skip, SEEK_CUR); - } - offset += bitmap.size; - - if (bitmap.clr_used != 0 || bitmap.bit_count < 24) { - palette_count = (bitmap.clr_used != 0 ? bitmap.clr_used : 1 << bitmap.bit_count); - palette = (Win32RGBQuad *)malloc(sizeof(Win32RGBQuad) * palette_count); - if (!in->read(palette, sizeof(Win32RGBQuad) * palette_count)) - goto local_cleanup; - offset += sizeof(Win32RGBQuad) * palette_count; - } - - width = bitmap.width; - height = ABS(bitmap.height)/2; - - image_size = height * ROW_BYTES(width * bitmap.bit_count); - mask_size = height * ROW_BYTES(width); - - if (entries[c].dib_size != bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad)) - debugC(DEBUG_RESOURCE, "incorrect total size of bitmap (%d specified; %d real)", - entries[c].dib_size, - (int)(bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad)) - ); - - image_data = (byte *)malloc(image_size); - if (!in->read(image_data, image_size)) - goto local_cleanup; - - mask_data = (byte *)malloc(mask_size); - if (!in->read(mask_data, mask_size)) - goto local_cleanup; - - offset += image_size; - offset += mask_size; - completed++; - matched++; - - *hotspot_x = entries[c].hotspot_x; - *hotspot_y = entries[c].hotspot_y; - *w = width; - *h = height; - *keycolor = 0; - *cursor = (byte *)malloc(width * height); - - row = (byte *)malloc(width * 4); - - for (d = 0; d < height; d++) { - uint32 x; - uint32 y = (bitmap.height < 0 ? d : height - d - 1); - uint32 imod = y * (image_size / height) * 8 / bitmap.bit_count; - uint32 mmod = y * (mask_size / height) * 8; - - for (x = 0; x < width; x++) { - - uint32 color = simple_vec(image_data, x + imod, bitmap.bit_count); - - // We set up cursor palette for default cursor, so use it - if (!simple_vec(mask_data, x + mmod, 1)) { - if (color) { - cursor[0][width * d + x] = 254; // white - } else { - cursor[0][width * d + x] = 253; // black - } - } else { - cursor[0][width * d + x] = 255; // transparent - } - /* - - if (bitmap.bit_count <= 16) { - if (color >= palette_count) { - error("color out of range in image data"); - goto local_cleanup; - } - row[4*x+0] = palette[color].red; - row[4*x+1] = palette[color].green; - row[4*x+2] = palette[color].blue; - - } else { - row[4*x+0] = (color >> 16) & 0xFF; - row[4*x+1] = (color >> 8) & 0xFF; - row[4*x+2] = (color >> 0) & 0xFF; - } - if (bitmap.bit_count == 32) - row[4*x+3] = (color >> 24) & 0xFF; - else - row[4*x+3] = simple_vec(mask_data, x + mmod, 1) ? 0 : 0xFF; - */ - } - - } - - free(row); - free(palette); - if (image_data != NULL) { - free(image_data); - free(mask_data); - } - continue; - - local_cleanup: - - free(row); - free(palette); - if (image_data != NULL) { - free(image_data); - free(mask_data); - } - goto cleanup; + + *w = width; + *h = height; + *keycolor = 0; + *cursor = (byte *)malloc(width * height); + + byte *row = (byte *)malloc(width * 4); + + for (uint32 d = 0; d < height; d++) { + uint32 y = (bitmap.height < 0 ? d : height - d - 1); + uint32 imod = y * (image_size / height) * 8 / bitmap.bit_count; + uint32 mmod = y * (mask_size / height) * 8; + + for (uint32 x = 0; x < width; x++) { + uint32 color = simple_vec(image_data, x + imod, bitmap.bit_count); + + // HACK: Ignore the actual cursor palette and use SCUMM's + if (!simple_vec(mask_data, x + mmod, 1)) { + if (color) + cursor[0][width * d + x] = 254; // white + else + cursor[0][width * d + x] = 253; // black } else { - if (entries[c].dib_offset > offset) - min_offset = MIN(min_offset, entries[c].dib_offset); + cursor[0][width * d + x] = 255; // transparent } } - if (previous == completed) { - if (min_offset < offset) { - error("offset of bitmap header incorrect (too low)"); - goto cleanup; - } - assert(min_offset != 0x7fffffff); - debugC(DEBUG_RESOURCE, "skipping %d bytes of garbage at %d", min_offset-offset, offset); - in->seek(min_offset - offset, SEEK_CUR); - offset = min_offset; - } } - free(entries); - return matched; - -cleanup: + free(row); + free(palette); + if (image_data != NULL) { + free(image_data); + free(mask_data); + } - free(entries); - return -1; + return 1; } uint32 Win32ResExtractor::simple_vec(byte *data, uint32 ofs, byte size) { @@ -1055,11 +269,13 @@ uint32 Win32ResExtractor::simple_vec(byte *data, uint32 ofs, byte size) { return 0; } -void Win32ResExtractor::fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj) { - LE16(obj->reserved); - LE16(obj->type); - LE16(obj->count); -} +#if defined(SCUMM_LITTLE_ENDIAN) +#define LE16(x) +#define LE32(x) +#elif defined(SCUMM_BIG_ENDIAN) +#define LE16(x) ((x) = TO_LE_16(x)) +#define LE32(x) ((x) = TO_LE_32(x)) +#endif void Win32ResExtractor::fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj) { LE32(obj->size); @@ -1075,76 +291,8 @@ void Win32ResExtractor::fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeade LE32(obj->clr_important); } -void Win32ResExtractor::fix_win32_cursor_icon_file_dir_entry_endian(Win32CursorIconFileDirEntry *obj) { - LE16(obj->hotspot_x); - LE16(obj->hotspot_y); - LE32(obj->dib_size); - LE32(obj->dib_offset); -} - -void Win32ResExtractor::fix_win32_image_section_header(Win32ImageSectionHeader *obj) { - LE32(obj->misc.physical_address); - LE32(obj->virtual_address); - LE32(obj->size_of_raw_data); - LE32(obj->pointer_to_raw_data); - LE32(obj->pointer_to_relocations); - LE32(obj->pointer_to_linenumbers); - LE16(obj->number_of_relocations); - LE16(obj->number_of_linenumbers); - LE32(obj->characteristics); -} - -/* fix_win32_image_header_endian: - * NOTE: This assumes that the optional header is always available. - */ -void Win32ResExtractor::fix_win32_image_header_endian(Win32ImageNTHeaders *obj) { - LE32(obj->signature); - LE16(obj->file_header.machine); - LE16(obj->file_header.number_of_sections); - LE32(obj->file_header.time_date_stamp); - LE32(obj->file_header.pointer_to_symbol_table); - LE32(obj->file_header.number_of_symbols); - LE16(obj->file_header.size_of_optional_header); - LE16(obj->file_header.characteristics); - - // FIXME: Does this assert ever trigger? If so, we should modify this function - // to properly deal with it. - assert(obj->file_header.size_of_optional_header >= sizeof(obj->optional_header)); - LE16(obj->optional_header.magic); - LE32(obj->optional_header.size_of_code); - LE32(obj->optional_header.size_of_initialized_data); - LE32(obj->optional_header.size_of_uninitialized_data); - LE32(obj->optional_header.address_of_entry_point); - LE32(obj->optional_header.base_of_code); - LE32(obj->optional_header.base_of_data); - LE32(obj->optional_header.image_base); - LE32(obj->optional_header.section_alignment); - LE32(obj->optional_header.file_alignment); - LE16(obj->optional_header.major_operating_system_version); - LE16(obj->optional_header.minor_operating_system_version); - LE16(obj->optional_header.major_image_version); - LE16(obj->optional_header.minor_image_version); - LE16(obj->optional_header.major_subsystem_version); - LE16(obj->optional_header.minor_subsystem_version); - LE32(obj->optional_header.win32_version_value); - LE32(obj->optional_header.size_of_image); - LE32(obj->optional_header.size_of_headers); - LE32(obj->optional_header.checksum); - LE16(obj->optional_header.subsystem); - LE16(obj->optional_header.dll_characteristics); - LE32(obj->optional_header.size_of_stack_reserve); - LE32(obj->optional_header.size_of_stack_commit); - LE32(obj->optional_header.size_of_heap_reserve); - LE32(obj->optional_header.size_of_heap_commit); - LE32(obj->optional_header.loader_flags); - LE32(obj->optional_header.number_of_rva_and_sizes); -} - -void Win32ResExtractor::fix_win32_image_data_directory(Win32ImageDataDirectory *obj) { - LE32(obj->virtual_address); - LE32(obj->size); -} - +#undef LE16 +#undef LE32 MacResExtractor::MacResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) { _resMgr = NULL; diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h index 6b4c3fe493..9dddc96f23 100644 --- a/engines/scumm/he/resource_he.h +++ b/engines/scumm/he/resource_he.h @@ -4,7 +4,7 @@ * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * - * Parts of this code are heavily based on: + * Parts of this code are based on: * icoutils - A set of programs dealing with MS Windows icons and cursors. * Copyright (C) 1998-2001 Oskar Liljeblad * @@ -31,89 +31,10 @@ #define SCUMM_HE_RESOURCE_HE_H #include "common/macresman.h" +#include "common/pe_exe.h" namespace Scumm { -#define WINRES_ID_MAXLEN (256) - -/* - * Definitions - */ - -#define MZ_HEADER(x) ((DOSImageHeader *)(x)) - -#define STRIP_RES_ID_FORMAT(x) (x != NULL && (x[0] == '-' || x[0] == '+') ? ++x : x) - -#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 -#define IMAGE_SIZEOF_SHORT_NAME 8 - -#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 -#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 - -#define PE_HEADER(module) \ - ((Win32ImageNTHeaders*)((byte *)(module) + \ - (((DOSImageHeader*)(module))->lfanew))) - -#define PE_SECTIONS(module) \ - ((Win32ImageSectionHeader *)((byte *) &PE_HEADER(module)->optional_header + \ - PE_HEADER(module)->file_header.size_of_optional_header)) - -#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */ -#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */ - -/* The following symbols below and another group a few lines below are defined in - * the windows header, at least in wince and most likely in plain win32 as well. - * Defining them out silences a redefinition warning in gcc. - * If the same problem arises in win32 builds as well, please replace - * _WIN32_WCE with _WIN32 which is also defined in the wince platform. - */ -#ifndef _WIN32_WCE -#define IMAGE_SCN_CNT_CODE 0x00000020 -#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 -#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 -#endif - -// Only IMAGE_DIRECTORY_ENTRY_RESOURCE is used: -#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 -#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 -#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 -#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 -#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 -#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 -#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 -#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 -#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* (MIPS GP) */ -#define IMAGE_DIRECTORY_ENTRY_TLS 9 -#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 -#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 -#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */ -#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 -#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 - -#ifndef _WIN32_WCE -// Only RT_GROUP_CURSOR and RT_GROUP_ICON are used -#define RT_CURSOR 1 -#define RT_BITMAP 2 -#define RT_ICON 3 -#define RT_MENU 4 -#define RT_DIALOG 5 -#define RT_STRING 6 -#define RT_FONTDIR 7 -#define RT_FONT 8 -#define RT_ACCELERATOR 9 -#define RT_RCDATA 10 -#define RT_MESSAGELIST 11 -#define RT_GROUP_CURSOR 12 -#define RT_GROUP_ICON 14 -#endif - -#define RETURN_IF_BAD_POINTER(r, x) \ - if (!check_offset(fi->memory, fi->total_size, _fileName.c_str(), &(x), sizeof(x))) \ - return (r); -#define RETURN_IF_BAD_OFFSET(r, x, s) \ - if (!check_offset(fi->memory, fi->total_size, _fileName.c_str(), x, s)) \ - return (r); - class ScummEngine_v70he; class ResExtractor { @@ -154,7 +75,7 @@ public: }; class Win32ResExtractor : public ResExtractor { - public: +public: Win32ResExtractor(ScummEngine_v70he *scumm); ~Win32ResExtractor() {} int extractResource(int id, byte **data); @@ -162,81 +83,15 @@ class Win32ResExtractor : public ResExtractor { int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h, int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize); - private: - int extractResource_(const char *resType, char *resName, byte **data); +private: + Common::PEResources _exe; + /* * Structures */ #include "common/pack-start.h" // START STRUCT PACKING - struct WinLibrary { - Common::SeekableReadStream *file; - byte *memory; - byte *first_resource; - int total_size; - } PACKED_STRUCT; - - struct WinResource { - char id[256]; - void *this_; - void *children; - int level; - bool numeric_id; - bool is_directory; - - Common::String getQuotedResourceId() const; - } PACKED_STRUCT; - - - struct Win32IconResDir { - byte width; - byte height; - byte color_count; - byte reserved; - } PACKED_STRUCT; - - struct Win32CursorDir { - uint16 width; - uint16 height; - } PACKED_STRUCT; - - struct Win32CursorIconDirEntry { - union { - Win32IconResDir icon; - Win32CursorDir cursor; - } res_info; - uint16 plane_count; - uint16 bit_count; - uint32 bytes_in_res; - uint16 res_id; - } PACKED_STRUCT; - - struct Win32CursorIconDir { - uint16 reserved; - uint16 type; - uint16 count; - Win32CursorIconDirEntry entries[1]; - } PACKED_STRUCT; - - struct Win32CursorIconFileDirEntry { - byte width; - byte height; - byte color_count; - byte reserved; - uint16 hotspot_x; - uint16 hotspot_y; - uint32 dib_size; - uint32 dib_offset; - } PACKED_STRUCT; - - struct Win32CursorIconFileDir { - uint16 reserved; - uint16 type; - uint16 count; - Win32CursorIconFileDirEntry entries[1]; - } PACKED_STRUCT; - struct Win32BitmapInfoHeader { uint32 size; int32 width; @@ -258,163 +113,10 @@ class Win32ResExtractor : public ResExtractor { byte reserved; } PACKED_STRUCT; - struct Win32ImageResourceDirectoryEntry { - uint32 name; - uint32 offset_to_data; - } PACKED_STRUCT; - - struct Win16NETypeInfo { - uint16 type_id; - uint16 count; - uint32 resloader; // FARPROC16 - smaller? uint16? - } PACKED_STRUCT; - - struct DOSImageHeader { - uint16 magic; - uint16 cblp; - uint16 cp; - uint16 crlc; - uint16 cparhdr; - uint16 minalloc; - uint16 maxalloc; - uint16 ss; - uint16 sp; - uint16 csum; - uint16 ip; - uint16 cs; - uint16 lfarlc; - uint16 ovno; - uint16 res[4]; - uint16 oemid; - uint16 oeminfo; - uint16 res2[10]; - uint32 lfanew; - } PACKED_STRUCT; - - struct Win32ImageFileHeader { - uint16 machine; - uint16 number_of_sections; - uint32 time_date_stamp; - uint32 pointer_to_symbol_table; - uint32 number_of_symbols; - uint16 size_of_optional_header; - uint16 characteristics; - } PACKED_STRUCT; - - struct Win32ImageDataDirectory { - uint32 virtual_address; - uint32 size; - } PACKED_STRUCT; - - struct Win32ImageOptionalHeader { - uint16 magic; - byte major_linker_version; - byte minor_linker_version; - uint32 size_of_code; - uint32 size_of_initialized_data; - uint32 size_of_uninitialized_data; - uint32 address_of_entry_point; - uint32 base_of_code; - uint32 base_of_data; - uint32 image_base; - uint32 section_alignment; - uint32 file_alignment; - uint16 major_operating_system_version; - uint16 minor_operating_system_version; - uint16 major_image_version; - uint16 minor_image_version; - uint16 major_subsystem_version; - uint16 minor_subsystem_version; - uint32 win32_version_value; - uint32 size_of_image; - uint32 size_of_headers; - uint32 checksum; - uint16 subsystem; - uint16 dll_characteristics; - uint32 size_of_stack_reserve; - uint32 size_of_stack_commit; - uint32 size_of_heap_reserve; - uint32 size_of_heap_commit; - uint32 loader_flags; - uint32 number_of_rva_and_sizes; - Win32ImageDataDirectory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; - } PACKED_STRUCT; - - struct Win32ImageNTHeaders { - uint32 signature; - Win32ImageFileHeader file_header; - Win32ImageOptionalHeader optional_header; - } PACKED_STRUCT; - - struct Win32ImageSectionHeader { - byte name[IMAGE_SIZEOF_SHORT_NAME]; - union { - uint32 physical_address; - uint32 virtual_size; - } misc; - uint32 virtual_address; - uint32 size_of_raw_data; - uint32 pointer_to_raw_data; - uint32 pointer_to_relocations; - uint32 pointer_to_linenumbers; - uint16 number_of_relocations; - uint16 number_of_linenumbers; - uint32 characteristics; - } PACKED_STRUCT; - - struct Win32ImageResourceDataEntry { - uint32 offset_to_data; - uint32 size; - uint32 code_page; - uint32 resource_handle; - } PACKED_STRUCT; - - struct Win32ImageResourceDirectory { - uint32 characteristics; - uint32 time_date_stamp; - uint16 major_version; - uint16 minor_version; - uint16 number_of_named_entries; - uint16 number_of_id_entries; - } PACKED_STRUCT; - #include "common/pack-end.h" // END STRUCT PACKING -/* - * Function Prototypes - */ - - WinResource *list_resources(WinLibrary *, WinResource *, int *); - bool read_library(WinLibrary *); - WinResource *find_resource(WinLibrary *, const char *, const char *, const char *, int *); - byte *get_resource_entry(WinLibrary *, WinResource *, int *); - int do_resources(WinLibrary *, const char *, char *, char *, byte **); - bool compare_resource_id(WinResource *, const char *); - const char *res_type_string_to_id(const char *); - - const char *res_type_id_to_string(int); - char *get_destination_name(WinLibrary *, char *, char *, char *); - - byte *extract_resource(WinLibrary *, WinResource *, int *, bool *, char *, char *, bool); - int extract_resources(WinLibrary *, WinResource *, WinResource *, WinResource *, WinResource *, byte **); - byte *extract_group_icon_cursor_resource(WinLibrary *, WinResource *, char *, int *, bool); - - bool decode_pe_resource_id(WinLibrary *, WinResource *, uint32); - WinResource *list_pe_resources(WinLibrary *, Win32ImageResourceDirectory *, int, int *); - int calc_vma_size(WinLibrary *); - int do_resources_recurs(WinLibrary *, WinResource *, WinResource *, WinResource *, WinResource *, const char *, char *, char *, byte **); - WinResource *find_with_resource_array(WinLibrary *, WinResource *, const char *); - - bool check_offset(byte *, int, const char *, void *, int); - uint32 simple_vec(byte *data, uint32 ofs, byte size); - - void fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj); void fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj); - void fix_win32_cursor_icon_file_dir_entry_endian(Win32CursorIconFileDirEntry *obj); - void fix_win32_image_section_header(Win32ImageSectionHeader *obj); - void fix_win32_image_header_endian(Win32ImageNTHeaders *obj); - void fix_win32_image_data_directory(Win32ImageDataDirectory *obj); }; class MacResExtractor : public ResExtractor { -- cgit v1.2.3