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

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

Bugfixes + def files changes

File size: 15.7 KB
Line 
1/* $Id: winimgres.cpp,v 1.12 1999-08-22 22:11:22 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+1);
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+1);
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 if(HIWORD(id)) {
256 dprintf(("Win32Image::getPEResource: couldn't find resource %s (type %d, lang %d)", id, type, lang));
257 }
258 else dprintf(("Win32Image::getPEResource: couldn't find resource %d (type %d, lang %d)", id, type, lang));
259 return 0;
260 }
261
262 char *resdata = (char *)((char *)pResDir + pData->OffsetToData - (pResSection->virtaddr - oh.ImageBase));
263 if(stringid != -1) {//search for string in table
264 USHORT *unicodestr = (USHORT *)resdata;
265
266 for(i=0;i<stringid;i++) {
267 unicodestr += *unicodestr+1;
268 }
269 res = new Win32Resource(this, id, NTRT_STRING, (*unicodestr+1)*sizeof(WCHAR),
270 (char *)(unicodestr+1));
271 if(res == NULL) {
272 dprintf(("new Win32Resource failed!\n"));
273 return(NULL);
274 }
275 }
276 else res = new Win32Resource(this, id, type, pData->Size, resdata);
277
278 return res;
279}
280//******************************************************************************
281//******************************************************************************
282HRSRC Win32Image::findResourceA(LPCSTR lpszName, LPSTR lpszType)
283{
284 Win32Resource *res = NULL;
285 HRSRC hres;
286 int i;
287 LPSTR szType = (LPSTR)lpszType;
288
289 if(fNativePEImage == TRUE) {
290 return (HRSRC) getPEResource((ULONG)lpszName, (ULONG)lpszType);
291 }
292 //else converted win32 exe/dll
293
294 if(HIWORD(lpszType) != 0) {//type name, translate to id
295 for(i=0;i<MAX_RES;i++) {
296 if(strcmp(lpszType, ResTypes[i]) == 0)
297 break;
298 }
299 if(i == MAX_RES) {//custom resource type, stored as rcdata
300 dprintf(("FindResourceA custom type %s\n", lpszType));
301 lpszType = (LPSTR)NTRT_RCDATA;
302 }
303 else lpszType = (LPSTR)i;
304
305 szType = (LPSTR)lpszType;
306 }
307 switch((int)szType) {
308 case NTRT_GROUP_ICON:
309 szType = (LPSTR)NTRT_ICON;
310 break;
311 case NTRT_GROUP_CURSOR:
312 szType = (LPSTR)NTRT_CURSOR;
313 break;
314 case NTRT_VERSION:
315 szType = (LPSTR)NTRT_RCDATA;
316 break;
317 case NTRT_STRING:
318 case NTRT_MENU:
319 case NTRT_ICON:
320 case NTRT_BITMAP:
321 case NTRT_CURSOR:
322 case NTRT_DIALOG:
323 case NTRT_RCDATA:
324 case NTRT_ACCELERATORS:
325 szType = lpszType;
326 break;
327 default: //unknown are stored as rcdata
328 szType = (LPSTR)NTRT_RCDATA;
329 break;
330 }
331 dprintf(("FindResourceA from %X type %d (%X)\n", hinstance, szType, lpszType));
332
333 if(HIWORD(lpszName) != 0) {//convert string name identifier to numeric id
334 dprintf(("FindResource %s\n", lpszName));
335 if(lpszName[0] == '#') {// #344
336 lpszName = (LPCSTR)atoi(&lpszName[1]);
337 }
338 else lpszName = (LPCSTR)ConvertNameId(hinstance, (char *)lpszName);
339 }
340 else dprintf(("FindResource %d\n", (int)lpszName));
341
342 hres = O32_FindResource(hinstance, lpszName, szType);
343 if(hres)
344 {
345 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
346 }
347
348 if(hres == NULL && HIWORD(lpszName) == 0 && (int)szType == NTRT_STRING) {
349 hres = O32_FindResource(hinstance, (LPCSTR)(((int)lpszName - 1)*16), (LPCSTR)NTRT_RCDATA);
350 if(hres)
351 {
352 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
353 }
354 else dprintf(("FindResourceA can't find string %d\n", (int)lpszName));
355 }
356 dprintf(("FindResourceA returned %X (%X)\n", hres, GetLastError()));
357
358 return (HRSRC)res;
359}
360//******************************************************************************
361//******************************************************************************
362HRSRC Win32Image::findResourceW(LPWSTR lpszName, LPWSTR lpszType)
363{
364 Win32Resource *res = NULL;
365 HRSRC hres;
366 LPSTR szType = (LPSTR)lpszType;
367 int i;
368 char *astring1 = NULL, *astring2 = NULL;
369
370 if(fNativePEImage == TRUE) {//load resources directly from res section
371 if(HIWORD(lpszType) != 0) {
372 char *resname = UnicodeToAsciiString(lpszType);
373 }
374 else astring1 = (char *)lpszType;
375
376 if(HIWORD(lpszName) != 0) {
377 astring2 = UnicodeToAsciiString(lpszName);
378 }
379 else astring2 = (char *)lpszName;
380
381 hres = (HRSRC) getPEResource((ULONG)astring1, (ULONG)astring1);
382 if(astring1) FreeAsciiString(astring1);
383 if(astring2) FreeAsciiString(astring2);
384
385 return(hres);
386 }
387 //else converted win32 exe/dll
388 if(HIWORD(lpszType) != 0) {//type name, translate to id
389 char *resname = UnicodeToAsciiString(lpszType);
390 for(i=0;i<MAX_RES;i++) {
391 if(strcmp(resname, ResTypes[i]) == 0)
392 break;
393 }
394 if(i == MAX_RES) {//custom resource type, stored as rcdata
395 dprintf(("FindResourceW custom type %s\n", resname));
396 i = NTRT_RCDATA;
397 }
398 FreeAsciiString(resname);
399 lpszType = (LPWSTR)i;
400
401 szType = (LPSTR)lpszType;
402 }
403 switch((int)szType) {
404 case NTRT_GROUP_ICON:
405 szType = (LPSTR)NTRT_ICON;
406 break;
407 case NTRT_GROUP_CURSOR:
408 szType = (LPSTR)NTRT_CURSOR;
409 break;
410 case NTRT_VERSION:
411 szType = (LPSTR)NTRT_RCDATA;
412 break;
413 case NTRT_STRING:
414 case NTRT_MENU:
415 case NTRT_ICON:
416 case NTRT_BITMAP:
417 case NTRT_CURSOR:
418 case NTRT_DIALOG:
419 case NTRT_RCDATA:
420 case NTRT_ACCELERATORS:
421 szType = (LPSTR)lpszType;
422 break;
423 default: //unknown are stored as rcdata
424 szType = (LPSTR)NTRT_RCDATA;
425 break;
426 }
427 dprintf(("FindResourceW type %d\n", szType));
428
429 if(HIWORD(lpszName) != 0) {//convert string name identifier to numeric id
430 astring1 = UnicodeToAsciiString(lpszName);
431 dprintf(("FindResourceW %X %s\n", hinstance, astring1));
432 if(astring1[0] == '#') {// #344
433 lpszName = (LPWSTR)atoi(&astring1[1]);
434 }
435 else lpszName = (LPWSTR)ConvertNameId(hinstance, (char *)astring1);
436 }
437 else dprintf(("FindResourceW %X %d\n", hinstance, (int)lpszName));
438
439 hres = O32_FindResource(hinstance, (LPCSTR)lpszName, (LPCSTR)szType);
440 if(hres)
441 {
442 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
443 }
444
445 if(hres == NULL && HIWORD(lpszName) == 0 && (int)szType == NTRT_STRING) {
446 hres = O32_FindResource(hinstance, (LPCSTR)(((ULONG)lpszName - 1)*16), (LPCSTR)NTRT_RCDATA);
447 if(hres)
448 {
449 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
450 }
451 else dprintf(("FindResourceW can't find string %d\n", (int)lpszName));
452 }
453 if(astring1) FreeAsciiString(astring1);
454
455 dprintf(("FindResourceW returned %X (%X)\n", hres, GetLastError()));
456
457 return (HRSRC)res;
458}
459//******************************************************************************
460//******************************************************************************
461ULONG Win32Image::getResourceSizeA(LPCSTR lpszName, LPSTR lpszType)
462{
463 if(fNativePEImage == TRUE) {
464 return getPEResourceSize((ULONG)lpszName, (ULONG)lpszType);
465 }
466 DebugInt3();
467 return 0;
468}
469//******************************************************************************
470//******************************************************************************
471ULONG Win32Image::getResourceSizeW(LPCWSTR lpszName, LPWSTR lpszType)
472{
473 char *astring1 = NULL, *astring2 = NULL;
474 ULONG ressize;
475
476 if(fNativePEImage == TRUE) {//load resources directly from res section
477 if(HIWORD(lpszType) != 0) {
478 char *resname = UnicodeToAsciiString(lpszType);
479 }
480 else astring1 = (char *)lpszType;
481
482 if(HIWORD(lpszName) != 0) {
483 astring2 = UnicodeToAsciiString((LPWSTR)lpszName);
484 }
485 else astring2 = (char *)lpszName;
486
487 ressize = getPEResourceSize((ULONG)astring1, (ULONG)astring1);
488 if(astring1) FreeAsciiString(astring1);
489 if(astring2) FreeAsciiString(astring2);
490
491 return(ressize);
492 }
493 DebugInt3();
494 return 0;
495}
496//******************************************************************************
497//******************************************************************************
Note: See TracBrowser for help on using the repository browser.