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

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

resource handling changes

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