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

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

GetFileTime bugfix + FindResource(Ex)A/W changes + setup thread security objects during creation

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