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

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

Added process api + virtualprotect fix

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