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

Last change on this file since 3753 was 3753, checked in by sandervl, 25 years ago

resource type numeric string fix

File size: 28.9 KB
Line 
1/* $Id: winimgres.cpp,v 1.41 2000-06-26 07:35:56 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 * TODO: Once the resource handling in PE2LX/win32k is changed,
13 * getVersionStruct/Size can be moved into the Win32ImageBase class
14 * TODO: Support for 'DIB' resource type (VPBuddy)
15 *
16 */
17#include <os2win.h>
18#include <winnls.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include <misc.h>
24#include <winimagebase.h>
25#include <unicode.h>
26#include <heapstring.h>
27#include "pefile.h"
28#include "oslibmisc.h"
29
30#define DBG_LOCALLOG DBG_winimgres
31#include "dbglocal.h"
32
33#define MAX_RES 17
34char *ResTypes[MAX_RES] =
35 {"niks", "CURSOR", "BITMAP", "ICON", "MENU", "DIALOG", "STRING",
36 "FONTDIR", "FONT", "ACCELERATOR", "RCDATA", "MESSAGETABLE",
37 "GROUP_CURSOR", "niks", "GROUP_ICON", "niks", "VERSION"};
38
39//SvL: VPBuddy bugfix, seems to load bitmaps with type name 'DIB'
40#define BITMAP_TYPENAME2 "DIB"
41
42#define RESERR_SUCCESS 0
43#define RESERR_IDNOTFOUND 1
44#define RESERR_TYPENOTFOUND 2
45#define RESERR_LANGNOTFOUND 3
46
47//******************************************************************************
48//Assuming names are case insensitive
49//PE spec says names & ids are sorted; keep on searching just to be sure
50//******************************************************************************
51PIMAGE_RESOURCE_DATA_ENTRY
52 Win32ImageBase::getPEResourceEntry(ULONG id, ULONG type, ULONG lang, int *error)
53{
54 PIMAGE_RESOURCE_DIRECTORY prdType;
55 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
56 PIMAGE_RESOURCE_DIR_STRING_U pstring;
57 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
58 ULONG nodeData[3], i, j, nameOffset;
59 BOOL fFound = FALSE, fNumType;
60
61 *error = RESERR_TYPENOTFOUND;
62
63 //PH: our system LX DLLs might not have a resource segment
64 if (pResDir == NULL)
65 return NULL;
66
67 if(HIWORD(type)) {
68 char *lpszName = (char *)type;
69 //"#102" really means numeric id 102
70 if(lpszName[0] == '#') {
71 type = atoi(&lpszName[1]);
72 }
73 }
74
75 if(HIWORD(id) && id != IDLANG_GETFIRST) {
76 char *lpszName = (char *)id;
77 //"#102" really means numeric id 102
78 if(lpszName[0] == '#') {
79 id = atoi(&lpszName[1]);
80 }
81 }
82
83 /* set pointer to first resource type entry */
84 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
85
86 /* loop through all resource directory entry types */
87 //1st level -> types
88 //2nd level -> names
89 //3rd level -> language
90 nodeData[0] = id;
91 nodeData[1] = lang;
92 nodeData[2] = 0xFFFFFFFF;
93
94 fNumType = TRUE; //assume numeric
95 if(HIWORD(type) != 0) {//string id?
96 for(i=0;i<MAX_RES;i++) {
97 if(stricmp((char *)type, ResTypes[i]) == 0)
98 break;
99 }
100//TODO:
101#if 0
102 if(stricmp((char *)type, BITMAP_TYPENAME2) == 0) {
103 i = (int)RT_BITMAPA;
104 }
105#endif
106
107 if(i == MAX_RES) {//custom resource type
108 fNumType = FALSE;
109 }
110 else type = i;
111 }
112
113 for (i=0; i<pResDir->NumberOfNamedEntries+pResDir->NumberOfIdEntries; i++) {
114 /* locate directory or each resource type */
115 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResDir + (int)prde->u2.OffsetToData);
116
117 if(i < pResDir->NumberOfNamedEntries)
118 {//name or id entry?
119 //SvL: 30-10-'97, high bit is set, so clear to get real offset
120 nameOffset = prde->u1.Name & ~0x80000000;
121
122 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + nameOffset);
123 char *typename = (char *)malloc(pstring->Length+1);
124 lstrcpynWtoA(typename, pstring->NameString, pstring->Length+1);
125 typename[pstring->Length] = 0;
126
127 if(!fNumType) {
128 if(stricmp(typename, (char *)type) == 0) {
129 fFound = TRUE;
130 }
131 }
132 else {
133 for(j=0;j<MAX_RES;j++) {
134 if(stricmp(typename, ResTypes[j]) == 0)
135 break;
136 }
137 if(j == type) {
138 fFound = TRUE;
139 }
140 }
141 free(typename);
142 }
143 else {
144 if(prde->u1.Id == type) {
145 fFound = TRUE;
146 }
147 }
148 if(fFound) {
149 if((ULONG)prdType & 0x80000000) {//subdirectory?
150 pData = ProcessResSubDir(prdType, &nodeData[0], 2, error);
151 }
152 else {
153 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType;
154 dprintf(("getResource: not a subdir!!\n"));
155 }
156 break;
157 }
158 /* increment to next entry */
159 prde++;
160 }
161 if(pData) {
162 *error = RESERR_SUCCESS; //found it
163 }
164 return pData;
165}
166//******************************************************************************
167//level: 2 ids
168// 3 languages
169//******************************************************************************
170PIMAGE_RESOURCE_DATA_ENTRY
171 Win32ImageBase::ProcessResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType,
172 ULONG *nodeData, int level, int *error)
173{
174 PIMAGE_RESOURCE_DIRECTORY prdType2;
175 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
176 PIMAGE_RESOURCE_DIR_STRING_U pstring;
177 PIMAGE_RESOURCE_DATA_ENTRY pData;
178 BOOL fFound = FALSE, fNumId;
179 ULONG nrres, nameOffset;
180 char *resname;
181 int i;
182
183 if(*nodeData == 0xFFFFFFFF) {//shouldn't happen!
184 dprintf(("ProcessResSubDir: *nodeData == 0xFFFFFFFF!\n"));
185 DebugInt3();
186 return(NULL);
187 }
188 prdType = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)prdType & ~0x80000000);
189 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdType + sizeof(IMAGE_RESOURCE_DIRECTORY));
190
191 if(level == 2) {
192 *error = RESERR_IDNOTFOUND;
193 }
194 else {
195 *error = RESERR_LANGNOTFOUND;
196 }
197 //level 2 (id) -> get first id?
198 //level 3 (lang) -> get first language?
199 if(*nodeData == IDLANG_GETFIRST) {
200 nrres = prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries;
201 fNumId = (prdType->NumberOfNamedEntries == 0);
202 }
203 else {
204 fNumId = HIWORD(*nodeData) == 0;
205
206 if(fNumId) {//numeric or string id?
207 nrres = prdType->NumberOfIdEntries;
208 prde += prdType->NumberOfNamedEntries; //skip name entries
209 }
210 else nrres = prdType->NumberOfNamedEntries;
211 }
212
213 for(i=0;i<nrres;i++) {
214 /* locate directory or each resource type */
215 prdType2 = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)pResDir + (ULONG)prde->u2.OffsetToData);
216
217 if(*nodeData == IDLANG_GETFIRST) {
218 fFound = TRUE; //always take the first one
219 }
220 else
221 if(!fNumId) {//name or id entry?
222 nameOffset = prde->u1.Name;
223 if(prde->u1.s.NameIsString) //unicode directory string /*PLF Sat 97-06-21 22:30:35*/
224 nameOffset &= ~0x80000000;
225
226 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + nameOffset);
227
228 resname = (char *)malloc(pstring->Length+1);
229 lstrcpynWtoA(resname, pstring->NameString, pstring->Length+1);
230 resname[pstring->Length] = 0;
231 if(stricmp(resname, (char *)*nodeData) == 0) {
232 fFound = TRUE;
233 }
234 free(resname);
235 }
236 else {
237 if(*nodeData == prde->u1.Id)
238 fFound = TRUE;
239 }
240
241 if(fFound) {
242 if((ULONG)prdType2 & 0x80000000) {//subdirectory?
243 return ProcessResSubDir(prdType2, nodeData+1, 3, error);
244 }
245 else {
246 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType2;
247 if(pData->Size) {//winamp17 winzip archive has resource with size 0
248 return(pData);
249 }
250 else return(NULL);
251 }
252 }
253 prde++;
254 }
255 return(NULL);
256}
257//******************************************************************************
258//******************************************************************************
259ULONG Win32ImageBase::getPEResourceSize(ULONG id, ULONG type, ULONG lang)
260{
261 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
262 int error;
263
264 switch(lang) {
265 case LOCALE_SYSTEM_DEFAULT:
266 lang = GetSystemDefaultLangID();
267 break;
268 case LOCALE_USER_DEFAULT:
269 lang = GetUserDefaultLangID();
270 break;
271 case LOCALE_NEUTRAL:
272 //TODO: Not correct; should take language associated with current thread
273 lang = IDLANG_GETFIRST;
274 break;
275 }
276
277 pData = getPEResourceEntry(id, type, lang, &error);
278 if(pData == NULL) {
279 dprintf(("Win32ImageBase::getPEResourceSize: couldn't find resource %d (type %d, lang %x)", id, type, lang));
280 return 0;
281 }
282 return pData->Size;
283}
284//******************************************************************************
285//Returns pointer to data of resource handle
286//******************************************************************************
287char *Win32ImageBase::getResourceAddr(HRSRC hResource)
288{
289 PIMAGE_RESOURCE_DATA_ENTRY pData = (PIMAGE_RESOURCE_DATA_ENTRY)hResource;
290
291 if(pData == NULL) {
292 DebugInt3();
293 return NULL;
294 }
295 //ulRVAResourceSection contains the relative virtual address (relative to the start of the image)
296 //for the resource section (images loaded by the pe.exe and pe2lx/win32k)
297 //For LX images, this is 0 as OffsetToData contains a relative offset
298 return (char *)((char *)pResDir + (pData->OffsetToData - ulRVAResourceSection));
299}
300//******************************************************************************
301//******************************************************************************
302ULONG Win32ImageBase::getResourceSize(HRSRC hResource)
303{
304 PIMAGE_RESOURCE_DATA_ENTRY pData = (PIMAGE_RESOURCE_DATA_ENTRY)hResource;
305
306 if(pData == NULL) {
307 DebugInt3();
308 return NULL;
309 }
310 return pData->Size;
311}
312//******************************************************************************
313//findResource returns the pointer of the resource's IMAGE_RESOURCE_DATA_ENTRY structure
314//******************************************************************************
315HRSRC Win32ImageBase::findResourceA(LPCSTR lpszName, LPSTR lpszType, ULONG langid)
316{
317 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
318 char *winres = NULL;
319 ULONG id, type, lang;
320 int i, j, error;
321
322#ifdef DEBUG
323 if(HIWORD(lpszType) != 0) {//string id?
324 for(i=0;i<MAX_RES;i++) {
325 if(stricmp(lpszType, ResTypes[i]) == 0)
326 break;
327 }
328 if(i == MAX_RES) {//custom resource type
329 type = (ULONG)lpszType;
330 }
331 else type = i;
332 }
333 else type = (ULONG)lpszType;
334#else
335 type = (ULONG)lpszType;
336#endif
337
338 switch(langid) {
339 case LOCALE_SYSTEM_DEFAULT:
340 lang = GetSystemDefaultLangID();
341 break;
342 case LOCALE_USER_DEFAULT:
343 lang = GetUserDefaultLangID();
344 break;
345 case LOCALE_NEUTRAL:
346 //TODO: Not correct; should take language associated with current thread
347 lang = IDLANG_GETFIRST;
348 break;
349 case IDLANG_GETFIRST:
350 lang = GetUserDefaultLangID();
351 break;
352 }
353 id = (ULONG)lpszName;
354 pData = getPEResourceEntry(id, type, lang, &error);
355 if(pData == NULL) {
356 //TODO: Optimize this; check if language wasn't found
357 //try system default language
358 if(error == RESERR_LANGNOTFOUND) {
359 pData = getPEResourceEntry(id, type, GetSystemDefaultLangID(), &error);
360 }
361 if(pData == NULL) {
362 //finally try first available language
363 if(error == RESERR_LANGNOTFOUND) {
364 pData = getPEResourceEntry(id, type, IDLANG_GETFIRST, &error);
365 }
366 if(pData == NULL) {
367 if(HIWORD(id)) {
368 dprintf(("Win32ImageBase::getPEResource %s: couldn't find resource %s (type %d, lang %x)", szModule, id, type, lang));
369 }
370 else dprintf(("Win32ImageBase::getPEResource %s: couldn't find resource %d (type %d, lang %x)", szModule, id, type, lang));
371 return 0;
372 }
373 }
374 }
375 if(HIWORD(id)) {
376 dprintf(("FindResource %s: resource %s (type %d, lang %x)", szModule, id, type, lang));
377 }
378 else dprintf(("FindResource %s: resource %d (type %d, lang %x)", szModule, id, type, lang));
379
380 return (HRSRC) pData;
381}
382//******************************************************************************
383//******************************************************************************
384HRSRC Win32ImageBase::findResourceW(LPWSTR lpszName, LPWSTR lpszType, ULONG lang)
385{
386 HRSRC hres;
387 char *astring1 = NULL, *astring2 = NULL;
388
389 if(HIWORD(lpszName) != 0) {
390 astring1 = UnicodeToAsciiString(lpszName);
391 }
392 else astring1 = (char *)lpszName;
393
394 if(HIWORD(lpszType) != 0) {
395 astring2 = UnicodeToAsciiString(lpszType);
396 }
397 else astring2 = (char *)lpszType;
398
399 hres = findResourceA(astring1, astring2, lang);
400
401 if(HIWORD(astring1)) FreeAsciiString(astring1);
402 if(HIWORD(astring2)) FreeAsciiString(astring2);
403
404 return(hres);
405}
406//******************************************************************************
407//******************************************************************************
408ULONG Win32ImageBase::getResourceSizeA(LPCSTR lpszName, LPSTR lpszType, ULONG lang)
409{
410 return getPEResourceSize((ULONG)lpszName, (ULONG)lpszType, lang);
411}
412//******************************************************************************
413//******************************************************************************
414ULONG Win32ImageBase::getResourceSizeW(LPCWSTR lpszName, LPWSTR lpszType, ULONG lang)
415{
416 char *astring1 = NULL, *astring2 = NULL;
417 ULONG ressize;
418
419 if(HIWORD(lpszName) != 0) {
420 astring1 = UnicodeToAsciiString((LPWSTR)lpszName);
421 }
422 else astring1 = (char *)lpszName;
423
424 if(HIWORD(lpszType) != 0) {
425 astring2 = UnicodeToAsciiString(lpszType);
426 }
427 else astring2 = (char *)lpszType;
428
429 ressize = getResourceSizeA(astring2, astring1, lang);
430
431 if(HIWORD(astring1)) FreeAsciiString(astring1);
432 if(HIWORD(astring2)) FreeAsciiString(astring2);
433
434 return(ressize);
435}
436//******************************************************************************
437//******************************************************************************
438ULONG Win32ImageBase::getVersionSize()
439{
440 return getResourceSizeA((LPCSTR)1, (LPSTR)NTRT_VERSION);
441}
442//******************************************************************************
443//******************************************************************************
444BOOL Win32ImageBase::getVersionStruct(char *verstruct, ULONG bufLength)
445{
446 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
447 int error;
448
449 if(verstruct == NULL || bufLength == 0) {
450 SetLastError(ERROR_INVALID_PARAMETER);
451 return FALSE;
452 }
453 pData = getPEResourceEntry(IDLANG_GETFIRST, NTRT_VERSION, IDLANG_GETFIRST, &error);
454 if(pData == NULL) {
455 dprintf(("Win32PeLdrImage::getVersionStruct: couldn't find version resource!"));
456 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
457 return 0;
458 }
459 char *resdata = (char *)((char *)pResDir + pData->OffsetToData - ulRVAResourceSection);
460 memcpy(verstruct, resdata, min(bufLength, pData->Size));
461 return TRUE;
462}
463
464
465/**
466 * The EnumResourceNames function searches a module for each
467 * resource of the specified type and passes the name of each
468 * resource it locates to an application-defined callback function
469 *
470 * @returns If the function succeeds, the return value is nonzero.
471 * If the function fails, the return value is zero
472 * @param hmod The specified module handle.
473 * @param lpszType pointer to resource type
474 * @param lpEnumFunc pointer to callback function
475 * @param lParam application-defined parameter
476 * @sketch IF not resources in module THEN return fail.
477 * Validate parameters.
478 * Get the subdirectory for the specified type.
479 * IF found THEN
480 * BEGIN
481 * Find the number of directory entries.
482 * Find directory entries.
483 * LOOP thru all entries while the callback function returns true
484 * BEGIN
485 * Name = pointer to ASCII name string or Id.
486 * call callback function.
487 * END
488 * END
489 * ELSE
490 * fail.
491 * return
492 * @status completely implemented and tested.
493 * @author knut st. osmundsen
494 * @remark The EnumResourceNames function continues to enumerate resource
495 * names until the callback function returns FALSE or all resource
496 * names have been enumerated
497 */
498BOOL Win32ImageBase::enumResourceNamesA(HMODULE hmod,
499 LPCTSTR lpszType,
500 ENUMRESNAMEPROCA lpEnumFunc,
501 LONG lParam)
502{
503 BOOL fRet;
504 PIMAGE_RESOURCE_DIRECTORY pResDirOurType;
505 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
506
507 if (pResDir == NULL)
508 {
509 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
510 return FALSE;
511 }
512
513 /* validate parameters - FIXME... Exception handler??? */
514 if ((unsigned)lpszType >= 0xc0000000) //....
515 {
516 SetLastError(ERROR_INVALID_PARAMETER);
517 return FALSE;
518 }
519
520 if ((unsigned)lpEnumFunc < 0x10000 || (unsigned)lpEnumFunc >= 0xc0000000)
521 {
522 SetLastError(ERROR_NOACCESS);
523 return FALSE;
524 }
525
526 //reminder:
527 //1st level -> types
528 //2nd level -> names
529 //3rd level -> language
530
531 pResDirOurType = getResSubDirA(pResDir, lpszType);
532 if (pResDirOurType != NULL)
533 {
534 char *pszASCII = NULL;
535 unsigned cch = 0;
536 unsigned cResEntries;
537 unsigned i;
538
539 fRet = TRUE;
540 cResEntries = pResDirOurType->NumberOfNamedEntries + pResDirOurType->NumberOfIdEntries;
541 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((unsigned)pResDirOurType + sizeof(*pResDirOurType));
542 for (i = 0; i < cResEntries && fRet; i++)
543 {
544 LPSTR lpszName;
545
546 if (paResDirEntries[i].u1.s.NameIsString)
547 {
548 PIMAGE_RESOURCE_DIR_STRING_U pResDirString =
549 (PIMAGE_RESOURCE_DIR_STRING_U)(paResDirEntries[i].u1.s.NameOffset + (unsigned)pResDir);
550
551 /* ASCII buffer allocation/adjustment? */
552 if (cch <= pResDirString->Length)
553 {
554 void *pszTmp;
555 cch = max(pResDirString->Length + 1, 32);
556 pszTmp = pszASCII != NULL ? realloc(pszASCII, cch) : malloc(cch);
557 if (pszTmp == NULL)
558 {
559 fRet = FALSE;
560 break;
561 }
562 pszASCII = (char*)pszTmp;
563 }
564 lstrcpynWtoA(pszASCII, pResDirString->NameString, pResDirString->Length+1);
565 lpszName = pszASCII;
566 }
567 else
568 lpszName = (LPSTR)paResDirEntries[i].u1.Id;
569
570 fRet = lpEnumFunc(hmod, lpszType, lpszName, lParam);
571 }
572
573 if (pszASCII != NULL)
574 free(pszASCII);
575 }
576 else
577 {
578 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
579 fRet = FALSE;
580 }
581
582 return fRet > 0 ? TRUE : FALSE;
583}
584
585
586/**
587 * The EnumResourceNames function searches a module for each
588 * resource of the specified type and passes the name of each
589 * resource it locates to an application-defined callback function
590 *
591 * @returns If the function succeeds, the return value is nonzero.
592 * If the function fails, the return value is zero
593 * @param hmod The specified module handle.
594 * @param lpszType pointer to resource type
595 * @param lpEnumFunc pointer to callback function
596 * @param lParam application-defined parameter
597 * @sketch IF not resources in module THEN return fail.
598 * Validate parameters.
599 * Get the subdirectory for the specified type.
600 * IF found THEN
601 * BEGIN
602 * Find the number of directory entries.
603 * Find directory entries.
604 * LOOP thru all entries while the callback function returns true
605 * BEGIN
606 * Name = pointer to ASCII name string or Id.
607 * call callback function.
608 * END
609 * END
610 * ELSE
611 * fail.
612 * return
613 * @status completely implemented and tested.
614 * @author knut st. osmundsen
615 * @remark The EnumResourceNames function continues to enumerate resource
616 * names until the callback function returns FALSE or all resource
617 * names have been enumerated
618 */
619BOOL Win32ImageBase::enumResourceNamesW(HMODULE hmod,
620 LPCWSTR lpszType,
621 ENUMRESNAMEPROCW lpEnumFunc,
622 LONG lParam)
623{
624 BOOL fRet;
625 PIMAGE_RESOURCE_DIRECTORY pResDirOurType;
626 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
627
628 if (pResDir == NULL)
629 {
630 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
631 return FALSE;
632 }
633
634 /* validate parameters - FIXME... Exception handler??? */
635 if ((unsigned)lpszType >= 0xc0000000) //....
636 {
637 SetLastError(ERROR_INVALID_PARAMETER);
638 return FALSE;
639 }
640
641 if ((unsigned)lpEnumFunc < 0x10000 || (unsigned)lpEnumFunc >= 0xc0000000)
642 {
643 SetLastError(ERROR_NOACCESS);
644 return FALSE;
645 }
646
647
648 //reminder:
649 //1st level -> types
650 //2nd level -> names
651 //3rd level -> language
652
653 pResDirOurType = getResSubDirW(pResDir, lpszType);
654 if (pResDirOurType != NULL)
655 {
656 unsigned cResEntries;
657 unsigned i;
658
659 fRet = TRUE;
660 cResEntries = pResDirOurType->NumberOfNamedEntries + pResDirOurType->NumberOfIdEntries;
661 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((unsigned)pResDirOurType + sizeof(*pResDirOurType));
662 for (i = 0; i < cResEntries && fRet; i++)
663 {
664 LPWSTR lpszName;
665
666 if (paResDirEntries[i].u1.s.NameIsString)
667 lpszName = (LPWSTR)(paResDirEntries[i].u1.s.NameOffset + (unsigned)pResDir + 2);
668 else
669 lpszName = (LPWSTR)paResDirEntries[i].u1.Id;
670
671 fRet = lpEnumFunc(hmod, lpszType, lpszName, lParam);
672 }
673 }
674 else
675 {
676 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
677 fRet = FALSE;
678 }
679
680 return fRet > 0;
681}
682
683
684
685/**
686 * This function finds a resource (sub)directory within a given resource directory.
687 * @returns Pointer to resource directory. NULL if not found or not a directory.
688 * @param pResDirToSearch Pointer to resource directory to search. (any level)
689 * @param lpszName Resource ID string.
690 * @sketch
691 * @status completely implemented
692 * @author knut st. osmundsen
693 */
694PIMAGE_RESOURCE_DIRECTORY Win32ImageBase::getResSubDirW(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch, LPCWSTR lpszName)
695{
696 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
697 int i;
698 int idName = -1;
699
700 /* lpszName */
701 if (HIWORD(lpszName) != 0)
702 {
703 if (lpszName[0] == '#')
704 {
705 char szBuf[10];
706 lstrcpynWtoA(szBuf, (WCHAR*)(lpszName + 1), sizeof(szBuf));
707 idName = atoi(szBuf);
708 }
709 }
710 else
711 idName = (int)lpszName;
712
713 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((unsigned)pResDirToSearch + sizeof(*pResDirToSearch));
714 if (idName != -1)
715 { /* idName */
716 paResDirEntries += pResDirToSearch->NumberOfNamedEntries;
717
718 for (i = 0; i < pResDirToSearch->NumberOfIdEntries; i++)
719 if (paResDirEntries[i].u1.Id == (WORD)idName)
720 return paResDirEntries[i].u2.s.DataIsDirectory ?
721 (PIMAGE_RESOURCE_DIRECTORY) (paResDirEntries[i].u2.s.OffsetToDirectory + (unsigned)pResDir /*?*/
722 /*- ulRVAResourceSection*/)
723 : NULL;
724 }
725 else
726 { /* string name */
727 int cusName = lstrlenW(lpszName);
728
729 for (i = 0; i < pResDirToSearch->NumberOfNamedEntries; i++)
730 {
731 PIMAGE_RESOURCE_DIR_STRING_U pResDirStr =
732 (PIMAGE_RESOURCE_DIR_STRING_U)(paResDirEntries[i].u1.s.NameOffset + (unsigned)pResDir /*?*/);
733
734 if (pResDirStr->Length == cusName
735 && UniStrncmp(pResDirStr->NameString, lpszName, cusName) == 0)
736 {
737 return paResDirEntries[i].u2.s.DataIsDirectory ?
738 (PIMAGE_RESOURCE_DIRECTORY) (paResDirEntries[i].u2.s.OffsetToDirectory + (unsigned)pResDir
739 /*- ulRVAResourceSection*/)
740 : NULL;
741 }
742 }
743 }
744
745 return NULL;
746}
747
748/**
749 * This function finds a resource (sub)directory within a given resource directory.
750 * @returns Pointer to resource directory. NULL if not found or not a directory.
751 * @param pResDirToSearch Pointer to resource directory to search. (any level)
752 * @param lpszName Resource ID string.
753 * @sketch
754 * @status completely implemented
755 * @author knut st. osmundsen
756 */
757PIMAGE_RESOURCE_DIRECTORY Win32ImageBase::getResSubDirA(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch, LPCTSTR lpszName)
758{
759 PIMAGE_RESOURCE_DIRECTORY pResDirRet;
760 LPCWSTR lpszwName;
761
762 /* lpszName */
763 if (HIWORD(lpszName) != 0)
764 {
765 lpszwName = AsciiToUnicodeString((char*)lpszName);
766 if (lpszwName == NULL)
767 return NULL;
768 }
769 else
770 lpszwName = (LPWSTR)lpszName;
771
772 pResDirRet = getResSubDirW(pResDirToSearch, lpszwName);
773
774 if (HIWORD(lpszwName) != 0)
775 free((void*)lpszwName);
776
777 return pResDirRet;
778}
779//******************************************************************************
780//******************************************************************************
781BOOL Win32ImageBase::enumResourceTypesA(HMODULE hmod, ENUMRESTYPEPROCA lpEnumFunc,
782 LONG lParam)
783{
784 PIMAGE_RESOURCE_DIRECTORY prdType;
785 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
786 PIMAGE_RESOURCE_DIR_STRING_U pstring;
787 ULONG i, nameOffset;
788 BOOL fRet;
789
790 if (pResDir == NULL)
791 {
792 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
793 return FALSE;
794 }
795
796 if ((unsigned)lpEnumFunc < 0x10000 || (unsigned)lpEnumFunc >= 0xc0000000)
797 {
798 SetLastError(ERROR_NOACCESS);
799 return FALSE;
800 }
801
802 //reminder:
803 //1st level -> types
804 //2nd level -> names
805 //3rd level -> language
806
807 /* set pointer to first resource type entry */
808 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
809
810 for (i=0; i<pResDir->NumberOfNamedEntries+pResDir->NumberOfIdEntries && fRet; i++)
811 {
812 /* locate directory or each resource type */
813 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResDir + (int)prde->u2.OffsetToData);
814
815 if (prde->u1.s.NameIsString)
816 {//name or id entry?
817 //SvL: 30-10-'97, high bit is set, so clear to get real offset
818 nameOffset = prde->u1.Name & ~0x80000000;
819
820 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + nameOffset);
821 char *typename = (char *)malloc(pstring->Length+1);
822 lstrcpynWtoA(typename, pstring->NameString, pstring->Length+1);
823 typename[pstring->Length] = 0;
824
825 fRet = lpEnumFunc(hmod, typename, lParam);
826 free(typename);
827 }
828 else {
829 fRet = lpEnumFunc(hmod, (LPSTR)prde->u1.Id, lParam);
830 }
831
832 /* increment to next entry */
833 prde++;
834 }
835 return fRet > 0 ? TRUE : FALSE;
836}
837//******************************************************************************
838//******************************************************************************
839BOOL Win32ImageBase::enumResourceTypesW(HMODULE hmod, ENUMRESTYPEPROCW lpEnumFunc,
840 LONG lParam)
841{
842 PIMAGE_RESOURCE_DIRECTORY prdType;
843 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
844 PIMAGE_RESOURCE_DIR_STRING_U pstring;
845 ULONG i, nameOffset;
846 BOOL fRet;
847
848 if (pResDir == NULL)
849 {
850 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
851 return FALSE;
852 }
853
854 if ((unsigned)lpEnumFunc < 0x10000 || (unsigned)lpEnumFunc >= 0xc0000000)
855 {
856 SetLastError(ERROR_NOACCESS);
857 return FALSE;
858 }
859
860 //reminder:
861 //1st level -> types
862 //2nd level -> names
863 //3rd level -> language
864
865 /* set pointer to first resource type entry */
866 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
867
868 for (i=0; i<pResDir->NumberOfNamedEntries+pResDir->NumberOfIdEntries && fRet; i++)
869 {
870 /* locate directory or each resource type */
871 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResDir + (int)prde->u2.OffsetToData);
872
873 if (prde->u1.s.NameIsString)
874 {//name or id entry?
875 //SvL: 30-10-'97, high bit is set, so clear to get real offset
876 nameOffset = prde->u1.Name & ~0x80000000;
877
878 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + nameOffset);
879 fRet = lpEnumFunc(hmod, pstring->NameString, lParam);
880 }
881 else fRet = lpEnumFunc(hmod, (LPWSTR)prde->u1.Id, lParam);
882
883 /* increment to next entry */
884 prde++;
885 }
886 return fRet > 0 ? TRUE : FALSE;
887}
888//******************************************************************************
889//******************************************************************************
Note: See TracBrowser for help on using the repository browser.