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

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

exception + enumresourcenamesa fix

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