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

Last change on this file since 2802 was 2802, checked in by sandervl, 26 years ago

Added new logging feature

File size: 27.1 KB
Line 
1/* $Id: winimgres.cpp,v 1.31 2000-02-16 14:22:12 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 %d)", 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 %d)", szModule, id, type, lang));
268 }
269 else dprintf(("Win32ImageBase::getPEResource %s: couldn't find resource %d (type %d, lang %d)", szModule, id, type, lang));
270 return 0;
271 }
272 if(HIWORD(id)) {
273 dprintf(("FindResource %s: resource %s (type %d, lang %d)", szModule, id, type, lang));
274 }
275 else dprintf(("FindResource %s: resource %d (type %d, lang %d)", 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//******************************************************************************
340#if 0
341ULONG Win32Pe2LxImage::getVersionSize()
342{
343 if(getVersionId() == -1) {
344 dprintf(("GetVersionSize: %s has no version resource!\n", szModule));
345 return(0);
346 }
347 return OSLibGetResourceSize(hinstance, getVersionId());
348}
349//******************************************************************************
350//******************************************************************************
351BOOL Win32Pe2LxImage::getVersionStruct(char *verstruct, ULONG bufLength)
352{
353 if(getVersionId() == -1) {
354 dprintf(("GetVersionStruct: %s has no version resource!\n", szModule));
355 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
356 return(FALSE);
357 }
358 return OSLibGetResource(hinstance, getVersionId(), verstruct, bufLength);
359}
360#endif
361//******************************************************************************
362//******************************************************************************
363ULONG Win32ImageBase::getVersionSize()
364{
365 return getResourceSizeA((LPCSTR)1, (LPSTR)NTRT_VERSION);
366}
367//******************************************************************************
368//******************************************************************************
369BOOL Win32ImageBase::getVersionStruct(char *verstruct, ULONG bufLength)
370{
371 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
372
373 if(verstruct == NULL || bufLength == 0) {
374 SetLastError(ERROR_INVALID_PARAMETER);
375 return FALSE;
376 }
377 pData = getPEResourceEntry(ID_GETFIRST, NTRT_VERSION);
378 if(pData == NULL) {
379 dprintf(("Win32PeLdrImage::getVersionStruct: couldn't find version resource!"));
380 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
381 return 0;
382 }
383 char *resdata = (char *)((char *)pResDir + pData->OffsetToData - ulRVAResourceSection);
384 memcpy(verstruct, resdata, min(bufLength, pData->Size));
385 return TRUE;
386}
387
388
389/**
390 * The EnumResourceNames function searches a module for each
391 * resource of the specified type and passes the name of each
392 * resource it locates to an application-defined callback function
393 *
394 * @returns If the function succeeds, the return value is nonzero.
395 * If the function fails, the return value is zero
396 * @param hmod The specified module handle.
397 * @param lpszType pointer to resource type
398 * @param lpEnumFunc pointer to callback function
399 * @param lParam application-defined parameter
400 * @sketch IF not resources in module THEN return fail.
401 * Validate parameters.
402 * Get the subdirectory for the specified type.
403 * IF found THEN
404 * BEGIN
405 * Find the number of directory entries.
406 * Find directory entries.
407 * LOOP thru all entries while the callback function returns true
408 * BEGIN
409 * Name = pointer to ASCII name string or Id.
410 * call callback function.
411 * END
412 * END
413 * ELSE
414 * fail.
415 * return
416 * @status completely implemented and tested.
417 * @author knut st. osmundsen
418 * @remark The EnumResourceNames function continues to enumerate resource
419 * names until the callback function returns FALSE or all resource
420 * names have been enumerated
421 */
422BOOL Win32ImageBase::enumResourceNamesA(HMODULE hmod,
423 LPCTSTR lpszType,
424 ENUMRESNAMEPROCA lpEnumFunc,
425 LONG lParam)
426{
427 BOOL fRet;
428 PIMAGE_RESOURCE_DIRECTORY pResDirOurType;
429 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
430
431 if (pResDir == NULL)
432 {
433 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
434 return FALSE;
435 }
436
437 /* validate parameters - FIXME... Exception handler??? */
438 if ((unsigned)lpszType >= 0xc0000000) //....
439 {
440 SetLastError(ERROR_INVALID_PARAMETER);
441 return FALSE;
442 }
443
444 if ((unsigned)lpEnumFunc < 0x10000 || (unsigned)lpEnumFunc >= 0xc0000000)
445 {
446 SetLastError(ERROR_NOACCESS);
447 return FALSE;
448 }
449
450 //reminder:
451 //1st level -> types
452 //2nd level -> names
453 //3rd level -> language
454
455 pResDirOurType = getResSubDirA(pResDir, lpszType);
456 if (pResDirOurType != NULL)
457 {
458 char *pszASCII = NULL;
459 unsigned cch = 0;
460 unsigned cResEntries;
461 unsigned i;
462
463 fRet = TRUE;
464 cResEntries = pResDirOurType->NumberOfNamedEntries + pResDirOurType->NumberOfIdEntries;
465 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((unsigned)pResDirOurType + sizeof(*pResDirOurType));
466 for (i = 0; i < cResEntries && fRet; i++)
467 {
468 LPSTR lpszName;
469
470 if (paResDirEntries[i].u1.s.NameIsString)
471 {
472 PIMAGE_RESOURCE_DIR_STRING_U pResDirString =
473 (PIMAGE_RESOURCE_DIR_STRING_U)(paResDirEntries[i].u1.s.NameOffset + (unsigned)pResDir);
474
475 /* ASCII buffer allocation/adjustment? */
476 if (cch <= pResDirString->Length)
477 {
478 void *pszTmp;
479 cch = max(pResDirString->Length + 1, 32);
480 pszTmp = pszASCII != NULL ? realloc(pszASCII, cch) : malloc(cch);
481 if (pszTmp == NULL)
482 {
483 fRet = FALSE;
484 break;
485 }
486 pszASCII = (char*)pszTmp;
487 }
488 UnicodeToAsciiN(pResDirString->NameString, pszASCII, pResDirString->Length);
489 lpszName = pszASCII;
490 }
491 else
492 lpszName = (LPSTR)paResDirEntries[i].u1.Id;
493
494 fRet = lpEnumFunc(hmod, lpszType, lpszName, lParam);
495 }
496
497 if (pszASCII != NULL)
498 free(pszASCII);
499 }
500 else
501 {
502 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
503 fRet = FALSE;
504 }
505
506 return fRet > 0 ? TRUE : FALSE;
507}
508
509
510/**
511 * The EnumResourceNames function searches a module for each
512 * resource of the specified type and passes the name of each
513 * resource it locates to an application-defined callback function
514 *
515 * @returns If the function succeeds, the return value is nonzero.
516 * If the function fails, the return value is zero
517 * @param hmod The specified module handle.
518 * @param lpszType pointer to resource type
519 * @param lpEnumFunc pointer to callback function
520 * @param lParam application-defined parameter
521 * @sketch IF not resources in module THEN return fail.
522 * Validate parameters.
523 * Get the subdirectory for the specified type.
524 * IF found THEN
525 * BEGIN
526 * Find the number of directory entries.
527 * Find directory entries.
528 * LOOP thru all entries while the callback function returns true
529 * BEGIN
530 * Name = pointer to ASCII name string or Id.
531 * call callback function.
532 * END
533 * END
534 * ELSE
535 * fail.
536 * return
537 * @status completely implemented and tested.
538 * @author knut st. osmundsen
539 * @remark The EnumResourceNames function continues to enumerate resource
540 * names until the callback function returns FALSE or all resource
541 * names have been enumerated
542 */
543BOOL Win32ImageBase::enumResourceNamesW(HMODULE hmod,
544 LPCWSTR lpszType,
545 ENUMRESNAMEPROCW lpEnumFunc,
546 LONG lParam)
547{
548 BOOL fRet;
549 PIMAGE_RESOURCE_DIRECTORY pResDirOurType;
550 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
551
552 if (pResDir == NULL)
553 {
554 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
555 return FALSE;
556 }
557
558 /* validate parameters - FIXME... Exception handler??? */
559 if ((unsigned)lpszType >= 0xc0000000) //....
560 {
561 SetLastError(ERROR_INVALID_PARAMETER);
562 return FALSE;
563 }
564
565 if ((unsigned)lpEnumFunc < 0x10000 || (unsigned)lpEnumFunc >= 0xc0000000)
566 {
567 SetLastError(ERROR_NOACCESS);
568 return FALSE;
569 }
570
571
572 //reminder:
573 //1st level -> types
574 //2nd level -> names
575 //3rd level -> language
576
577 pResDirOurType = getResSubDirW(pResDir, lpszType);
578 if (pResDirOurType != NULL)
579 {
580 unsigned cResEntries;
581 unsigned i;
582
583 fRet = TRUE;
584 cResEntries = pResDirOurType->NumberOfNamedEntries + pResDirOurType->NumberOfIdEntries;
585 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((unsigned)pResDirOurType + sizeof(*pResDirOurType));
586 for (i = 0; i < cResEntries && fRet; i++)
587 {
588 LPWSTR lpszName;
589
590 if (paResDirEntries[i].u1.s.NameIsString)
591 lpszName = (LPWSTR)(paResDirEntries[i].u1.s.NameOffset + (unsigned)pResDir + 2);
592 else
593 lpszName = (LPWSTR)paResDirEntries[i].u1.Id;
594
595 fRet = lpEnumFunc(hmod, lpszType, lpszName, lParam);
596 }
597 }
598 else
599 {
600 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
601 fRet = FALSE;
602 }
603
604 return fRet > 0;
605}
606
607
608
609/**
610 * This function finds a resource (sub)directory within a given resource directory.
611 * @returns Pointer to resource directory. NULL if not found or not a directory.
612 * @param pResDirToSearch Pointer to resource directory to search. (any level)
613 * @param lpszName Resource ID string.
614 * @sketch
615 * @status completely implemented
616 * @author knut st. osmundsen
617 */
618PIMAGE_RESOURCE_DIRECTORY Win32ImageBase::getResSubDirW(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch, LPCWSTR lpszName)
619{
620 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
621 int i;
622 int idName = -1;
623
624 /* lpszName */
625 if (HIWORD(lpszName) != 0)
626 {
627 if (lpszName[0] == '#')
628 {
629 char szBuf[10];
630 lstrcpynWtoA(szBuf, (WCHAR*)(lpszName + 1), sizeof(szBuf));
631 idName = atoi(szBuf);
632 }
633 }
634 else
635 idName = (int)lpszName;
636
637 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((unsigned)pResDirToSearch + sizeof(*pResDirToSearch));
638 if (idName != -1)
639 { /* idName */
640 paResDirEntries += pResDirToSearch->NumberOfNamedEntries;
641
642 for (i = 0; i < pResDirToSearch->NumberOfIdEntries; i++)
643 if (paResDirEntries[i].u1.Id == (WORD)idName)
644 return paResDirEntries[i].u2.s.DataIsDirectory ?
645 (PIMAGE_RESOURCE_DIRECTORY) (paResDirEntries[i].u2.s.OffsetToDirectory + (unsigned)pResDir /*?*/
646 /*- ulRVAResourceSection*/)
647 : NULL;
648 }
649 else
650 { /* string name */
651 int cusName = lstrlenW(lpszName);
652
653 for (i = 0; i < pResDirToSearch->NumberOfNamedEntries; i++)
654 {
655 PIMAGE_RESOURCE_DIR_STRING_U pResDirStr =
656 (PIMAGE_RESOURCE_DIR_STRING_U)(paResDirEntries[i].u1.s.NameOffset + (unsigned)pResDir /*?*/);
657
658 if (pResDirStr->Length == cusName
659 && UniStrncmp(pResDirStr->NameString, lpszName, cusName) == 0)
660 {
661 return paResDirEntries[i].u2.s.DataIsDirectory ?
662 (PIMAGE_RESOURCE_DIRECTORY) (paResDirEntries[i].u2.s.OffsetToDirectory + (unsigned)pResDir
663 /*- ulRVAResourceSection*/)
664 : NULL;
665 }
666 }
667 }
668
669 return NULL;
670}
671
672/**
673 * This function finds a resource (sub)directory within a given resource directory.
674 * @returns Pointer to resource directory. NULL if not found or not a directory.
675 * @param pResDirToSearch Pointer to resource directory to search. (any level)
676 * @param lpszName Resource ID string.
677 * @sketch
678 * @status completely implemented
679 * @author knut st. osmundsen
680 */
681PIMAGE_RESOURCE_DIRECTORY Win32ImageBase::getResSubDirA(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch, LPCTSTR lpszName)
682{
683 PIMAGE_RESOURCE_DIRECTORY pResDirRet;
684 LPCWSTR lpszwName;
685
686 /* lpszName */
687 if (HIWORD(lpszName) != 0)
688 {
689 lpszwName = AsciiToUnicodeString((char*)lpszName);
690 if (lpszwName == NULL)
691 return NULL;
692 }
693 else
694 lpszwName = (LPWSTR)lpszName;
695
696 pResDirRet = getResSubDirW(pResDirToSearch, lpszwName);
697
698 if (HIWORD(lpszwName) != 0)
699 free((void*)lpszwName);
700
701 return pResDirRet;
702}
703//******************************************************************************
704//******************************************************************************
705BOOL Win32ImageBase::enumResourceTypesA(HMODULE hmod, ENUMRESTYPEPROCA lpEnumFunc,
706 LONG lParam)
707{
708 PIMAGE_RESOURCE_DIRECTORY prdType;
709 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
710 PIMAGE_RESOURCE_DIR_STRING_U pstring;
711 ULONG i, nameOffset;
712 BOOL fRet;
713
714 if (pResDir == NULL)
715 {
716 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
717 return FALSE;
718 }
719
720 if ((unsigned)lpEnumFunc < 0x10000 || (unsigned)lpEnumFunc >= 0xc0000000)
721 {
722 SetLastError(ERROR_NOACCESS);
723 return FALSE;
724 }
725
726 //reminder:
727 //1st level -> types
728 //2nd level -> names
729 //3rd level -> language
730
731 /* set pointer to first resource type entry */
732 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
733
734 for (i=0; i<pResDir->NumberOfNamedEntries+pResDir->NumberOfIdEntries && fRet; i++)
735 {
736 /* locate directory or each resource type */
737 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResDir + (int)prde->u2.OffsetToData);
738
739 if (prde->u1.s.NameIsString)
740 {//name or id entry?
741 //SvL: 30-10-'97, high bit is set, so clear to get real offset
742 nameOffset = prde->u1.Name & ~0x80000000;
743
744 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + nameOffset);
745 char *typename = (char *)malloc(pstring->Length+1);
746 lstrcpynWtoA(typename, pstring->NameString, pstring->Length+1);
747 typename[pstring->Length] = 0;
748
749 fRet = lpEnumFunc(hmod, typename, lParam);
750 free(typename);
751 }
752 else {
753 fRet = lpEnumFunc(hmod, (LPSTR)prde->u1.Id, lParam);
754 }
755
756 /* increment to next entry */
757 prde++;
758 }
759 return fRet > 0 ? TRUE : FALSE;
760}
761//******************************************************************************
762//******************************************************************************
763BOOL Win32ImageBase::enumResourceTypesW(HMODULE hmod, ENUMRESTYPEPROCW lpEnumFunc,
764 LONG lParam)
765{
766 PIMAGE_RESOURCE_DIRECTORY prdType;
767 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
768 PIMAGE_RESOURCE_DIR_STRING_U pstring;
769 ULONG i, nameOffset;
770 BOOL fRet;
771
772 if (pResDir == NULL)
773 {
774 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
775 return FALSE;
776 }
777
778 if ((unsigned)lpEnumFunc < 0x10000 || (unsigned)lpEnumFunc >= 0xc0000000)
779 {
780 SetLastError(ERROR_NOACCESS);
781 return FALSE;
782 }
783
784 //reminder:
785 //1st level -> types
786 //2nd level -> names
787 //3rd level -> language
788
789 /* set pointer to first resource type entry */
790 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
791
792 for (i=0; i<pResDir->NumberOfNamedEntries+pResDir->NumberOfIdEntries && fRet; i++)
793 {
794 /* locate directory or each resource type */
795 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResDir + (int)prde->u2.OffsetToData);
796
797 if (prde->u1.s.NameIsString)
798 {//name or id entry?
799 //SvL: 30-10-'97, high bit is set, so clear to get real offset
800 nameOffset = prde->u1.Name & ~0x80000000;
801
802 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + nameOffset);
803 fRet = lpEnumFunc(hmod, pstring->NameString, lParam);
804 }
805 else fRet = lpEnumFunc(hmod, (LPWSTR)prde->u1.Id, lParam);
806
807 /* increment to next entry */
808 prde++;
809 }
810 return fRet > 0 ? TRUE : FALSE;
811}
812//******************************************************************************
813//******************************************************************************
Note: See TracBrowser for help on using the repository browser.