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

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

EnumResourceTypesA/W changes

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