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

Last change on this file since 7029 was 6442, checked in by sandervl, 24 years ago

Temporarily disabled new name lookup (resources) until

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