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

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

More PE resource changes

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