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

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

Critical section changes

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