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

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

FindResource language fixes

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