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

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

TLS + resource lookup (name -1) fixes

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