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

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

PE loader resource fixes

File size: 15.5 KB
Line 
1/* $Id: winimgres.cpp,v 1.11 1999-08-20 11:52:44 sandervl Exp $ */
2
3/*
4 * Win32 PE Image class (resource methods)
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 * TODO: Check created resource objects before loading the resource!
12 *
13 */
14#include <os2win.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19#include <misc.h>
20#include <nameid.h>
21#include <winimage.h>
22#include <windll.h>
23#include <winexe.h>
24#include <winres.h>
25#include <unicode.h>
26#include <heapstring.h>
27#include "pefile.h"
28
29char *ResTypes[MAX_RES] =
30 {"niks", "CURSOR", "BITMAP", "ICON", "MENU", "DIALOG", "STRING",
31 "FONTDIR", "FONT", "ACCELERATOR", "RCDATA", "MESSAGETABLE",
32 "GROUP_CURSOR", "niks", "GROUP_ICON", "niks", "VERSION"};
33
34
35//******************************************************************************
36//Assuming names are case insensitive
37//PE spec says names & ids are sorted; keep on searching just to be sure
38//******************************************************************************
39PIMAGE_RESOURCE_DATA_ENTRY
40 Win32Image::getPEResourceEntry(ULONG id, ULONG type, ULONG lang)
41{
42 PIMAGE_RESOURCE_DIRECTORY prdType;
43 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
44 PIMAGE_RESOURCE_DIR_STRING_U pstring;
45 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
46 ULONG nodeData[3], i, j, nameOffset;
47 BOOL fFound = FALSE, fNumType;
48
49 /* set pointer to first resource type entry */
50 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
51
52 /* loop through all resource directory entry types */
53 //1st level -> types
54 //2nd level -> names
55 //3rd level -> language
56 nodeData[0] = id;
57 nodeData[1] = lang;
58 nodeData[2] = 0xFFFFFFFF;
59
60 fNumType = TRUE; //assume numeric
61 if(HIWORD(type) != 0) {//string id?
62 for(i=0;i<MAX_RES;i++) {
63 if(stricmp((char *)type, ResTypes[i]) == 0)
64 break;
65 }
66 if(i == MAX_RES) {//custom resource type
67 fNumType = FALSE;
68 }
69 else type = i;
70 }
71
72 for (i=0; i<pResDir->NumberOfNamedEntries+pResDir->NumberOfIdEntries; i++) {
73 /* locate directory or each resource type */
74 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResDir + (int)prde->u2.OffsetToData);
75
76 if(i < pResDir->NumberOfNamedEntries)
77 {//name or id entry?
78 //SvL: 30-10-'97, high bit is set, so clear to get real offset
79 nameOffset = prde->u1.Name & ~0x80000000;
80
81 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + nameOffset);
82 char *typename = (char *)malloc(pstring->Length+1);
83 lstrcpynWtoA(typename, pstring->NameString, pstring->Length);
84 typename[pstring->Length] = 0;
85
86 if(!fNumType) {
87 if(stricmp(typename, (char *)type) == 0) {
88 fFound = TRUE;
89 }
90 }
91 else {
92 for(j=0;j<MAX_RES;j++) {
93 if(stricmp(typename, ResTypes[j]) == 0)
94 break;
95 }
96 if(j == type) {
97 fFound = TRUE;
98 }
99 }
100 free(typename);
101 }
102 else {
103 if(prde->u1.Id == type) {
104 fFound = TRUE;
105 }
106 }
107 if(fFound) {
108 if((ULONG)prdType & 0x80000000) {//subdirectory?
109 pData = ProcessResSubDir(prdType, &nodeData[0], 2);
110 }
111 else {
112 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType;
113 dprintf(("getResource: not a subdir!!\n"));
114 }
115 break;
116 }
117 /* increment to next entry */
118 prde++;
119 }
120 return pData;
121}
122//******************************************************************************
123//level: 2 ids
124// 3 languages
125//******************************************************************************
126PIMAGE_RESOURCE_DATA_ENTRY
127 Win32Image::ProcessResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType,
128 ULONG *nodeData, int level)
129{
130 PIMAGE_RESOURCE_DIRECTORY prdType2;
131 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
132 PIMAGE_RESOURCE_DIR_STRING_U pstring;
133 PIMAGE_RESOURCE_DATA_ENTRY pData;
134 BOOL fFound = FALSE, fNumId;
135 ULONG nrres, nameOffset;
136 char *resname;
137 int i;
138
139 if(*nodeData == 0xFFFFFFFF) {//shouldn't happen!
140 dprintf(("ProcessResSubDir: *nodeData == 0xFFFFFFFF!\n"));
141 return(NULL);
142 }
143 prdType = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)prdType & ~0x80000000);
144 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdType + sizeof(IMAGE_RESOURCE_DIRECTORY));
145
146 if(level == 3 && *nodeData == LANG_GETFIRST) {
147 nrres = prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries;
148 fNumId = (prdType->NumberOfNamedEntries == 0);
149 }
150 else {
151 fNumId = HIWORD(*nodeData) == 0;
152
153 if(fNumId) {//numeric or string id?
154 nrres = prdType->NumberOfIdEntries;
155 prde += prdType->NumberOfNamedEntries; //skip name entries
156 }
157 else nrres = prdType->NumberOfNamedEntries;
158 }
159
160 for(i=0;i<nrres;i++) {
161 /* locate directory or each resource type */
162 prdType2 = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)pResDir + (ULONG)prde->u2.OffsetToData);
163
164 if(!fNumId) {//name or id entry?
165 nameOffset = prde->u1.Name;
166 if(prde->u1.s.NameIsString) //unicode directory string /*PLF Sat 97-06-21 22:30:35*/
167 nameOffset &= ~0x80000000;
168
169 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + nameOffset);
170
171 resname = (char *)malloc(pstring->Length+1);
172 lstrcpynWtoA(resname, pstring->NameString, pstring->Length);
173 resname[pstring->Length] = 0;
174 if(stricmp(resname, (char *)*nodeData) == 0) {
175 fFound = TRUE;
176 }
177 free(resname);
178 }
179 else {
180 if(*nodeData == prde->u1.Id)
181 fFound = TRUE;
182 }
183 if(*nodeData == LANG_GETFIRST)
184 fFound = TRUE;
185
186 if(fFound) {
187 if((ULONG)prdType2 & 0x80000000) {//subdirectory?
188 return ProcessResSubDir(prdType2, nodeData+1, 3);
189 }
190 else {
191 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType2;
192 if(pData->Size) {//winamp17 winzip archive has resource with size 0
193 return(pData);
194 }
195 else return(NULL);
196 }
197 }
198 prde++;
199 }
200 return(NULL);
201}
202//******************************************************************************
203//******************************************************************************
204ULONG Win32Image::getPEResourceSize(ULONG id, ULONG type, ULONG lang)
205{
206 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
207
208 pData = getPEResourceEntry(id, type, lang);
209 if(pData == NULL) {
210 dprintf(("Win32Image::getPEResourceSize: couldn't find resource %d (type %d, lang %d)", id, type, lang));
211 return 0;
212 }
213 return pData->Size;
214}
215//******************************************************************************
216//******************************************************************************
217Win32Resource *Win32Image::getPEResource(ULONG id, ULONG type, ULONG lang)
218{
219 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
220 Win32Resource *res;
221 BOOL fNumType;
222 char *winres = NULL;
223 int i, stringid = -1, j;
224
225 fNumType = TRUE; //assume numeric
226 if(HIWORD(type) != 0) {//string id?
227 for(i=0;i<MAX_RES;i++) {
228 if(stricmp((char *)type, ResTypes[i]) == 0)
229 break;
230 }
231 if(i == MAX_RES) {//custom resource type
232 fNumType = FALSE;
233 }
234 else type = i;
235 }
236
237 //String format: tables of 16 strings stored as one resource
238 //upper 12 bits of resource id passed by user determines block (res id)
239 //lower 4 bits are an index into the string table
240 if(fNumType) {
241 if(type == NTRT_STRING) {
242 stringid = id & 0xF;
243 id = (id >> 4)+1;
244 }
245 }
246 else {
247 if(stricmp((char *)type, ResTypes[NTRT_STRING]) == 0) {
248 stringid = id & 0xF;
249 id = (id >> 4)+1;
250 }
251 }
252
253 pData = getPEResourceEntry(id, type, lang);
254 if(pData == NULL) {
255 dprintf(("Win32Image::getPEResource: couldn't find resource %d (type %d, lang %d)", id, type, lang));
256 return 0;
257 }
258
259 char *resdata = (char *)((char *)pResDir + pData->OffsetToData - (pResSection->virtaddr - oh.ImageBase));
260 if(stringid != -1) {//search for string in table
261 USHORT *unicodestr = (USHORT *)resdata;
262
263 for(i=0;i<stringid;i++) {
264 unicodestr += *unicodestr+1;
265 }
266 res = new Win32Resource(this, id, NTRT_STRING, (*unicodestr+1)*sizeof(WCHAR),
267 (char *)(unicodestr+1));
268 if(res == NULL) {
269 dprintf(("new Win32Resource failed!\n"));
270 return(NULL);
271 }
272 }
273 else res = new Win32Resource(this, id, type, pData->Size, resdata);
274
275 return res;
276}
277//******************************************************************************
278//******************************************************************************
279HRSRC Win32Image::findResourceA(LPCSTR lpszName, LPSTR lpszType)
280{
281 Win32Resource *res = NULL;
282 HRSRC hres;
283 int i;
284 LPSTR szType = (LPSTR)lpszType;
285
286 if(fNativePEImage == TRUE) {
287 return (HRSRC) getPEResource((ULONG)lpszName, (ULONG)lpszType);
288 }
289 //else converted win32 exe/dll
290
291 if(HIWORD(lpszType) != 0) {//type name, translate to id
292 for(i=0;i<MAX_RES;i++) {
293 if(strcmp(lpszType, ResTypes[i]) == 0)
294 break;
295 }
296 if(i == MAX_RES) {//custom resource type, stored as rcdata
297 dprintf(("FindResourceA custom type %s\n", lpszType));
298 lpszType = (LPSTR)NTRT_RCDATA;
299 }
300 else lpszType = (LPSTR)i;
301
302 szType = (LPSTR)lpszType;
303 }
304 switch((int)szType) {
305 case NTRT_GROUP_ICON:
306 szType = (LPSTR)NTRT_ICON;
307 break;
308 case NTRT_GROUP_CURSOR:
309 szType = (LPSTR)NTRT_CURSOR;
310 break;
311 case NTRT_VERSION:
312 szType = (LPSTR)NTRT_RCDATA;
313 break;
314 case NTRT_STRING:
315 case NTRT_MENU:
316 case NTRT_ICON:
317 case NTRT_BITMAP:
318 case NTRT_CURSOR:
319 case NTRT_DIALOG:
320 case NTRT_RCDATA:
321 case NTRT_ACCELERATORS:
322 szType = lpszType;
323 break;
324 default: //unknown are stored as rcdata
325 szType = (LPSTR)NTRT_RCDATA;
326 break;
327 }
328 dprintf(("FindResourceA from %X type %d (%X)\n", hinstance, szType, lpszType));
329
330 if(HIWORD(lpszName) != 0) {//convert string name identifier to numeric id
331 dprintf(("FindResource %s\n", lpszName));
332 if(lpszName[0] == '#') {// #344
333 lpszName = (LPCSTR)atoi(&lpszName[1]);
334 }
335 else lpszName = (LPCSTR)ConvertNameId(hinstance, (char *)lpszName);
336 }
337 else dprintf(("FindResource %d\n", (int)lpszName));
338
339 hres = O32_FindResource(hinstance, lpszName, szType);
340 if(hres)
341 {
342 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
343 }
344
345 if(hres == NULL && HIWORD(lpszName) == 0 && (int)szType == NTRT_STRING) {
346 hres = O32_FindResource(hinstance, (LPCSTR)(((int)lpszName - 1)*16), (LPCSTR)NTRT_RCDATA);
347 if(hres)
348 {
349 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
350 }
351 else dprintf(("FindResourceA can't find string %d\n", (int)lpszName));
352 }
353 dprintf(("FindResourceA returned %X (%X)\n", hres, GetLastError()));
354
355 return (HRSRC)res;
356}
357//******************************************************************************
358//******************************************************************************
359HRSRC Win32Image::findResourceW(LPWSTR lpszName, LPWSTR lpszType)
360{
361 Win32Resource *res = NULL;
362 HRSRC hres;
363 LPSTR szType = (LPSTR)lpszType;
364 int i;
365 char *astring1 = NULL, *astring2 = NULL;
366
367 if(fNativePEImage == TRUE) {//load resources directly from res section
368 if(HIWORD(lpszType) != 0) {
369 char *resname = UnicodeToAsciiString(lpszType);
370 }
371 else astring1 = (char *)lpszType;
372
373 if(HIWORD(lpszName) != 0) {
374 astring2 = UnicodeToAsciiString(lpszName);
375 }
376 else astring2 = (char *)lpszName;
377
378 hres = (HRSRC) getPEResource((ULONG)astring1, (ULONG)astring1);
379 if(astring1) FreeAsciiString(astring1);
380 if(astring2) FreeAsciiString(astring2);
381
382 return(hres);
383 }
384 //else converted win32 exe/dll
385 if(HIWORD(lpszType) != 0) {//type name, translate to id
386 char *resname = UnicodeToAsciiString(lpszType);
387 for(i=0;i<MAX_RES;i++) {
388 if(strcmp(resname, ResTypes[i]) == 0)
389 break;
390 }
391 if(i == MAX_RES) {//custom resource type, stored as rcdata
392 dprintf(("FindResourceW custom type %s\n", resname));
393 i = NTRT_RCDATA;
394 }
395 FreeAsciiString(resname);
396 lpszType = (LPWSTR)i;
397
398 szType = (LPSTR)lpszType;
399 }
400 switch((int)szType) {
401 case NTRT_GROUP_ICON:
402 szType = (LPSTR)NTRT_ICON;
403 break;
404 case NTRT_GROUP_CURSOR:
405 szType = (LPSTR)NTRT_CURSOR;
406 break;
407 case NTRT_VERSION:
408 szType = (LPSTR)NTRT_RCDATA;
409 break;
410 case NTRT_STRING:
411 case NTRT_MENU:
412 case NTRT_ICON:
413 case NTRT_BITMAP:
414 case NTRT_CURSOR:
415 case NTRT_DIALOG:
416 case NTRT_RCDATA:
417 case NTRT_ACCELERATORS:
418 szType = (LPSTR)lpszType;
419 break;
420 default: //unknown are stored as rcdata
421 szType = (LPSTR)NTRT_RCDATA;
422 break;
423 }
424 dprintf(("FindResourceW type %d\n", szType));
425
426 if(HIWORD(lpszName) != 0) {//convert string name identifier to numeric id
427 astring1 = UnicodeToAsciiString(lpszName);
428 dprintf(("FindResourceW %X %s\n", hinstance, astring1));
429 if(astring1[0] == '#') {// #344
430 lpszName = (LPWSTR)atoi(&astring1[1]);
431 }
432 else lpszName = (LPWSTR)ConvertNameId(hinstance, (char *)astring1);
433 }
434 else dprintf(("FindResourceW %X %d\n", hinstance, (int)lpszName));
435
436 hres = O32_FindResource(hinstance, (LPCSTR)lpszName, (LPCSTR)szType);
437 if(hres)
438 {
439 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
440 }
441
442 if(hres == NULL && HIWORD(lpszName) == 0 && (int)szType == NTRT_STRING) {
443 hres = O32_FindResource(hinstance, (LPCSTR)(((ULONG)lpszName - 1)*16), (LPCSTR)NTRT_RCDATA);
444 if(hres)
445 {
446 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
447 }
448 else dprintf(("FindResourceW can't find string %d\n", (int)lpszName));
449 }
450 if(astring1) FreeAsciiString(astring1);
451
452 dprintf(("FindResourceW returned %X (%X)\n", hres, GetLastError()));
453
454 return (HRSRC)res;
455}
456//******************************************************************************
457//******************************************************************************
458ULONG Win32Image::getResourceSizeA(LPCSTR lpszName, LPSTR lpszType)
459{
460 if(fNativePEImage == TRUE) {
461 return getPEResourceSize((ULONG)lpszName, (ULONG)lpszType);
462 }
463 DebugInt3();
464 return 0;
465}
466//******************************************************************************
467//******************************************************************************
468ULONG Win32Image::getResourceSizeW(LPCWSTR lpszName, LPWSTR lpszType)
469{
470 char *astring1 = NULL, *astring2 = NULL;
471 ULONG ressize;
472
473 if(fNativePEImage == TRUE) {//load resources directly from res section
474 if(HIWORD(lpszType) != 0) {
475 char *resname = UnicodeToAsciiString(lpszType);
476 }
477 else astring1 = (char *)lpszType;
478
479 if(HIWORD(lpszName) != 0) {
480 astring2 = UnicodeToAsciiString((LPWSTR)lpszName);
481 }
482 else astring2 = (char *)lpszName;
483
484 ressize = getPEResourceSize((ULONG)astring1, (ULONG)astring1);
485 if(astring1) FreeAsciiString(astring1);
486 if(astring2) FreeAsciiString(astring2);
487
488 return(ressize);
489 }
490 DebugInt3();
491 return 0;
492}
493//******************************************************************************
494//******************************************************************************
Note: See TracBrowser for help on using the repository browser.