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

Last change on this file since 10471 was 10471, checked in by sandervl, 22 years ago

DBCS fixes for console & resource functions

File size: 34.4 KB
Line 
1/* $Id: winimgres.cpp,v 1.54 2004-02-19 13:03:07 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 int len = lstrlenWtoA( pstring->NameString, pstring->Length );
605 char *typename = (char *)malloc( len + 1 );
606 lstrcpynWtoA(typename, pstring->NameString, len + 1 );
607 typename[len] = 0;
608
609 fRet = lpEnumFunc(hmod, typename, lParam);
610 free(typename);
611 }
612 else {
613 fRet = lpEnumFunc(hmod, (LPSTR)prde->u1.Id, lParam);
614 }
615
616 /* increment to next entry */
617 prde++;
618 }
619 return fRet > 0 ? TRUE : FALSE;
620}
621//******************************************************************************
622//******************************************************************************
623BOOL Win32ImageBase::enumResourceTypesW(HMODULE hmod, ENUMRESTYPEPROCW lpEnumFunc,
624 LONG lParam)
625{
626 PIMAGE_RESOURCE_DIRECTORY prdType;
627 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
628 PIMAGE_RESOURCE_DIR_STRING_U pstring;
629 ULONG i, nameOffset;
630 BOOL fRet;
631 LPWSTR lpszType;
632
633 if (pResRootDir == NULL)
634 {
635 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
636 return FALSE;
637 }
638
639 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
640 {
641 SetLastError(ERROR_NOACCESS);
642 return FALSE;
643 }
644
645 //reminder:
646 //1st level -> types
647 //2nd level -> names
648 //3rd level -> language
649
650 /* set pointer to first resource type entry */
651 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResRootDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
652
653 for (i=0; i<pResRootDir->NumberOfNamedEntries+pResRootDir->NumberOfIdEntries && fRet; i++)
654 {
655 /* locate directory or each resource type */
656 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResRootDir + (int)prde->u2.OffsetToData);
657
658 if (prde->u1.s.NameIsString)
659 {//name or id entry?
660 //SvL: 30-10-'97, high bit is set, so clear to get real offset
661 nameOffset = prde->u1.Name & ~0x80000000;
662
663 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResRootDir + nameOffset);
664
665 lpszType = (LPWSTR)malloc((pstring->Length+1) * sizeof(WCHAR));
666 memcpy(lpszType, pstring->NameString, pstring->Length * sizeof(WCHAR));
667 lpszType[pstring->Length] = 0;
668
669 fRet = lpEnumFunc(hmod, pstring->NameString, lParam);
670
671 free(lpszType);
672 }
673 else fRet = lpEnumFunc(hmod, (LPWSTR)prde->u1.Id, lParam);
674
675 /* increment to next entry */
676 prde++;
677 }
678 return fRet > 0 ? TRUE : FALSE;
679}
680/**
681 * The EnumResourceNames function searches a module for each
682 * resource of the specified type and passes the name of each
683 * resource it locates to an application-defined callback function
684 *
685 * @returns If the function succeeds, the return value is nonzero.
686 * If the function fails, the return value is zero
687 * @param hmod The specified module handle.
688 * @param lpszType pointer to resource type
689 * @param lpEnumFunc pointer to callback function
690 * @param lParam application-defined parameter
691 * @sketch IF not resources in module THEN return fail.
692 * Validate parameters.
693 * Get the subdirectory for the specified type.
694 * IF found THEN
695 * BEGIN
696 * Find the number of directory entries.
697 * Find directory entries.
698 * LOOP thru all entries while the callback function returns true
699 * BEGIN
700 * Name = pointer to ASCII name string or Id.
701 * call callback function.
702 * END
703 * END
704 * ELSE
705 * fail.
706 * return
707 * @status completely implemented and tested.
708 * @author knut st. osmundsen
709 * @remark The EnumResourceNames function continues to enumerate resource
710 * names until the callback function returns FALSE or all resource
711 * names have been enumerated
712 */
713BOOL Win32ImageBase::enumResourceNamesA(HMODULE hmod,
714 LPCTSTR lpszType,
715 ENUMRESNAMEPROCA lpEnumFunc,
716 LONG lParam)
717{
718 BOOL fRet;
719 PIMAGE_RESOURCE_DIRECTORY pResDirOurType;
720 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
721
722 if (pResRootDir == NULL)
723 {
724 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
725 return FALSE;
726 }
727
728 /* validate parameters - FIXME... Exception handler??? */
729 if ((ULONG)lpszType >= 0xc0000000) //....
730 {
731 SetLastError(ERROR_INVALID_PARAMETER);
732 return FALSE;
733 }
734
735 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
736 {
737 SetLastError(ERROR_NOACCESS);
738 return FALSE;
739 }
740
741 //reminder:
742 //1st level -> types
743 //2nd level -> names
744 //3rd level -> language
745
746 pResDirOurType = getResSubDirA(pResRootDir, lpszType);
747 if (pResDirOurType != NULL)
748 {
749 char *pszASCII = NULL;
750 unsigned cch = 0;
751 unsigned cResEntries;
752 unsigned i;
753
754 fRet = TRUE;
755 cResEntries = pResDirOurType->NumberOfNamedEntries + pResDirOurType->NumberOfIdEntries;
756 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirOurType + sizeof(*pResDirOurType));
757 for (i = 0; i < cResEntries && fRet; i++)
758 {
759 LPSTR lpszName;
760
761 if (paResDirEntries[i].u1.s.NameIsString)
762 {
763 PIMAGE_RESOURCE_DIR_STRING_U pResDirString =
764 (PIMAGE_RESOURCE_DIR_STRING_U)(paResDirEntries[i].u1.s.NameOffset + (ULONG)pResRootDir);
765
766 /* ASCII buffer allocation/adjustment? */
767 if (cch <= pResDirString->Length)
768 {
769 void *pszTmp;
770 cch = max(pResDirString->Length + 1, 32);
771 pszTmp = pszASCII != NULL ? realloc(pszASCII, cch) : malloc(cch);
772 if (pszTmp == NULL)
773 {
774 fRet = FALSE;
775 break;
776 }
777 pszASCII = (char*)pszTmp;
778 }
779
780 int len = lstrlenWtoA( pResDirString->NameString, pResDirString->Length );
781 lstrcpynWtoA(pszASCII, pResDirString->NameString, len + 1);
782 pszASCII[len] = 0;
783 lpszName = pszASCII;
784 }
785 else
786 lpszName = (LPSTR)paResDirEntries[i].u1.Id;
787
788 fRet = lpEnumFunc(hmod, lpszType, lpszName, lParam);
789 }
790
791 if (pszASCII != NULL)
792 free(pszASCII);
793 }
794 else
795 {
796 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
797 fRet = FALSE;
798 }
799
800 return fRet > 0 ? TRUE : FALSE;
801}
802
803
804/**
805 * The EnumResourceNames function searches a module for each
806 * resource of the specified type and passes the name of each
807 * resource it locates to an application-defined callback function
808 *
809 * @returns If the function succeeds, the return value is nonzero.
810 * If the function fails, the return value is zero
811 * @param hmod The specified module handle.
812 * @param lpszType pointer to resource type
813 * @param lpEnumFunc pointer to callback function
814 * @param lParam application-defined parameter
815 * @sketch IF not resources in module THEN return fail.
816 * Validate parameters.
817 * Get the subdirectory for the specified type.
818 * IF found THEN
819 * BEGIN
820 * Find the number of directory entries.
821 * Find directory entries.
822 * LOOP thru all entries while the callback function returns true
823 * BEGIN
824 * Name = pointer to ASCII name string or Id.
825 * call callback function.
826 * END
827 * END
828 * ELSE
829 * fail.
830 * return
831 * @status completely implemented and tested.
832 * @author knut st. osmundsen
833 * @remark The EnumResourceNames function continues to enumerate resource
834 * names until the callback function returns FALSE or all resource
835 * names have been enumerated
836 */
837BOOL Win32ImageBase::enumResourceNamesW(HMODULE hmod,
838 LPCWSTR lpszType,
839 ENUMRESNAMEPROCW lpEnumFunc,
840 LONG lParam)
841{
842 BOOL fRet;
843 PIMAGE_RESOURCE_DIRECTORY pResDirOurType;
844 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
845
846 if (pResRootDir == NULL)
847 {
848 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
849 return FALSE;
850 }
851
852 /* validate parameters - FIXME... Exception handler??? */
853 if ((ULONG)lpszType >= 0xc0000000) //....
854 {
855 SetLastError(ERROR_INVALID_PARAMETER);
856 return FALSE;
857 }
858
859 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
860 {
861 SetLastError(ERROR_NOACCESS);
862 return FALSE;
863 }
864
865
866 //reminder:
867 //1st level -> types
868 //2nd level -> names
869 //3rd level -> language
870
871 pResDirOurType = getResSubDirW(pResRootDir, lpszType);
872 if (pResDirOurType != NULL)
873 {
874 unsigned cResEntries;
875 unsigned i, length;
876
877 fRet = TRUE;
878 cResEntries = pResDirOurType->NumberOfNamedEntries + pResDirOurType->NumberOfIdEntries;
879 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirOurType + sizeof(*pResDirOurType));
880 for (i = 0; i < cResEntries && fRet; i++)
881 {
882 LPWSTR lpszName, lpszResName;
883
884 if(paResDirEntries[i].u1.s.NameIsString)
885 {
886 lpszName = (LPWSTR)(paResDirEntries[i].u1.s.NameOffset + (ULONG)pResRootDir + 2);
887 length = (int)*(LPWSTR)(paResDirEntries[i].u1.s.NameOffset + (ULONG)pResRootDir);
888
889 lpszResName = (LPWSTR)malloc((length+1) * sizeof(WCHAR));
890 memcpy(lpszResName, lpszName, length * sizeof(WCHAR));
891 lpszResName[length] = 0;
892
893 fRet = lpEnumFunc(hmod, lpszType, lpszResName, lParam);
894 free(lpszResName);
895 }
896 else {
897 lpszName = (LPWSTR)paResDirEntries[i].u1.Id;
898 fRet = lpEnumFunc(hmod, lpszType, lpszName, lParam);
899 }
900 }
901 }
902 else
903 {
904 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
905 fRet = FALSE;
906 }
907
908 return fRet > 0;
909}
910//******************************************************************************
911//******************************************************************************
912BOOL Win32ImageBase::enumResourceLanguagesA(HMODULE hmod, LPCSTR lpszType,
913 LPCSTR lpszName,
914 ENUMRESLANGPROCA lpEnumFunc,
915 LONG lParam)
916{
917 PIMAGE_RESOURCE_DIRECTORY pResDirRet;
918 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
919 BOOL fRet;
920
921 if (pResRootDir == NULL)
922 {
923 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
924 return FALSE;
925 }
926
927 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
928 {
929 SetLastError(ERROR_NOACCESS);
930 return FALSE;
931 }
932
933 pResDirRet = getResSubDirA(pResRootDir, lpszType);
934 if(!pResDirRet) {
935 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
936 return FALSE;
937 }
938 pResDirRet = getResSubDirA(pResDirRet, lpszName);
939 if(!pResDirRet) {
940 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
941 return FALSE;
942 }
943
944 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirRet + sizeof(*pResDirRet));
945 if(pResDirRet->NumberOfNamedEntries) {
946 DebugInt3();
947 }
948 paResDirEntries += pResDirRet->NumberOfNamedEntries;
949
950 for(int i = 0;i < pResDirRet->NumberOfIdEntries;i++)
951 {
952 fRet = lpEnumFunc(hmod, lpszType, lpszName, paResDirEntries[i].u1.Id, lParam);
953 if(!fRet)
954 break;
955 }
956 return fRet;
957}
958//******************************************************************************
959//******************************************************************************
960BOOL Win32ImageBase::enumResourceLanguagesW(HMODULE hmod, LPCWSTR lpszType,
961 LPCWSTR lpszName,
962 ENUMRESLANGPROCW lpEnumFunc,
963 LONG lParam)
964{
965 PIMAGE_RESOURCE_DIRECTORY pResDirRet;
966 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
967 BOOL fRet;
968
969 if (pResRootDir == NULL)
970 {
971 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
972 return FALSE;
973 }
974
975 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
976 {
977 SetLastError(ERROR_NOACCESS);
978 return FALSE;
979 }
980
981 pResDirRet = getResSubDirW(pResRootDir, lpszType);
982 if(!pResDirRet) {
983 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
984 return FALSE;
985 }
986 pResDirRet = getResSubDirW(pResDirRet, lpszName);
987 if(!pResDirRet) {
988 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
989 return FALSE;
990 }
991
992 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirRet + sizeof(*pResDirRet));
993 if(pResDirRet->NumberOfNamedEntries) {
994 DebugInt3();
995 }
996 paResDirEntries += pResDirRet->NumberOfNamedEntries;
997
998 for(int i = 0;i < pResDirRet->NumberOfIdEntries;i++)
999 {
1000 fRet = lpEnumFunc(hmod, lpszType, lpszName, paResDirEntries[i].u1.Id, lParam);
1001 if(!fRet)
1002 break;
1003 }
1004 return fRet;
1005}
1006//******************************************************************************
1007//******************************************************************************
Note: See TracBrowser for help on using the repository browser.