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

Last change on this file since 5706 was 5474, checked in by sandervl, 24 years ago

free bugfix

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