source: trunk/src/kernel32/winres.cpp@ 597

Last change on this file since 597 was 597, checked in by sandervl, 26 years ago

PE loader resource fixes

File size: 11.5 KB
Line 
1/* $Id: winres.cpp,v 1.10 1999-08-20 11:52:44 sandervl Exp $ */
2
3/*
4 * Win32 resource class
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 *
12 */
13#define INCL_BASE
14#define INCL_WIN
15#define INCL_GPIBITMAPS
16#define INCL_BITMAPFILEFORMAT
17#define INCL_DOSMODULEMGR
18#include <os2wrap.h> //Odin32 OS/2 api wrappers
19#include <stdarg.h>
20#ifdef __IBMCPP__
21#include <builtin.h>
22#endif
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#define INCL_WINRES
27#include <win32type.h>
28#include <winres.h>
29#include <misc.h>
30#include <nameid.h>
31#include <winexe.h>
32#include "cvtresource.h"
33
34//******************************************************************************
35//******************************************************************************
36static ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy)
37{
38 ULONG alignment;
39 ULONG factor;
40 BOOL flag = TRUE; //true: '*' false: '/'
41
42 cy = cy < 0 ? -cy : cy;
43
44 switch(cBits)
45 {
46 case 1:
47 factor = 8;
48 flag = FALSE;
49 break;
50
51 case 4:
52 factor = 2;
53 flag = FALSE;
54 break;
55
56 case 8:
57 factor = 1;
58 break;
59
60 case 16:
61 factor = 2;
62 break;
63
64 case 24:
65 factor = 3;
66 break;
67
68 case 32:
69 return cx*cy;
70
71 default:
72 return 0;
73 }
74
75 if (flag)
76 alignment = (cx = (cx*factor)) % 4;
77 else
78 alignment = (cx = ((cx+factor-1)/factor)) % 4;
79
80 if (alignment != 0)
81 cx += 4 - alignment;
82
83 return cx*cy;
84}
85
86//******************************************************************************
87//******************************************************************************
88Win32Resource::Win32Resource(Win32Image *module, HRSRC hRes, ULONG id, ULONG type) :
89 os2resdata(NULL), winresdata(NULL), resType(RSRC_PE2LX)
90{
91 APIRET rc;
92
93 next = module->winres;
94 module->winres = this;
95
96 this->module = module;
97 this->id = id;
98 this->type = type;
99 this->hres = hRes;
100
101 switch(type) {
102 case NTRT_NEWBITMAP:
103 case NTRT_BITMAP:
104 orgos2type = RT_BITMAP;
105 break;
106 case NTRT_CURSOR:
107 case NTRT_GROUP_CURSOR:
108 case NTRT_GROUP_ICON:
109 case NTRT_ICON:
110 orgos2type = RT_POINTER;
111 break;
112 case NTRT_ACCELERATORS:
113 orgos2type = RT_ACCELTABLE;
114 break;
115 case NTRT_NEWMENU:
116 case NTRT_MENU:
117 orgos2type = RT_MENU;
118 break;
119 case NTRT_NEWDIALOG:
120 case NTRT_DIALOG:
121 orgos2type = RT_DIALOG;
122 break;
123 case NTRT_FONTDIR:
124 case NTRT_FONT:
125 case NTRT_MESSAGETABLE:
126 case NTRT_STRING:
127 case NTRT_RCDATA:
128 case NTRT_VERSION:
129 default:
130 orgos2type = RT_RCDATA;
131 break;
132 }
133 OS2ResHandle = 0;
134
135 rc = DosQueryResourceSize(module->hinstance, type, id, &ressize);
136 if(rc) {
137 dprintf(("Win32Resource ctor: DosQueryResourceSize %x %d %d returned %X\n", module->hinstance, type, id, rc));
138 ressize = 0;
139 }
140}
141//******************************************************************************
142//******************************************************************************
143Win32Resource::Win32Resource(Win32Image *module, ULONG id, ULONG type,
144 ULONG size, char *resdata) : hres(NULL),
145 os2resdata(NULL), winresdata(NULL), resType(RSRC_PELOADER)
146{
147 next = module->winres;
148 module->winres = this;
149
150 this->module = module;
151 this->id = id;
152 this->type = type;
153 orgos2type = -1;
154 this->ressize = size;
155 winresdata = (char *)malloc(size);
156 if(winresdata == NULL) {
157 DebugInt3();
158 return;
159 }
160 OS2ResHandle = 0;
161
162 if(type == NTRT_STRING) {
163 memcpy(winresdata, resdata, size-sizeof(WCHAR));
164 ((USHORT *)winresdata)[size/sizeof(WCHAR)-1] = 0;
165 }
166 else memcpy(winresdata, resdata, size);
167}
168//******************************************************************************
169//******************************************************************************
170Win32Resource::~Win32Resource()
171{
172 Win32Resource *res = module->winres;
173
174 //returned by DosGetResource, so we don't (and mustn't) free it
175 if(os2resdata && resType == RSRC_PELOADER)
176 free(os2resdata);
177
178 if(winresdata) free(winresdata);
179
180 if(res == this) {
181 module->winres = res->next;
182 }
183 else {
184 while(res->next != this) {
185 res = res->next;
186 }
187 if(res)
188 res->next = next;
189 }
190}
191//******************************************************************************
192//******************************************************************************
193PVOID Win32Resource::lockResource()
194{
195 int restype = 0, newid;
196 void *resdata = NULL;
197 APIRET rc;
198 ULONG os2type = RT_RCDATA;
199
200 dprintf(("Win32Resource::lockResource %d\n", id));
201 if(winresdata)
202 return(winresdata);
203
204 switch(type) {
205 case NTRT_BITMAP:
206 rc = DosGetResource((HMODULE)module->hinstance, RT_BITMAP, id, (PPVOID)&resdata);
207 if(rc) return(NULL);
208 winresdata = convertOS2Bitmap((BITMAPFILEHEADER2 *)resdata);
209 break;
210
211 case NTRT_ACCELERATORS:
212 case NTRT_MENU:
213 case NTRT_DIALOG:
214 newid = module->getWin32ResourceId(id);
215
216 rc = DosGetResource((HMODULE)module->hinstance, RT_RCDATA, (int)newid, (PPVOID)&resdata);
217 if(rc) {
218 dprintf(("Can't find original resource!!!\n"));
219 return(NULL);
220 }
221 winresdata = (char *)malloc(ressize);
222 memcpy(winresdata, resdata, ressize);
223 break;
224
225 //TODO:not yet implemented
226 case NTRT_FONTDIR:
227 case NTRT_FONT:
228 case NTRT_MESSAGETABLE:
229 case NTRT_NEWBITMAP:
230 case NTRT_NEWMENU:
231 case NTRT_NEWDIALOG:
232 os2type = RT_RCDATA;
233 break;
234
235 //Can't do this right now (all group icons stored into a single one)
236 case NTRT_CURSOR:
237 case NTRT_GROUP_CURSOR:
238 case NTRT_GROUP_ICON:
239 case NTRT_ICON:
240 dprintf(("Can't convert this resource!!!!!\n"));
241 os2type = RT_POINTER;
242 break;
243
244 case NTRT_STRING:
245 rc = DosGetResource((HMODULE)module->hinstance, RT_RCDATA, id, (PPVOID)&resdata);
246 if(rc) {
247 dprintf(("Can't find original string!!!\n"));
248 return(NULL);
249 }
250 winresdata = (char *)malloc(ressize);
251 memcpy(winresdata, resdata, ressize);
252 DosFreeResource(resdata);
253 return((PVOID)((ULONG)winresdata+2)); //skip length word
254
255 //no conversion necessary
256 case NTRT_RCDATA:
257 case NTRT_VERSION:
258 default:
259 os2type = RT_RCDATA;
260 break;
261 }
262
263 if(winresdata == NULL) {
264 rc = DosGetResource((HMODULE)module->hinstance, os2type, id, (PPVOID)&resdata);
265 if(rc) {
266 dprintf(("Can't find original resource!!!\n"));
267 return(NULL);
268 }
269 winresdata = (char *)malloc(ressize);
270 memcpy(winresdata, resdata, ressize);
271 }
272 if(resdata)
273 DosFreeResource(resdata);
274
275 return winresdata;
276}
277//******************************************************************************
278//******************************************************************************
279PVOID Win32Resource::lockOS2Resource()
280{
281 APIRET rc;
282 PVOID resdata;
283
284 dprintf(("Win32Resource::lockOS2Resource %d\n", id));
285 if(os2resdata == NULL) {
286 if(resType == RSRC_PELOADER) {
287 os2resdata = convertResource(winresdata);
288 }
289 else {
290 rc = DosGetResource((HMODULE)module->hinstance, orgos2type, id, (PPVOID)&resdata);
291 if(rc) return(NULL);
292 os2resdata = resdata;
293 }
294 }
295 return os2resdata;
296}
297//******************************************************************************
298//******************************************************************************
299PVOID Win32Resource::convertResource(void *win32res)
300{
301 ULONG cvtressize;
302
303 switch(type) {
304 case NTRT_NEWBITMAP:
305 case NTRT_BITMAP:
306 return ConvertBitmap((WINBITMAPINFOHEADER *)win32res, ressize, &ressize);
307
308 case NTRT_CURSOR:
309 return ConvertCursor((CursorComponent *)win32res, ressize);
310
311 case NTRT_GROUP_CURSOR:
312 return ConvertCursorGroup((CursorHeader *)win32res, ressize, module);
313
314 case NTRT_GROUP_ICON:
315 return ConvertIconGroup((IconHeader *)win32res, ressize, module);
316
317 case NTRT_ICON:
318 return ConvertIcon((WINBITMAPINFOHEADER *)win32res, ressize);
319
320 case NTRT_ACCELERATORS:
321 return ConvertAccelerator((WINACCEL *)win32res, ressize);
322
323 case NTRT_NEWMENU:
324 case NTRT_MENU:
325 return ConvertMenu((MenuHeader *)win32res, ressize);
326
327 case NTRT_NEWDIALOG:
328 case NTRT_DIALOG:
329 break;
330 case NTRT_FONTDIR:
331 case NTRT_FONT:
332 case NTRT_MESSAGETABLE:
333 case NTRT_RCDATA:
334 case NTRT_VERSION:
335 case NTRT_STRING:
336 break;
337
338 default:
339 break;
340 }
341 dprintf(("Win32Resource::convertResource: Can't convert resource %d (type %d)", id, type));
342 return 0;
343}
344//******************************************************************************
345//NOTE: Will be removed once pe2lx rewrite has been completed
346//******************************************************************************
347PVOID Win32Resource::convertOS2Bitmap(void *bmpdata)
348{
349 BITMAPFILEHEADER2 *bmphdr = (BITMAPFILEHEADER2 *)bmpdata;
350 WINBITMAPINFOHEADER *winbmphdr;
351 RGBQUAD *rgb;
352 RGB2 *os2rgb;
353 int palsize = 0;
354 int imgsize;
355
356 if(bmphdr->cbSize != sizeof(BITMAPFILEHEADER2))
357 return(bmpdata); //don't convert OS/2 1.x bitmap
358
359 if(bmphdr->bmp2.cBitCount < 16) {
360 palsize = (1 << bmphdr->bmp2.cBitCount) * sizeof(RGBQUAD);
361 }
362
363 //SvL: Always recalculate bitmap size (donut.exe has wrong size)
364 imgsize = CalcBitmapSize(bmphdr->bmp2.cBitCount,
365 bmphdr->bmp2.cx,
366 bmphdr->bmp2.cy);
367
368 winbmphdr = (WINBITMAPINFOHEADER *)malloc(sizeof(WINBITMAPINFOHEADER) +
369 imgsize + palsize);
370 memset((char *)winbmphdr, 0, sizeof(WINBITMAPINFOHEADER) + imgsize + palsize);
371
372 winbmphdr->biSize = sizeof(WINBITMAPINFOHEADER);
373 winbmphdr->biWidth = bmphdr->bmp2.cx;
374 winbmphdr->biHeight = bmphdr->bmp2.cy;
375 winbmphdr->biPlanes = bmphdr->bmp2.cPlanes;
376 winbmphdr->biBitCount = bmphdr->bmp2.cBitCount;
377 //TODO: Identical except for BI_BITFIELDS (3L) type!
378 winbmphdr->biCompression = bmphdr->bmp2.ulCompression;
379 winbmphdr->biSizeImage = imgsize;
380 //TODO: Doesn't seem to be completely identical..
381 winbmphdr->biClrUsed = bmphdr->bmp2.cclrUsed;
382 winbmphdr->biClrImportant = bmphdr->bmp2.cclrImportant;
383 winbmphdr->biXPelsPerMeter = bmphdr->bmp2.cxResolution;
384 winbmphdr->biYPelsPerMeter = bmphdr->bmp2.cyResolution;
385
386 os2rgb = (RGB2 *)(bmphdr+1);
387 rgb = (RGBQUAD *)(winbmphdr+1);
388
389 if(palsize) {
390 memcpy((char *)rgb, (char *)os2rgb, palsize);
391 os2rgb = (RGB2 *)((int)os2rgb + palsize);
392 rgb = (RGBQUAD *)((int)rgb + palsize);
393 }
394 memcpy((char *)rgb, (char *)os2rgb, imgsize);
395 return((PVOID)winbmphdr);
396}
397//******************************************************************************
398//******************************************************************************
399void Win32Resource::destroyAll(Win32Image *module)
400{
401 Win32Resource *res = module->winres, *next;
402
403 while(res) {
404 next = res->next;
405 delete(res);
406 res = next;
407 }
408}
409//******************************************************************************
410//******************************************************************************
Note: See TracBrowser for help on using the repository browser.