/***** $Source: d:\gunther\source\grc/RCS/rcompile.c,v $ $Author: gunther $ $Date: 1996/01/02 23:17:24 $ $Revision: 1.6 $ Changed by: Fred Kiefer (kiefer@isys.de) 1996/6/2 *****/ #include #include #include #include #include #include #include "rcompile.h" #include "wstring.h" #include "rcutils.h" #include "portio.h" #include "resfile.h" FILE *res; node *stringTable; node *fontTable; int iconComponents = 1; int cursorComponents = 1; int readFullFile(char *filename, char **buffer, DWORD *size) { FILE *bmp; *size = filesize(filename); *buffer = (char *) xmalloc(*size); bmp = fopen(filename, "rb"); if(!bmp) { open_error(filename); free(*buffer); return GRC_ERR_OPEN; } if(fread(*buffer, 1, *size, bmp) != *size) { read_error(filename); free(*buffer); fclose(bmp); return GRC_ERR_READ; } fclose(bmp); return GRC_OK; } /*-------------------------------------------------- getBitmap() create the bitmap resource format Parameters: name UNICODE or WCHAR id filename name of .bmp file memflags some optional memory flags Returns: GRC_OK, if successful an error code otherwise ---------------------------------------------------*/ int getBitmap(wchar_t *name, int memflags, ResourceTail *tail, char *filename) { DWORD HeaderSize; DWORD DataSize; wchar_t resourceType[2] = { INVAL_WCHAR, RT_BITMAP }; char *buffer = NULL; char *ptr; int retcode; int padding = 0; int delta = 14; /* sizeof(BITMAPFILEHEADER) */ char *fullfilename = search_include(filename); if((retcode = readFullFile(fullfilename, &buffer, &DataSize)) != GRC_OK) return retcode; tail->MemoryFlags = memflags; DataSize -= delta; ptr = buffer + delta; retcode = writeResourceHeader(&DataSize, &HeaderSize, resourceType, name, tail, res); if(retcode != HeaderSize){ write_error("resource file"); free(buffer); return GRC_ERR_WRITE | GRC_ERR_FATAL; } if (fwrite(ptr, sizeof(char), DataSize, res) != DataSize) { write_error("resource file"); free(buffer); return GRC_ERR_WRITE | GRC_ERR_FATAL; } free(buffer); padding = PADDING(DataSize, 4); if (!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } return GRC_OK; } /*-------------------------------------------------- getIcon() create the icon resource format Parameters: name UNICODE or WCHAR id filename name of .ico file memflags some optional memory flags Returns: GRC_OK, if successful an error code otherwise ---------------------------------------------------*/ int getIcon(wchar_t *name, int memflags, ResourceTail *tail, char *filename) { DWORD HeaderSize; DWORD DataSize; wchar_t resourceType[2] = { INVAL_WCHAR, RT_ICON }; char *buffer = NULL; int padding = 0; FILE *ico; IconHeader fileheader; ICONDIRENTRY *file_components; IconResourceDirectory *group_component; int i; int retcode; char *fullfilename = search_include(filename); tail->MemoryFlags = memflags; /* read the ICONHEADER structure */ if(!(ico = fopen(fullfilename, "rb"))) { open_error(filename); return GRC_ERR_OPEN | GRC_ERR_FATAL; } if(readIconHeader(&fileheader, ico) != ICONHEADER_SIZE) { fclose(ico); read_error(filename); return GRC_ERR_READ | GRC_ERR_FATAL; } if(fileheader.wType != 1) { fclose(ico); err_msg(GRC_err_invalid_icon_file); return GRC_ERR_INVALID_FILE | GRC_ERR_FATAL; } file_components = (ICONDIRENTRY *) xmalloc(ICONDIRENTRY_SIZE * fileheader.wCount); /* read the component header entries */ for(i = 0; i < fileheader.wCount; i++) { if(readICONDIRENTRY(&file_components[i], ico) != ICONDIRENTRY_SIZE) { fclose(ico); free(file_components); read_error(filename); return GRC_ERR_READ | GRC_ERR_FATAL; } } /* write the component resources to the .res file */ for(i = 0; i < fileheader.wCount; i++) { wchar_t resourceName[2] = {INVAL_WCHAR, (wchar_t) (i + iconComponents)}; HeaderSize = 0x20; DataSize = file_components[i].dwBytesInRes; buffer = (char *) xmalloc(DataSize); if(fseek(ico, file_components[i].dwImageOffset, SEEK_SET)) { fclose(ico); free(file_components); free(buffer); seek_error(filename); return GRC_ERR_WRITE | GRC_ERR_FATAL; } /* read the ICON bitmap data */ if(fread(buffer, sizeof(char), DataSize, ico) != DataSize) { fclose(ico); free(file_components); free(buffer); read_error(filename); return GRC_ERR_WRITE | GRC_ERR_FATAL; } /* write the resource header for ICON component */ retcode = writeResourceHeader(&DataSize, &HeaderSize, resourceType, resourceName, tail, res); if(retcode != HeaderSize) { fclose(ico); free(file_components); free(buffer); write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } /* write the bitmap data for ICON component */ if(fwrite(buffer, 1, DataSize, res) != DataSize) { fclose(ico); free(file_components); free(buffer); write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } free(buffer); /* add DWORD padding stuff */ padding = PADDING(DataSize, 4); if(!writePadding(padding, res)) { fclose(ico); free(file_components); write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } fclose(ico); /* write the icon-group resource */ resourceType[0] = INVAL_WCHAR; resourceType[1] = RT_GROUP_ICON; group_component = (IconResourceDirectory *) xmalloc(IconResourceDirectory_SIZE * fileheader.wCount); DataSize = IconResourceDirectory_SIZE * fileheader.wCount + ICONHEADER_SIZE; for(i = 0; i < fileheader.wCount; i++) { int colors; group_component[i].bWidth = file_components[i].bWidth; group_component[i].bHeight = file_components[i].bHeight; group_component[i].bColorCount = colors = file_components[i].bColorCount; group_component[i].bReserved = file_components[i].bReserved; group_component[i].wPlanes = 1; /* file_components[i].wPlanes; */ group_component[i].wBitCount = int_log2(colors); /* file_components[i].wBitCount; */ group_component[i].lBytesInRes = file_components[i].dwBytesInRes; group_component[i].wNameOrdinal = i + iconComponents; } free(file_components); tail->MemoryFlags = DISCARDABLE | MOVEABLE | PURE; /* write the resource header */ retcode = writeResourceHeader(&DataSize, &HeaderSize, resourceType, name, tail, res); if(retcode != HeaderSize) { free(group_component); write_error("resource file"); return GRC_ERR_MEM | GRC_ERR_FATAL; } /* write the icon header block */ if(writeIconHeader(&fileheader, res) != ICONHEADER_SIZE) { free(group_component); write_error("resource file"); return GRC_ERR_MEM | GRC_ERR_FATAL; } /* write the group component blocks */ for(i = 0; i < fileheader.wCount; i++) { if(writeResourceDirectory(&group_component[i], res) != IconResourceDirectory_SIZE) { free(group_component); write_error("resource file"); return GRC_ERR_MEM | GRC_ERR_FATAL; } } free(group_component); iconComponents += fileheader.wCount; padding = PADDING(DataSize, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } return GRC_OK; } /*-------------------------------------------------- getCursor() create the cursor resource format Parameters: name UNICODE or WCHAR id filename name of .cur file memflags some optional memory flags Returns: GRC_OK, if successful an error code otherwise ---------------------------------------------------*/ int getCursor(wchar_t *name, int memflags, ResourceTail *tail, char *filename) { DWORD HeaderSize; DWORD DataSize; wchar_t resourceType[2] = { INVAL_WCHAR, RT_CURSOR }; char *buffer = NULL; int padding = 0; FILE *ico; IconHeader fileheader; CURSORDIRENTRY *file_components; CursorResourceDirectory *group_component; CursorComponent hotspot; int i; int retcode; char *fullfilename = search_include(filename); tail->MemoryFlags = memflags; /* read the ICONHEADER structure */ if(!(ico = fopen(fullfilename, "rb"))) { open_error(filename); return GRC_ERR_OPEN | GRC_ERR_FATAL; } if(readIconHeader(&fileheader, ico) != ICONHEADER_SIZE) { read_error(filename); fclose(ico); return GRC_ERR_OPEN | GRC_ERR_FATAL; } if(fileheader.wType != 2) { fclose(ico); err_msg(GRC_err_invalid_cursor_file); return GRC_ERR_INVALID_FILE; } file_components = (CURSORDIRENTRY *) xmalloc(sizeof(CURSORDIRENTRY) * fileheader.wCount); /* read the component header entries */ for(i = 0; i < fileheader.wCount; i++) { if(readCURSORDIRENTRY(&file_components[i], ico) != CURSORDIRENTRY_SIZE) { read_error(filename); free(file_components); fclose(ico); return GRC_ERR_SEEK | GRC_ERR_FATAL; } } /* write the component resources to the .res file */ for(i = 0; i < fileheader.wCount; i++) { wchar_t resourceName[2] = {INVAL_WCHAR, (wchar_t) (i + cursorComponents)}; DataSize = file_components[i].lBytesInRes; buffer = (char *) xmalloc(DataSize); hotspot.xHotspot = file_components[i].wXHotspot; hotspot.yHotspot = file_components[i].wYHotspot; if(fseek(ico, file_components[i].dwImageOffset, SEEK_SET)) { seek_error(filename); free(buffer); free(file_components); fclose(ico); return GRC_ERR_SEEK | GRC_ERR_FATAL; } if(fread(buffer, 1, DataSize, ico) != DataSize) { read_error(filename); free(buffer); free(file_components); fclose(ico); return GRC_ERR_READ | GRC_ERR_FATAL; } DataSize += CursorComponent_SIZE; retcode = writeResourceHeader(&DataSize, &HeaderSize, resourceType, resourceName, tail, res); if(retcode != HeaderSize) { write_error("resource file"); free(buffer); free(file_components); fclose(ico); return GRC_ERR_WRITE | GRC_ERR_FATAL; } DataSize -= CursorComponent_SIZE; if(writeCursorComponent(&hotspot, res) != CursorComponent_SIZE) { write_error("resource file"); free(buffer); free(file_components); fclose(ico); return GRC_ERR_WRITE | GRC_ERR_FATAL; } if(fwrite(buffer, 1, DataSize, res) != DataSize) { write_error("resource file"); free(buffer); free(file_components); fclose(ico); return GRC_ERR_WRITE | GRC_ERR_FATAL; } free(buffer); padding = PADDING(DataSize, 4); if(!writePadding(padding, res)) { write_error("resource file"); free(file_components); fclose(ico); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } fclose(ico); /* write the cursor-group resource */ resourceType[0] = INVAL_WCHAR; resourceType[1] = RT_GROUP_CURSOR; group_component = (CursorResourceDirectory *) xmalloc(CursorResourceDirectory_SIZE * fileheader.wCount); DataSize = CursorResourceDirectory_SIZE * fileheader.wCount + ICONHEADER_SIZE; for(i = 0; i < fileheader.wCount; i++) { group_component[i].wWidth = file_components[i].bWidth; group_component[i].wHeight = 2 * file_components[i].bHeight; group_component[i].wPlanes = 1; group_component[i].wBitCount = 1; /* group_component[i].wBitCount = 4; */ group_component[i].lBytesInRes = file_components[i].lBytesInRes + sizeof(DWORD); group_component[i].wNameOrdinal = i + cursorComponents; } free(file_components); tail->MemoryFlags = DISCARDABLE | MOVEABLE | PURE; retcode = writeResourceHeader(&DataSize, &HeaderSize, resourceType, name, tail, res); if(retcode != HeaderSize) { write_error("resource file"); free(group_component); return GRC_ERR_WRITE | GRC_ERR_FATAL; } if(writeIconHeader(&fileheader, res) != ICONHEADER_SIZE) { write_error("resource file"); free(group_component); return GRC_ERR_WRITE | GRC_ERR_FATAL; } for(i = 0; i < fileheader.wCount; i++) { if(writeCursorResourceDirectory(&group_component[i], res) != CursorResourceDirectory_SIZE) { write_error("resource file"); free(group_component); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } free(group_component); cursorComponents += fileheader.wCount; padding = PADDING(DataSize, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } return GRC_OK; } /*-------------------------------------------------- getFont() create the font resource format and also saves up the font description in a list for the generation of the font dir Parameters: name UNICODE or WCHAR id filename name of .fon file memflags some optional memory flags Returns: GRC_OK, if successful an error code otherwise ---------------------------------------------------*/ int getFont(wchar_t *name, int memflags, ResourceTail *tail, char *filename) { /* DWORD HeaderSize; DWORD DataSize; wchar_t resourceType[2] = { INVAL_WCHAR, RT_FONT }; char *buffer; int padding = 0; */ return GRC_OK; } /*-------------------------------------------------- addControl() create the control resource format and add it to a temporary file which will be used by getDialog() Parameters: ctrl points to an YYSTYPE structure which contains the parsing results Returns: GRC_OK, if successful an error code otherwise ---------------------------------------------------*/ int addControl(struct_control *ctrl) { int padding = 0; int size = 0; if(writeDLGITEMTEMPLATE(&ctrl->control, res) != sizeof(DLGITEMTEMPLATE)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } size += sizeof(DLGITEMTEMPLATE); /* type information */ if(writeNameOrId(ctrl->typeID, res) != getIDlength(ctrl->typeID)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } size += getIDlength(ctrl->typeID); /* name information */ if(writeNameOrId(ctrl->nameID, res) != getIDlength(ctrl->nameID)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } size += getIDlength(ctrl->nameID); /* extra stuff */ if(!writePadding(sizeof(wchar_t), res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } size += sizeof(wchar_t); /* add padding bytes for DWORD alignment */ padding = PADDING(size, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } return GRC_OK; } int getControlSize(node *controls) { node *p; struct_control *ctrl; int size = 0; for(p = controls->next; p; p = p->next) { ctrl = (struct_control *)p->u.data; size += sizeof(DLGITEMTEMPLATE) + getIDlength(ctrl->typeID) + getIDlength(ctrl->nameID) + sizeof(wchar_t); if (p->next) size = ROUNDUP(size, 4); } return size; } /*-------------------------------------------------- getDialog() create the dialog resource structures Parameters: name UNICODE or WORD id memflags some optional memory flags x, y, cx, cy position and size of dialog options some additional options like language, version, menu, font, ... Returns: GRC_OK, if successful an error code otherwise ---------------------------------------------------*/ int getDialog(wchar_t *name, int memflags, int x, int y, int cx, int cy, struct_dialog *options, node *controls) { DWORD HeaderSize; DWORD DataSize; wchar_t resourceType[2] = { INVAL_WCHAR, RT_DIALOG }; int dlgHeaderSize; int padding = 0; DLGTEMPLATE dlg; ResourceTail *tail = &options->tail; int retcode; int ctrlCount = controls->u.count; node *p; DataSize = getControlSize(controls); dlg.style = options->style ? options->style : WS_POPUP | WS_BORDER | WS_SYSMENU; dlg.dwExtendedStyle = options->dwExtendedStyle; dlg.x = x; dlg.y = y; dlg.cx = cx; dlg.cy = cy; dlg.cdit = ctrlCount; tail->MemoryFlags = memflags ? memflags : 4144; dlgHeaderSize = sizeof(DLGTEMPLATE) + getIDlength(options->menuID) + getIDlength(options->typeID) + getIDlength(options->nameID) + ((dlg.style & DS_SETFONT) ? sizeof(wchar_t) + getIDlength(options->font.TypefaceName) : 0); DataSize += ROUNDUP(dlgHeaderSize, 4); retcode = writeResourceHeader(&DataSize, &HeaderSize, resourceType, name, tail, res); if(retcode != HeaderSize) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } retcode = writeDLGTEMPLATE(&dlg, res); retcode += writeNameOrId(options->menuID, res); retcode += writeNameOrId(options->typeID, res); retcode += writeNameOrId(options->nameID, res); if(retcode != sizeof(DLGTEMPLATE) + getIDlength(options->menuID) + getIDlength(options->typeID) + getIDlength(options->nameID)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } if(dlg.style & DS_SETFONT) writeDLGFONT(&options->font, res); padding = PADDING(dlgHeaderSize, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } for(p = controls->next; p; p = p->next) { struct_control *ctrl = (struct_control *)p->u.data; if (addControl(ctrl) != GRC_OK) { return GRC_ERR_WRITE | GRC_ERR_FATAL; } } list_free(controls, TRUE); free(options); return GRC_OK; } /*-------------------------------------------------- getMenuSize() determines the size of the resource structure of a complete menu tree Parameters: menu points to the root of the menu tree Returns: size of the menu resource data, in bytes ---------------------------------------------------*/ int getMenuSize(node *menu) { int size = 0; menuItem *mi; node *p; for(p = menu->next; p; p = p->next) { mi = (menuItem*) p->u.data; if(mi->flags & MENUFLAG_POPUP) { size += 2; size += getIDlength(mi->title); size += getMenuSize(mi->items); } else if (mi->flags & MENUFLAG_SEPARATOR) { size += 3 * sizeof(wchar_t); } else { size += 4; size += getIDlength(mi->title); } } return size; } /*-------------------------------------------------- getMenuItems() converts the menu tree to the resource format Parameters: menu points to the root of the menu tree Returns: GRC_OK, if successful an error code otherwise ---------------------------------------------------*/ int getMenuItems(node *menu) { menuItem *mi; node *p; wchar_t null[4] = { 0, 0, 0, 0 }; int retcode; for(p = menu->next; p; p = p->next) { mi = (menuItem*) p->u.data; if (!p->next) { mi->flags |= MENUFLAG_ENDMENU; } if(mi->flags & MENUFLAG_POPUP) { /* write item data */ retcode = write_int16(&mi->flags, res); retcode += writeNameOrId(mi->title, res); if(retcode != 2 + getIDlength(mi->title)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } /* write submenu data */ getMenuItems(mi->items); } else if(mi->flags & MENUFLAG_SEPARATOR) { if(fwrite(&null, sizeof(wchar_t), 3, res) != 3) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } else { retcode = write_int16(&mi->flags, res); retcode += write_int16(&mi->id, res); retcode += writeNameOrId(mi->title, res); if(retcode != 4 + getIDlength(mi->title)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } } list_free(menu, TRUE); return GRC_OK; } /*-------------------------------------------------- getMenu() creates the menu resource structure Parameters: resourceName UNICODE or WCHAR id memflags some optional memory flags tail part of the resource header menu parsing result: the menu tree Returns: GRC_OK, if successful an error code otherwise ---------------------------------------------------*/ int getMenu(wchar_t *resourceName, int memflags, ResourceTail *tail, node *menu) { DWORD HeaderSize; DWORD DataSize; wchar_t resourceType[2] = { INVAL_WCHAR, RT_MENU }; MenuHeader header; int padding = 0; int retcode; DataSize = getMenuSize(menu) + sizeof(MenuHeader); header.wVersion = 0; header.cbHeaderSize = 0; tail->MemoryFlags = memflags; retcode = writeResourceHeader(&DataSize, &HeaderSize, resourceType, resourceName, tail, res); if(retcode != HeaderSize) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } if(writeMenuHeader(&header, res) != MenuHeader_SIZE) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } if((retcode = getMenuItems(menu)) != GRC_OK) return retcode; padding = PADDING(DataSize, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } return GRC_OK; } int getStringtableSize(wchar_t **items) { int i; int size = 0; for(i = 0; i < 16; i++) { if(items[i]){ size += sizeof(wchar_t) * (items[i][0] + 1); } else { size += sizeof(wchar_t); } } return size; } int addTable(int memflags, ResourceTail *tail, node *table) { node *p; stringEntry *entry; for(p = table->next; p; p = p->next) { entry = (stringEntry *)p->u.data; entry->tail = *tail; entry->tail.MemoryFlags = memflags; list_add(stringTable, entry); } list_free(table, FALSE); return GRC_OK; } /*-------------------------------------------------- getString() creates all string resources Returns: GRC_OK, if successful an error code otherwise ---------------------------------------------------*/ int getString(node *table) { DWORD HeaderSize = 4 * sizeof(DWORD) + sizeof(ResourceTail); /* should be 0x20 */ wchar_t resourceType[2] = { INVAL_WCHAR, RT_STRING }; ResourceTail tail; wchar_t *block[16]; int j; int padding; int retcode; node *p; stringEntry *entry; for(p = table->next; p; p = p->next) { entry = (stringEntry *) p->u.data; if (entry) { DWORD DataSize; wchar_t resourceName[2] = { INVAL_WCHAR, entry->block }; int language = entry->tail.LanguageId; int blocknr = entry->block; node *q; stringEntry *entry2; int i; tail = entry->tail; for (i = 0; i < 16; i++) { block[i] = NULL; } /* the current item has to be the first item in loop */ for(q = p; q; q = q->next){ entry2 = (stringEntry *) q->u.data; if(entry2) { if((entry2->block == blocknr) && (entry2->tail.LanguageId == language)) { if(block[entry2->pos]) { yyerror("Duplicate string identifiers are not allowed.block"); verbose(("Duplicate %d pos %d", blocknr, entry2->pos)); } else { block[entry2->pos] = entry2->string; } /* remove it from table */ free(entry2); q->u.data = NULL; } } } /* write the general resource header */ DataSize = getStringtableSize(block); retcode = writeResourceHeader(&DataSize, &HeaderSize, resourceType, resourceName, &tail, res); if(retcode != HeaderSize) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } /* the header is already DWORD-aligned */ for(j = 0; j < 16; j++) { if(block[j]) { wchar_t *string = block[j]; int k; /* write and free the string data */ for(k = 0; k <= string[0]; k++) { if(write_int16(&string[k], res) != sizeof(wchar_t)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } free(block[j]); } else /* write a '00 00' word if there is no string at position j */ if(!writePadding(sizeof(wchar_t), res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } /* add padding stuff */ padding = PADDING(DataSize, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } } list_free(table, TRUE); return GRC_OK; } int getAccelerators(wchar_t *name, int memflags, ResourceTail *tail, node *table) { DWORD HeaderSize; wchar_t resourceType[2] = { INVAL_WCHAR, RT_ACCELERATOR }; DWORD DataSize = sizeof(ACCELTABLEENTRY) * table->u.count; ACCELTABLEENTRY*entry; node *p; tail->MemoryFlags = memflags; if(writeResourceHeader(&DataSize, &HeaderSize, resourceType, name, tail, res) != HeaderSize) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } for(p = table->next; p; p = p->next) { entry = (ACCELTABLEENTRY*)p->u.data; if (!p->next) { entry->fFlags |= ACC_LAST; } if(writeaccel_entry(entry, res) != sizeof(ACCELTABLEENTRY)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } list_free(table, TRUE); return GRC_OK; } int getRcdata(wchar_t *resourceType, wchar_t *name, int memflags, ResourceTail *tail, node *entries) { DWORD HeaderSize; DWORD DataSize = 0; int padding; rcdata_entry *entry; node *p; tail->MemoryFlags = memflags; for(p = entries->next; p; p = p->next) { entry = (rcdata_entry *)p->u.data; DataSize += entry->size; } if(writeResourceHeader(&DataSize, &HeaderSize, resourceType, name, tail, res) != HeaderSize) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } for(p = entries->next; p; p = p->next) { entry = (rcdata_entry *)p->u.data; if (fwrite(entry->field, 1, entry->size, res) != entry->size) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } list_free(entries, TRUE); /* add padding stuff */ padding = PADDING(DataSize, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } return GRC_OK; } int getToolbar(wchar_t *resourceType, wchar_t *name, int memflags, ResourceTail *tail, int width, int height, node *entries) { DWORD HeaderSize; DWORD DataSize = 0; int padding; rcdata_entry *entry; short head[4] = {1, 0, 0, 0}; node *p; tail->MemoryFlags = memflags; DataSize = 8 + 2 * entries->u.count; if(writeResourceHeader(&DataSize, &HeaderSize, resourceType, name, tail, res) != HeaderSize) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } head[1] = width; head[2] = height; head[3] = entries->u.count; if (fwrite(head, sizeof(short), 4, res) != 4) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } for(p = entries->next; p; p = p->next) { entry = (rcdata_entry *)p->u.data; if (fwrite(entry->field, 1, entry->size, res) != entry->size) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } } list_free(entries, TRUE); /* add padding stuff */ padding = PADDING(DataSize, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } return GRC_OK; } int getUserRC(wchar_t *resourceType, wchar_t *name, int memflags, ResourceTail *tail, char *filename) { DWORD HeaderSize; DWORD DataSize; int padding; char *buffer = NULL; int retcode; char *fullfilename = search_include(filename); if((retcode = readFullFile(fullfilename, &buffer, &DataSize)) != GRC_OK) return retcode; tail->MemoryFlags = memflags; if(writeResourceHeader(&DataSize, &HeaderSize, resourceType, name, tail, res) != HeaderSize) { write_error("resource file"); free(buffer); return GRC_ERR_WRITE | GRC_ERR_FATAL; } if (fwrite(buffer, sizeof(char), DataSize, res) != DataSize) { write_error("resource file"); free(buffer); return GRC_ERR_WRITE | GRC_ERR_FATAL; } free(buffer); /* add padding stuff */ padding = PADDING(DataSize, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } return GRC_OK; } int getVersionEntrySize(version_entry *vs) { version_entry *entry; node *p; int Size = 6; if (vs->szKey) Size += sizeof(wchar_t) * (wstrlen(vs->szKey) + 1); Size = ROUNDUP(Size, 4); Size += vs->wValueLength * (vs->wType ? sizeof(wchar_t) : 1); if (vs->entries) { for (p = vs->entries->next; p; p = p->next){ entry = (version_entry *) p->u.data; Size += getVersionEntrySize(entry); if (p->next) Size = ROUNDUP(Size, 4); } } vs->wLength = Size; return Size; } int getVersionEntry(version_entry *vs) { int padding; version_entry *entry; node *p; int Size; Size = writeVersionEntry(vs, res); /* add padding stuff */ padding = PADDING(Size, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } if (vs->entries) { for (p = vs->entries->next; p; p = p->next){ entry = (version_entry *) p->u.data; Size = getVersionEntry(entry); } list_free(vs->entries, TRUE); } return GRC_OK; } int getVersioninfo(wchar_t *name, int memflags, ResourceTail *tail, version_entry *vs) { DWORD HeaderSize; wchar_t resourceType[2] = { INVAL_WCHAR, RT_VERSION }; DWORD DataSize; int padding; tail->MemoryFlags = memflags; DataSize = getVersionEntrySize(vs); if(writeResourceHeader(&DataSize, &HeaderSize, resourceType, name, tail, res) != HeaderSize) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } getVersionEntry(vs); /* add padding stuff */ padding = PADDING(DataSize, 4); if(!writePadding(padding, res)) { write_error("resource file"); return GRC_ERR_WRITE | GRC_ERR_FATAL; } return GRC_OK; } int StartRes(const char *resfile) { DWORD resfilePrefix[8] = { 0, 32, MAKELONG(-1, 0), MAKELONG(-1, 0), 0, 0, 0, 0 }; stringTable = list_new(); fontTable = list_new(); res = fopen(resfile, "wb"); if(!res) { open_error(resfile); return GRC_ERR_OPEN; } /* write the WIN32 resource file header */ fwrite(resfilePrefix, sizeof(DWORD), 8, res); return GRC_OK; } int FinishRes(int ok) { int retcode = GRC_OK; if (ok){ retcode = getString(stringTable); } fclose(res); return retcode; }