source: trunk/src/kernel32/old/winimgres.cpp@ 1036

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

Backup copy of old kernel32

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