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

Last change on this file since 22018 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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