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

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

GetModuleHandle fix + minor changes

File size: 27.4 KB
Line 
1/* $Id: winimgres.cpp,v 1.45 2000-08-17 18:22:18 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 SetLastError(ERROR_SUCCESS);
169 return hRes;
170}
171//******************************************************************************
172//******************************************************************************
173HRSRC Win32ImageBase::findResourceW(LPWSTR lpszName, LPWSTR lpszType, ULONG lang)
174{
175 PIMAGE_RESOURCE_DIRECTORY pResDirRet;
176 char *astring1 = NULL;
177 int typelen;
178 HRSRC hRes;
179
180 if(HIWORD(lpszType) != 0 && lpszType[0] != (WCHAR)'#')
181 {
182 astring1 = UnicodeToAsciiString(lpszType);
183 typelen = strlen(astring1);
184
185 for(int i=0;i<MAX_RES;i++) {
186 if(ResType[i].namelen &&
187 ResType[i].namelen == typelen &&
188 stricmp(astring1, ResType[i].typename) == 0)
189 break;
190 }
191 if(i != MAX_RES) {//standard res type
192 lpszType = (LPWSTR)i;
193 }
194 FreeAsciiString(astring1);
195 }
196 pResDirRet = getResSubDirW(pResRootDir, lpszType);
197 if(!pResDirRet) {
198 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
199 return NULL;
200 }
201 pResDirRet = getResSubDirW(pResDirRet, lpszName);
202 if(!pResDirRet) {
203 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
204 return NULL;
205 }
206
207 /* Here is the real difference between FindResource and FindResourceEx */
208 if(lang == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) ||
209 lang == MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) ||
210 lang == MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT) ||
211 lang == MAKELANGID(LANG_NEUTRAL, 3)) /* FIXME: real name? */
212 {
213 hRes = getResourceLang(pResDirRet);
214 }
215 else hRes = getResourceLangEx(pResDirRet, lang);
216
217 SetLastError(ERROR_SUCCESS);
218 return hRes;
219}
220//******************************************************************************
221//According to Wine:
222/* FindResourceA/W does search in the following order:
223 * 1. Neutral language with neutral sublanguage
224 * 2. Neutral language with default sublanguage
225 * 3. Current locale lang id
226 * 4. Current locale lang id with neutral sublanguage
227 * 5. (!) LANG_ENGLISH, SUBLANG_DEFAULT
228 * 6. Return first in the list
229 */
230//******************************************************************************
231HRSRC Win32ImageBase::getResourceLang(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch)
232{
233 HRSRC hRes;
234 DWORD lang;
235
236 /* 1. Neutral language with neutral sublanguage */
237 lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
238 hRes = (HRSRC)getResDataLang(pResDirToSearch, lang);
239 if(!hRes) {
240 /* 2. Neutral language with default sublanguage */
241 lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
242 hRes = (HRSRC)getResDataLang(pResDirToSearch, lang);
243 }
244 if(!hRes) {
245 /* 3. Current locale lang id */
246 lang = LANGIDFROMLCID(GetUserDefaultLCID());
247 hRes = (HRSRC)getResDataLang(pResDirToSearch, lang);
248 }
249 if(!hRes) {
250 /* 4. Current locale lang id with neutral sublanguage */
251 lang = MAKELANGID(PRIMARYLANGID(lang), SUBLANG_NEUTRAL);
252 hRes = (HRSRC)getResDataLang(pResDirToSearch, lang);
253 }
254 if(!hRes) {
255 /* 5. (!) LANG_ENGLISH, SUBLANG_DEFAULT */
256 lang = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
257 hRes = (HRSRC)getResDataLang(pResDirToSearch, lang);
258 }
259 if(!hRes) {
260 /* 6. Return first in the list */
261 hRes = (HRSRC)getResDataLang(pResDirToSearch, lang, TRUE);
262 }
263 return hRes;
264}
265//******************************************************************************
266//According to Wine:
267/* FindResourceExA/W does search in the following order:
268 * 1. Exact specified language
269 * 2. Language with neutral sublanguage
270 * 3. Neutral language with neutral sublanguage
271 * 4. Neutral language with default sublanguage
272 */
273//******************************************************************************
274HRSRC Win32ImageBase::getResourceLangEx(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch,
275 DWORD lang)
276{
277 HRSRC hRes;
278
279 /* 1. Exact specified language */
280 hRes = (HRSRC)getResDataLang(pResDirToSearch, lang);
281 if(!hRes) {
282 /* 2. Language with neutral sublanguage */
283 lang = MAKELANGID(PRIMARYLANGID(lang), SUBLANG_NEUTRAL);
284 hRes = (HRSRC)getResDataLang(pResDirToSearch, lang);
285 }
286 if(!hRes) {
287 /* 3. Neutral language with neutral sublanguage */
288 lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
289 hRes = (HRSRC)getResDataLang(pResDirToSearch, lang);
290 }
291 if(!hRes) {
292 /* 4. Current locale lang id with neutral sublanguage */
293 lang = MAKELANGID(PRIMARYLANGID(lang), SUBLANG_NEUTRAL);
294 hRes = (HRSRC)getResDataLang(pResDirToSearch, lang);
295 }
296 return hRes;
297}
298//******************************************************************************
299//******************************************************************************
300ULONG Win32ImageBase::getVersionSize()
301{
302 return getResourceSizeW((LPWSTR)1, (LPWSTR)NTRT_VERSION);
303}
304//******************************************************************************
305//******************************************************************************
306BOOL Win32ImageBase::getVersionStruct(char *verstruct, ULONG bufLength)
307{
308 HRSRC hRes;
309
310 if(verstruct == NULL || bufLength == 0) {
311 SetLastError(ERROR_INVALID_PARAMETER);
312 return FALSE;
313 }
314 hRes = findResourceW((LPWSTR)ID_GETFIRST, (LPWSTR)NTRT_VERSION, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
315 if(hRes == NULL) {
316 //last error already set by findResourceW
317 dprintf(("Win32PeLdrImage::getVersionStruct: couldn't find version resource!"));
318 return 0;
319 }
320 memcpy(verstruct, getResourceAddr(hRes), min(bufLength, getResourceSize(hRes)));
321 SetLastError(ERROR_SUCCESS);
322 return TRUE;
323}
324
325
326/**
327 * The EnumResourceNames function searches a module for each
328 * resource of the specified type and passes the name of each
329 * resource it locates to an application-defined callback function
330 *
331 * @returns If the function succeeds, the return value is nonzero.
332 * If the function fails, the return value is zero
333 * @param hmod The specified module handle.
334 * @param lpszType pointer to resource type
335 * @param lpEnumFunc pointer to callback function
336 * @param lParam application-defined parameter
337 * @sketch IF not resources in module THEN return fail.
338 * Validate parameters.
339 * Get the subdirectory for the specified type.
340 * IF found THEN
341 * BEGIN
342 * Find the number of directory entries.
343 * Find directory entries.
344 * LOOP thru all entries while the callback function returns true
345 * BEGIN
346 * Name = pointer to ASCII name string or Id.
347 * call callback function.
348 * END
349 * END
350 * ELSE
351 * fail.
352 * return
353 * @status completely implemented and tested.
354 * @author knut st. osmundsen
355 * @remark The EnumResourceNames function continues to enumerate resource
356 * names until the callback function returns FALSE or all resource
357 * names have been enumerated
358 */
359BOOL Win32ImageBase::enumResourceNamesA(HMODULE hmod,
360 LPCTSTR lpszType,
361 ENUMRESNAMEPROCA lpEnumFunc,
362 LONG lParam)
363{
364 BOOL fRet;
365 PIMAGE_RESOURCE_DIRECTORY pResDirOurType;
366 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
367
368 if (pResRootDir == NULL)
369 {
370 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
371 return FALSE;
372 }
373
374 /* validate parameters - FIXME... Exception handler??? */
375 if ((ULONG)lpszType >= 0xc0000000) //....
376 {
377 SetLastError(ERROR_INVALID_PARAMETER);
378 return FALSE;
379 }
380
381 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
382 {
383 SetLastError(ERROR_NOACCESS);
384 return FALSE;
385 }
386
387 //reminder:
388 //1st level -> types
389 //2nd level -> names
390 //3rd level -> language
391
392 pResDirOurType = getResSubDirA(pResRootDir, lpszType);
393 if (pResDirOurType != NULL)
394 {
395 char *pszASCII = NULL;
396 unsigned cch = 0;
397 unsigned cResEntries;
398 unsigned i;
399
400 fRet = TRUE;
401 cResEntries = pResDirOurType->NumberOfNamedEntries + pResDirOurType->NumberOfIdEntries;
402 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirOurType + sizeof(*pResDirOurType));
403 for (i = 0; i < cResEntries && fRet; i++)
404 {
405 LPSTR lpszName;
406
407 if (paResDirEntries[i].u1.s.NameIsString)
408 {
409 PIMAGE_RESOURCE_DIR_STRING_U pResDirString =
410 (PIMAGE_RESOURCE_DIR_STRING_U)(paResDirEntries[i].u1.s.NameOffset + (ULONG)pResRootDir);
411
412 /* ASCII buffer allocation/adjustment? */
413 if (cch <= pResDirString->Length)
414 {
415 void *pszTmp;
416 cch = max(pResDirString->Length + 1, 32);
417 pszTmp = pszASCII != NULL ? realloc(pszASCII, cch) : malloc(cch);
418 if (pszTmp == NULL)
419 {
420 fRet = FALSE;
421 break;
422 }
423 pszASCII = (char*)pszTmp;
424 }
425 lstrcpynWtoA(pszASCII, pResDirString->NameString, pResDirString->Length+1);
426 lpszName = pszASCII;
427 }
428 else
429 lpszName = (LPSTR)paResDirEntries[i].u1.Id;
430
431 fRet = lpEnumFunc(hmod, lpszType, lpszName, lParam);
432 }
433
434 if (pszASCII != NULL)
435 free(pszASCII);
436 }
437 else
438 {
439 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
440 fRet = FALSE;
441 }
442
443 return fRet > 0 ? TRUE : FALSE;
444}
445
446
447/**
448 * The EnumResourceNames function searches a module for each
449 * resource of the specified type and passes the name of each
450 * resource it locates to an application-defined callback function
451 *
452 * @returns If the function succeeds, the return value is nonzero.
453 * If the function fails, the return value is zero
454 * @param hmod The specified module handle.
455 * @param lpszType pointer to resource type
456 * @param lpEnumFunc pointer to callback function
457 * @param lParam application-defined parameter
458 * @sketch IF not resources in module THEN return fail.
459 * Validate parameters.
460 * Get the subdirectory for the specified type.
461 * IF found THEN
462 * BEGIN
463 * Find the number of directory entries.
464 * Find directory entries.
465 * LOOP thru all entries while the callback function returns true
466 * BEGIN
467 * Name = pointer to ASCII name string or Id.
468 * call callback function.
469 * END
470 * END
471 * ELSE
472 * fail.
473 * return
474 * @status completely implemented and tested.
475 * @author knut st. osmundsen
476 * @remark The EnumResourceNames function continues to enumerate resource
477 * names until the callback function returns FALSE or all resource
478 * names have been enumerated
479 */
480BOOL Win32ImageBase::enumResourceNamesW(HMODULE hmod,
481 LPCWSTR lpszType,
482 ENUMRESNAMEPROCW lpEnumFunc,
483 LONG lParam)
484{
485 BOOL fRet;
486 PIMAGE_RESOURCE_DIRECTORY pResDirOurType;
487 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
488
489 if (pResRootDir == NULL)
490 {
491 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
492 return FALSE;
493 }
494
495 /* validate parameters - FIXME... Exception handler??? */
496 if ((ULONG)lpszType >= 0xc0000000) //....
497 {
498 SetLastError(ERROR_INVALID_PARAMETER);
499 return FALSE;
500 }
501
502 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
503 {
504 SetLastError(ERROR_NOACCESS);
505 return FALSE;
506 }
507
508
509 //reminder:
510 //1st level -> types
511 //2nd level -> names
512 //3rd level -> language
513
514 pResDirOurType = getResSubDirW(pResRootDir, lpszType);
515 if (pResDirOurType != NULL)
516 {
517 unsigned cResEntries;
518 unsigned i;
519
520 fRet = TRUE;
521 cResEntries = pResDirOurType->NumberOfNamedEntries + pResDirOurType->NumberOfIdEntries;
522 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirOurType + sizeof(*pResDirOurType));
523 for (i = 0; i < cResEntries && fRet; i++)
524 {
525 LPWSTR lpszName;
526
527 if (paResDirEntries[i].u1.s.NameIsString)
528 lpszName = (LPWSTR)(paResDirEntries[i].u1.s.NameOffset + (ULONG)pResRootDir + 2);
529 else
530 lpszName = (LPWSTR)paResDirEntries[i].u1.Id;
531
532 fRet = lpEnumFunc(hmod, lpszType, lpszName, lParam);
533 }
534 }
535 else
536 {
537 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
538 fRet = FALSE;
539 }
540
541 return fRet > 0;
542}
543
544
545
546/**
547 * This function finds a resource (sub)directory within a given resource directory.
548 * @returns Pointer to resource directory. NULL if not found or not a directory.
549 * @param pResDirToSearch Pointer to resource directory to search. (any level)
550 * @param lpszName Resource ID string.
551 * @sketch
552 * @status completely implemented
553 * @author knut st. osmundsen
554 */
555PIMAGE_RESOURCE_DIRECTORY Win32ImageBase::getResSubDirW(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch,
556 LPCWSTR lpszName)
557{
558 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
559 int i;
560 int idName = -1;
561
562 if(pResDirToSearch == NULL) {
563 return NULL;
564 }
565
566 /* lpszName */
567 if ((ULONG)lpszName != ID_GETFIRST && HIWORD(lpszName) != 0)
568 {
569 if (lpszName[0] == '#')
570 {
571 char szBuf[10];
572 lstrcpynWtoA(szBuf, (WCHAR*)(lpszName + 1), sizeof(szBuf));
573 idName = atoi(szBuf);
574 }
575 }
576 else
577 idName = (int)lpszName;
578
579 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirToSearch + sizeof(*pResDirToSearch));
580 if(idName == ID_GETFIRST) {
581 return paResDirEntries[0].u2.s.DataIsDirectory ?
582 (PIMAGE_RESOURCE_DIRECTORY) (paResDirEntries[0].u2.s.OffsetToDirectory + (ULONG)pResRootDir)
583 : NULL;
584 }
585
586 if (idName != -1)
587 { /* idName */
588 paResDirEntries += pResDirToSearch->NumberOfNamedEntries;
589
590 for (i = 0; i < pResDirToSearch->NumberOfIdEntries; i++)
591 if (paResDirEntries[i].u1.Id == (WORD)idName)
592 return paResDirEntries[i].u2.s.DataIsDirectory ?
593 (PIMAGE_RESOURCE_DIRECTORY) (paResDirEntries[i].u2.s.OffsetToDirectory + (ULONG)pResRootDir /*?*/
594 /*- ulRVAResourceSection*/)
595 : NULL;
596 }
597 else
598 { /* string name */
599 int cusName = lstrlenW(lpszName);
600
601 for (i = 0; i < pResDirToSearch->NumberOfNamedEntries; i++)
602 {
603 PIMAGE_RESOURCE_DIR_STRING_U pResDirStr =
604 (PIMAGE_RESOURCE_DIR_STRING_U)(paResDirEntries[i].u1.s.NameOffset + (ULONG)pResRootDir /*?*/);
605
606 //SvL: Must do case insensitive string compare here
607 if (pResDirStr->Length == cusName
608 && lstrncmpiW(pResDirStr->NameString, lpszName, cusName) == 0)
609 {
610 return paResDirEntries[i].u2.s.DataIsDirectory ?
611 (PIMAGE_RESOURCE_DIRECTORY) (paResDirEntries[i].u2.s.OffsetToDirectory + (ULONG)pResRootDir
612 /*- ulRVAResourceSection*/)
613 : NULL;
614 }
615 }
616 }
617
618 return NULL;
619}
620
621/**
622 * This function finds a resource (sub)directory within a given resource directory.
623 * @returns Pointer to resource directory. NULL if not found or not a directory.
624 * @param pResDirToSearch Pointer to resource directory to search. (any level)
625 * @param lpszName Resource ID string.
626 * @sketch
627 * @status completely implemented
628 * @author knut st. osmundsen
629 */
630PIMAGE_RESOURCE_DIRECTORY Win32ImageBase::getResSubDirA(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch,
631 LPCTSTR lpszName)
632{
633 PIMAGE_RESOURCE_DIRECTORY pResDirRet;
634 LPCWSTR lpszwName;
635
636 if(pResDirToSearch == NULL) {
637 return NULL;
638 }
639
640 /* lpszName */
641 if ((ULONG)lpszName != ID_GETFIRST && HIWORD(lpszName) != 0)
642 {
643 lpszwName = AsciiToUnicodeString((char*)lpszName);
644 if (lpszwName == NULL)
645 return NULL;
646 }
647 else
648 lpszwName = (LPWSTR)lpszName;
649
650 pResDirRet = getResSubDirW(pResDirToSearch, lpszwName);
651
652 if ((ULONG)lpszName != ID_GETFIRST && HIWORD(lpszwName) != 0)
653 free((void*)lpszwName);
654
655 return pResDirRet;
656}
657//******************************************************************************
658/**
659 * This function finds a resource data entry within a given resource directory.
660 * @returns Pointer to resource data entry. NULL if not found
661 * @param pResDirToSearch Pointer to resource directory to search. (lang level)
662 * @param language Resource language id
663 * @param fGetDefault TRUE -> get first available resource if not found
664 * @sketch
665 * @status completely implemented
666 * @author Sander van Leeuwen
667 */
668//******************************************************************************
669PIMAGE_RESOURCE_DATA_ENTRY
670 Win32ImageBase::getResDataLang(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch,
671 ULONG language, BOOL fGetDefault)
672{
673 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
674 int i;
675
676 if(pResDirToSearch == NULL) {
677 return NULL;
678 }
679
680 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirToSearch + sizeof(*pResDirToSearch));
681
682 if(pResDirToSearch->NumberOfNamedEntries) {
683 DebugInt3();
684 }
685 paResDirEntries += pResDirToSearch->NumberOfNamedEntries;
686
687 for (i = 0; i < pResDirToSearch->NumberOfIdEntries; i++) {
688 if (paResDirEntries[i].u1.Id == language)
689 {
690 return (PIMAGE_RESOURCE_DATA_ENTRY) (paResDirEntries[i].u2.s.OffsetToDirectory + (ULONG)pResRootDir);
691 }
692 }
693
694 // if nothing found and fGetDefault is true, return first entry
695 if(fGetDefault)
696 {
697 return (PIMAGE_RESOURCE_DATA_ENTRY) (paResDirEntries[0].u2.s.OffsetToDirectory + (ULONG)pResRootDir);
698 }
699 return NULL;
700}
701//******************************************************************************
702//******************************************************************************
703BOOL Win32ImageBase::enumResourceTypesA(HMODULE hmod, ENUMRESTYPEPROCA lpEnumFunc,
704 LONG lParam)
705{
706 PIMAGE_RESOURCE_DIRECTORY prdType;
707 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
708 PIMAGE_RESOURCE_DIR_STRING_U pstring;
709 ULONG i, nameOffset;
710 BOOL fRet;
711
712 if (pResRootDir == NULL)
713 {
714 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
715 return FALSE;
716 }
717
718 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
719 {
720 SetLastError(ERROR_NOACCESS);
721 return FALSE;
722 }
723
724 //reminder:
725 //1st level -> types
726 //2nd level -> names
727 //3rd level -> language
728
729 /* set pointer to first resource type entry */
730 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResRootDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
731
732 for (i=0; i<pResRootDir->NumberOfNamedEntries+pResRootDir->NumberOfIdEntries && fRet; i++)
733 {
734 /* locate directory or each resource type */
735 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResRootDir + (int)prde->u2.OffsetToData);
736
737 if (prde->u1.s.NameIsString)
738 {//name or id entry?
739 //SvL: 30-10-'97, high bit is set, so clear to get real offset
740 nameOffset = prde->u1.Name & ~0x80000000;
741
742 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResRootDir + nameOffset);
743 char *typename = (char *)malloc(pstring->Length+1);
744 lstrcpynWtoA(typename, pstring->NameString, pstring->Length+1);
745 typename[pstring->Length] = 0;
746
747 fRet = lpEnumFunc(hmod, typename, lParam);
748 free(typename);
749 }
750 else {
751 fRet = lpEnumFunc(hmod, (LPSTR)prde->u1.Id, lParam);
752 }
753
754 /* increment to next entry */
755 prde++;
756 }
757 return fRet > 0 ? TRUE : FALSE;
758}
759//******************************************************************************
760//******************************************************************************
761BOOL Win32ImageBase::enumResourceTypesW(HMODULE hmod, ENUMRESTYPEPROCW lpEnumFunc,
762 LONG lParam)
763{
764 PIMAGE_RESOURCE_DIRECTORY prdType;
765 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
766 PIMAGE_RESOURCE_DIR_STRING_U pstring;
767 ULONG i, nameOffset;
768 BOOL fRet;
769
770 if (pResRootDir == NULL)
771 {
772 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
773 return FALSE;
774 }
775
776 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
777 {
778 SetLastError(ERROR_NOACCESS);
779 return FALSE;
780 }
781
782 //reminder:
783 //1st level -> types
784 //2nd level -> names
785 //3rd level -> language
786
787 /* set pointer to first resource type entry */
788 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResRootDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
789
790 for (i=0; i<pResRootDir->NumberOfNamedEntries+pResRootDir->NumberOfIdEntries && fRet; i++)
791 {
792 /* locate directory or each resource type */
793 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResRootDir + (int)prde->u2.OffsetToData);
794
795 if (prde->u1.s.NameIsString)
796 {//name or id entry?
797 //SvL: 30-10-'97, high bit is set, so clear to get real offset
798 nameOffset = prde->u1.Name & ~0x80000000;
799
800 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResRootDir + nameOffset);
801 fRet = lpEnumFunc(hmod, pstring->NameString, lParam);
802 }
803 else fRet = lpEnumFunc(hmod, (LPWSTR)prde->u1.Id, lParam);
804
805 /* increment to next entry */
806 prde++;
807 }
808 return fRet > 0 ? TRUE : FALSE;
809}
810//******************************************************************************
811//******************************************************************************
Note: See TracBrowser for help on using the repository browser.