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

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

PE loader resource lookup bug fixed

File size: 11.7 KB
Line 
1/* $Id: winres.cpp,v 1.12 1999-08-21 19:11:56 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, orgos2type, 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 = malloc(ressize+sizeof(WCHAR));
251 memcpy(winresdata, resdata, ressize);
252 *(USHORT *)(&((char *)winresdata)[ressize]) = 0;
253 DosFreeResource(resdata);
254 return((PVOID)((ULONG)winresdata+2)); //skip length word
255
256 //no conversion necessary
257 case NTRT_RCDATA:
258 case NTRT_VERSION:
259 default:
260 os2type = RT_RCDATA;
261 break;
262 }
263
264 if(winresdata == NULL) {
265 rc = DosGetResource((HMODULE)module->hinstance, os2type, id, (PPVOID)&resdata);
266 if(rc) {
267 dprintf(("Can't find original resource!!!\n"));
268 return(NULL);
269 }
270 winresdata = (char *)malloc(ressize);
271 memcpy(winresdata, resdata, ressize);
272 }
273 if(resdata)
274 DosFreeResource(resdata);
275
276 return winresdata;
277}
278//******************************************************************************
279//******************************************************************************
280PVOID Win32Resource::lockOS2Resource()
281{
282 APIRET rc;
283 PVOID resdata;
284
285 dprintf(("Win32Resource::lockOS2Resource %d\n", id));
286 if(os2resdata == NULL) {
287 if(resType == RSRC_PELOADER) {
288 os2resdata = convertResource(winresdata);
289 }
290 else {
291 rc = DosGetResource((HMODULE)module->hinstance, orgos2type, id, (PPVOID)&resdata);
292 if(rc) return(NULL);
293 os2resdata = resdata;
294 }
295 }
296 return os2resdata;
297}
298//******************************************************************************
299//******************************************************************************
300PVOID Win32Resource::convertResource(void *win32res)
301{
302 ULONG cvtressize;
303
304 switch(type) {
305 case NTRT_NEWBITMAP:
306 case NTRT_BITMAP:
307 return ConvertBitmap((WINBITMAPINFOHEADER *)win32res, ressize, &ressize);
308
309 case NTRT_CURSOR:
310 return ConvertCursor((CursorComponent *)win32res, ressize);
311
312 case NTRT_GROUP_CURSOR:
313 return ConvertCursorGroup((CursorHeader *)win32res, ressize, module);
314
315 case NTRT_GROUP_ICON:
316 return ConvertIconGroup((IconHeader *)win32res, ressize, module);
317
318 case NTRT_ICON:
319 return ConvertIcon((WINBITMAPINFOHEADER *)win32res, ressize);
320
321 case NTRT_ACCELERATORS:
322 return ConvertAccelerator((WINACCEL *)win32res, ressize);
323
324 case NTRT_NEWMENU:
325 case NTRT_MENU:
326 return ConvertMenu((MenuHeader *)win32res, ressize);
327
328 case NTRT_NEWDIALOG:
329 case NTRT_DIALOG:
330 break;
331 case NTRT_FONTDIR:
332 case NTRT_FONT:
333 case NTRT_MESSAGETABLE:
334 case NTRT_RCDATA:
335 case NTRT_VERSION:
336 case NTRT_STRING:
337 break;
338
339 default:
340 break;
341 }
342 dprintf(("Win32Resource::convertResource: Can't convert resource %d (type %d)", id, type));
343 return 0;
344}
345//******************************************************************************
346//NOTE: Will be removed once pe2lx rewrite has been completed
347//******************************************************************************
348PVOID Win32Resource::convertOS2Bitmap(void *bmpdata)
349{
350 BITMAPFILEHEADER2 *bmphdr = (BITMAPFILEHEADER2 *)bmpdata;
351 WINBITMAPINFOHEADER *winbmphdr;
352 RGBQUAD *rgb;
353 RGB2 *os2rgb;
354 int palsize = 0;
355 int imgsize;
356
357 if(bmphdr->cbSize != sizeof(BITMAPFILEHEADER2)) {
358 PVOID bmpdat = malloc(ressize);
359 memcpy(bmpdat, bmpdata, ressize);
360 return(bmpdat); //don't convert OS/2 1.x bitmap
361 }
362
363 if(bmphdr->bmp2.cBitCount < 16) {
364 palsize = (1 << bmphdr->bmp2.cBitCount) * sizeof(RGBQUAD);
365 }
366
367 //SvL: Always recalculate bitmap size (donut.exe has wrong size)
368 imgsize = CalcBitmapSize(bmphdr->bmp2.cBitCount,
369 bmphdr->bmp2.cx,
370 bmphdr->bmp2.cy);
371
372 winbmphdr = (WINBITMAPINFOHEADER *)malloc(sizeof(WINBITMAPINFOHEADER) +
373 imgsize + palsize);
374 memset((char *)winbmphdr, 0, sizeof(WINBITMAPINFOHEADER) + imgsize + palsize);
375
376 winbmphdr->biSize = sizeof(WINBITMAPINFOHEADER);
377 winbmphdr->biWidth = bmphdr->bmp2.cx;
378 winbmphdr->biHeight = bmphdr->bmp2.cy;
379 winbmphdr->biPlanes = bmphdr->bmp2.cPlanes;
380 winbmphdr->biBitCount = bmphdr->bmp2.cBitCount;
381 //TODO: Identical except for BI_BITFIELDS (3L) type!
382 winbmphdr->biCompression = bmphdr->bmp2.ulCompression;
383 winbmphdr->biSizeImage = imgsize;
384 //TODO: Doesn't seem to be completely identical..
385 winbmphdr->biClrUsed = bmphdr->bmp2.cclrUsed;
386 winbmphdr->biClrImportant = bmphdr->bmp2.cclrImportant;
387 winbmphdr->biXPelsPerMeter = bmphdr->bmp2.cxResolution;
388 winbmphdr->biYPelsPerMeter = bmphdr->bmp2.cyResolution;
389
390 os2rgb = (RGB2 *)(bmphdr+1);
391 rgb = (RGBQUAD *)(winbmphdr+1);
392
393 if(palsize) {
394 memcpy((char *)rgb, (char *)os2rgb, palsize);
395 os2rgb = (RGB2 *)((int)os2rgb + palsize);
396 rgb = (RGBQUAD *)((int)rgb + palsize);
397 }
398 memcpy((char *)rgb, (char *)os2rgb, imgsize);
399 return((PVOID)winbmphdr);
400}
401//******************************************************************************
402//******************************************************************************
403void Win32Resource::destroyAll(Win32Image *module)
404{
405 Win32Resource *res = module->winres, *next;
406
407 while(res) {
408 next = res->next;
409 delete(res);
410 res = next;
411 }
412}
413//******************************************************************************
414//******************************************************************************
Note: See TracBrowser for help on using the repository browser.