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

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

resource lookup bugfix

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