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

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

changes for setting current dir of new process

File size: 31.0 KB
Line 
1/* $Id: winimgres.cpp,v 1.48 2000-10-06 15:16:06 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 /* lpszName */
346 if ((ULONG)lpszName != ID_GETFIRST && HIWORD(lpszName) != 0)
347 {
348 if (lpszName[0] == '#')
349 {
350 char szBuf[10];
351 lstrcpynWtoA(szBuf, (WCHAR*)(lpszName + 1), sizeof(szBuf));
352 idName = atoi(szBuf);
353 }
354 }
355 else
356 idName = (int)lpszName;
357
358 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirToSearch + sizeof(*pResDirToSearch));
359 if(idName == ID_GETFIRST) {
360 return paResDirEntries[0].u2.s.DataIsDirectory ?
361 (PIMAGE_RESOURCE_DIRECTORY) (paResDirEntries[0].u2.s.OffsetToDirectory + (ULONG)pResRootDir)
362 : NULL;
363 }
364
365 if (idName != -1)
366 { /* idName */
367 paResDirEntries += pResDirToSearch->NumberOfNamedEntries;
368
369 for (i = 0; i < pResDirToSearch->NumberOfIdEntries; i++)
370 if (paResDirEntries[i].u1.Id == (WORD)idName)
371 return paResDirEntries[i].u2.s.DataIsDirectory ?
372 (PIMAGE_RESOURCE_DIRECTORY) (paResDirEntries[i].u2.s.OffsetToDirectory + (ULONG)pResRootDir /*?*/
373 /*- ulRVAResourceSection*/)
374 : NULL;
375 }
376 else
377 { /* string name */
378 int cusName = lstrlenW(lpszName);
379
380 for (i = 0; i < pResDirToSearch->NumberOfNamedEntries; i++)
381 {
382 PIMAGE_RESOURCE_DIR_STRING_U pResDirStr =
383 (PIMAGE_RESOURCE_DIR_STRING_U)(paResDirEntries[i].u1.s.NameOffset + (ULONG)pResRootDir /*?*/);
384
385 //SvL: Must do case insensitive string compare here
386 if (pResDirStr->Length == cusName
387 && lstrncmpiW(pResDirStr->NameString, lpszName, cusName) == 0)
388 {
389 return paResDirEntries[i].u2.s.DataIsDirectory ?
390 (PIMAGE_RESOURCE_DIRECTORY) (paResDirEntries[i].u2.s.OffsetToDirectory + (ULONG)pResRootDir
391 /*- ulRVAResourceSection*/)
392 : NULL;
393 }
394 }
395 }
396
397 return NULL;
398}
399
400/**
401 * This function finds a resource (sub)directory within a given resource directory.
402 * @returns Pointer to resource directory. NULL if not found or not a directory.
403 * @param pResDirToSearch Pointer to resource directory to search. (any level)
404 * @param lpszName Resource ID string.
405 * @sketch
406 * @status completely implemented
407 * @author knut st. osmundsen
408 */
409PIMAGE_RESOURCE_DIRECTORY Win32ImageBase::getResSubDirA(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch,
410 LPCTSTR lpszName)
411{
412 PIMAGE_RESOURCE_DIRECTORY pResDirRet;
413 LPCWSTR lpszwName;
414
415 if(pResDirToSearch == NULL) {
416 return NULL;
417 }
418
419 /* lpszName */
420 if ((ULONG)lpszName != ID_GETFIRST && HIWORD(lpszName) != 0)
421 {
422 lpszwName = AsciiToUnicodeString((char*)lpszName);
423 if (lpszwName == NULL)
424 return NULL;
425 }
426 else
427 lpszwName = (LPWSTR)lpszName;
428
429 pResDirRet = getResSubDirW(pResDirToSearch, lpszwName);
430
431 if ((ULONG)lpszName != ID_GETFIRST && HIWORD(lpszwName) != 0)
432 free((void*)lpszwName);
433
434 return pResDirRet;
435}
436//******************************************************************************
437/**
438 * This function finds a resource data entry within a given resource directory.
439 * @returns Pointer to resource data entry. NULL if not found
440 * @param pResDirToSearch Pointer to resource directory to search. (lang level)
441 * @param language Resource language id
442 * @param fGetDefault TRUE -> get first available resource if not found
443 * @sketch
444 * @status completely implemented
445 * @author Sander van Leeuwen
446 */
447//******************************************************************************
448PIMAGE_RESOURCE_DATA_ENTRY
449 Win32ImageBase::getResDataLang(PIMAGE_RESOURCE_DIRECTORY pResDirToSearch,
450 ULONG language, BOOL fGetDefault)
451{
452 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
453 int i;
454
455 if(pResDirToSearch == NULL) {
456 return NULL;
457 }
458
459 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirToSearch + sizeof(*pResDirToSearch));
460
461 if(pResDirToSearch->NumberOfNamedEntries) {
462 DebugInt3();
463 }
464 paResDirEntries += pResDirToSearch->NumberOfNamedEntries;
465
466 for (i = 0; i < pResDirToSearch->NumberOfIdEntries; i++) {
467 if (paResDirEntries[i].u1.Id == language)
468 {
469 return (PIMAGE_RESOURCE_DATA_ENTRY) (paResDirEntries[i].u2.s.OffsetToDirectory + (ULONG)pResRootDir);
470 }
471 }
472
473 // if nothing found and fGetDefault is true, return first entry
474 if(fGetDefault)
475 {
476 return (PIMAGE_RESOURCE_DATA_ENTRY) (paResDirEntries[0].u2.s.OffsetToDirectory + (ULONG)pResRootDir);
477 }
478 return NULL;
479}
480//******************************************************************************
481//******************************************************************************
482BOOL Win32ImageBase::enumResourceTypesA(HMODULE hmod, ENUMRESTYPEPROCA lpEnumFunc,
483 LONG lParam)
484{
485 PIMAGE_RESOURCE_DIRECTORY prdType;
486 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
487 PIMAGE_RESOURCE_DIR_STRING_U pstring;
488 ULONG i, nameOffset;
489 BOOL fRet;
490
491 if (pResRootDir == NULL)
492 {
493 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
494 return FALSE;
495 }
496
497 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
498 {
499 SetLastError(ERROR_NOACCESS);
500 return FALSE;
501 }
502
503 //reminder:
504 //1st level -> types
505 //2nd level -> names
506 //3rd level -> language
507
508 /* set pointer to first resource type entry */
509 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResRootDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
510
511 for (i=0; i<pResRootDir->NumberOfNamedEntries+pResRootDir->NumberOfIdEntries && fRet; i++)
512 {
513 /* locate directory or each resource type */
514 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResRootDir + (int)prde->u2.OffsetToData);
515
516 if (prde->u1.s.NameIsString)
517 {//name or id entry?
518 //SvL: 30-10-'97, high bit is set, so clear to get real offset
519 nameOffset = prde->u1.Name & ~0x80000000;
520
521 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResRootDir + nameOffset);
522 char *typename = (char *)malloc(pstring->Length+1);
523 lstrcpynWtoA(typename, pstring->NameString, pstring->Length+1);
524 typename[pstring->Length] = 0;
525
526 fRet = lpEnumFunc(hmod, typename, lParam);
527 free(typename);
528 }
529 else {
530 fRet = lpEnumFunc(hmod, (LPSTR)prde->u1.Id, lParam);
531 }
532
533 /* increment to next entry */
534 prde++;
535 }
536 return fRet > 0 ? TRUE : FALSE;
537}
538//******************************************************************************
539//******************************************************************************
540BOOL Win32ImageBase::enumResourceTypesW(HMODULE hmod, ENUMRESTYPEPROCW lpEnumFunc,
541 LONG lParam)
542{
543 PIMAGE_RESOURCE_DIRECTORY prdType;
544 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
545 PIMAGE_RESOURCE_DIR_STRING_U pstring;
546 ULONG i, nameOffset;
547 BOOL fRet;
548 LPWSTR lpszType;
549
550 if (pResRootDir == NULL)
551 {
552 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
553 return FALSE;
554 }
555
556 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
557 {
558 SetLastError(ERROR_NOACCESS);
559 return FALSE;
560 }
561
562 //reminder:
563 //1st level -> types
564 //2nd level -> names
565 //3rd level -> language
566
567 /* set pointer to first resource type entry */
568 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResRootDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
569
570 for (i=0; i<pResRootDir->NumberOfNamedEntries+pResRootDir->NumberOfIdEntries && fRet; i++)
571 {
572 /* locate directory or each resource type */
573 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResRootDir + (int)prde->u2.OffsetToData);
574
575 if (prde->u1.s.NameIsString)
576 {//name or id entry?
577 //SvL: 30-10-'97, high bit is set, so clear to get real offset
578 nameOffset = prde->u1.Name & ~0x80000000;
579
580 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResRootDir + nameOffset);
581
582 lpszType = (LPWSTR)malloc((pstring->Length+1) * sizeof(WCHAR));
583 memcpy(lpszType, pstring->NameString, pstring->Length * sizeof(WCHAR));
584 lpszType[pstring->Length] = 0;
585
586 fRet = lpEnumFunc(hmod, pstring->NameString, lParam);
587
588 free(lpszType);
589 }
590 else fRet = lpEnumFunc(hmod, (LPWSTR)prde->u1.Id, lParam);
591
592 /* increment to next entry */
593 prde++;
594 }
595 return fRet > 0 ? TRUE : FALSE;
596}
597/**
598 * The EnumResourceNames function searches a module for each
599 * resource of the specified type and passes the name of each
600 * resource it locates to an application-defined callback function
601 *
602 * @returns If the function succeeds, the return value is nonzero.
603 * If the function fails, the return value is zero
604 * @param hmod The specified module handle.
605 * @param lpszType pointer to resource type
606 * @param lpEnumFunc pointer to callback function
607 * @param lParam application-defined parameter
608 * @sketch IF not resources in module THEN return fail.
609 * Validate parameters.
610 * Get the subdirectory for the specified type.
611 * IF found THEN
612 * BEGIN
613 * Find the number of directory entries.
614 * Find directory entries.
615 * LOOP thru all entries while the callback function returns true
616 * BEGIN
617 * Name = pointer to ASCII name string or Id.
618 * call callback function.
619 * END
620 * END
621 * ELSE
622 * fail.
623 * return
624 * @status completely implemented and tested.
625 * @author knut st. osmundsen
626 * @remark The EnumResourceNames function continues to enumerate resource
627 * names until the callback function returns FALSE or all resource
628 * names have been enumerated
629 */
630BOOL Win32ImageBase::enumResourceNamesA(HMODULE hmod,
631 LPCTSTR lpszType,
632 ENUMRESNAMEPROCA lpEnumFunc,
633 LONG lParam)
634{
635 BOOL fRet;
636 PIMAGE_RESOURCE_DIRECTORY pResDirOurType;
637 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
638
639 if (pResRootDir == NULL)
640 {
641 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
642 return FALSE;
643 }
644
645 /* validate parameters - FIXME... Exception handler??? */
646 if ((ULONG)lpszType >= 0xc0000000) //....
647 {
648 SetLastError(ERROR_INVALID_PARAMETER);
649 return FALSE;
650 }
651
652 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
653 {
654 SetLastError(ERROR_NOACCESS);
655 return FALSE;
656 }
657
658 //reminder:
659 //1st level -> types
660 //2nd level -> names
661 //3rd level -> language
662
663 pResDirOurType = getResSubDirA(pResRootDir, lpszType);
664 if (pResDirOurType != NULL)
665 {
666 char *pszASCII = NULL;
667 unsigned cch = 0;
668 unsigned cResEntries;
669 unsigned i;
670
671 fRet = TRUE;
672 cResEntries = pResDirOurType->NumberOfNamedEntries + pResDirOurType->NumberOfIdEntries;
673 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirOurType + sizeof(*pResDirOurType));
674 for (i = 0; i < cResEntries && fRet; i++)
675 {
676 LPSTR lpszName;
677
678 if (paResDirEntries[i].u1.s.NameIsString)
679 {
680 PIMAGE_RESOURCE_DIR_STRING_U pResDirString =
681 (PIMAGE_RESOURCE_DIR_STRING_U)(paResDirEntries[i].u1.s.NameOffset + (ULONG)pResRootDir);
682
683 /* ASCII buffer allocation/adjustment? */
684 if (cch <= pResDirString->Length)
685 {
686 void *pszTmp;
687 cch = max(pResDirString->Length + 1, 32);
688 pszTmp = pszASCII != NULL ? realloc(pszASCII, cch) : malloc(cch);
689 if (pszTmp == NULL)
690 {
691 fRet = FALSE;
692 break;
693 }
694 pszASCII = (char*)pszTmp;
695 }
696 lstrcpynWtoA(pszASCII, pResDirString->NameString, pResDirString->Length+1);
697 pszASCII[pResDirString->Length] = 0;
698 lpszName = pszASCII;
699 }
700 else
701 lpszName = (LPSTR)paResDirEntries[i].u1.Id;
702
703 fRet = lpEnumFunc(hmod, lpszType, lpszName, lParam);
704 }
705
706 if (pszASCII != NULL)
707 free(pszASCII);
708 }
709 else
710 {
711 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
712 fRet = FALSE;
713 }
714
715 return fRet > 0 ? TRUE : FALSE;
716}
717
718
719/**
720 * The EnumResourceNames function searches a module for each
721 * resource of the specified type and passes the name of each
722 * resource it locates to an application-defined callback function
723 *
724 * @returns If the function succeeds, the return value is nonzero.
725 * If the function fails, the return value is zero
726 * @param hmod The specified module handle.
727 * @param lpszType pointer to resource type
728 * @param lpEnumFunc pointer to callback function
729 * @param lParam application-defined parameter
730 * @sketch IF not resources in module THEN return fail.
731 * Validate parameters.
732 * Get the subdirectory for the specified type.
733 * IF found THEN
734 * BEGIN
735 * Find the number of directory entries.
736 * Find directory entries.
737 * LOOP thru all entries while the callback function returns true
738 * BEGIN
739 * Name = pointer to ASCII name string or Id.
740 * call callback function.
741 * END
742 * END
743 * ELSE
744 * fail.
745 * return
746 * @status completely implemented and tested.
747 * @author knut st. osmundsen
748 * @remark The EnumResourceNames function continues to enumerate resource
749 * names until the callback function returns FALSE or all resource
750 * names have been enumerated
751 */
752BOOL Win32ImageBase::enumResourceNamesW(HMODULE hmod,
753 LPCWSTR lpszType,
754 ENUMRESNAMEPROCW lpEnumFunc,
755 LONG lParam)
756{
757 BOOL fRet;
758 PIMAGE_RESOURCE_DIRECTORY pResDirOurType;
759 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
760
761 if (pResRootDir == NULL)
762 {
763 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
764 return FALSE;
765 }
766
767 /* validate parameters - FIXME... Exception handler??? */
768 if ((ULONG)lpszType >= 0xc0000000) //....
769 {
770 SetLastError(ERROR_INVALID_PARAMETER);
771 return FALSE;
772 }
773
774 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
775 {
776 SetLastError(ERROR_NOACCESS);
777 return FALSE;
778 }
779
780
781 //reminder:
782 //1st level -> types
783 //2nd level -> names
784 //3rd level -> language
785
786 pResDirOurType = getResSubDirW(pResRootDir, lpszType);
787 if (pResDirOurType != NULL)
788 {
789 unsigned cResEntries;
790 unsigned i, length;
791
792 fRet = TRUE;
793 cResEntries = pResDirOurType->NumberOfNamedEntries + pResDirOurType->NumberOfIdEntries;
794 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirOurType + sizeof(*pResDirOurType));
795 for (i = 0; i < cResEntries && fRet; i++)
796 {
797 LPWSTR lpszName, lpszResName;
798
799 if(paResDirEntries[i].u1.s.NameIsString)
800 {
801 lpszName = (LPWSTR)(paResDirEntries[i].u1.s.NameOffset + (ULONG)pResRootDir + 2);
802 length = (int)*(LPWSTR)(paResDirEntries[i].u1.s.NameOffset + (ULONG)pResRootDir);
803
804 lpszResName = (LPWSTR)malloc((length+1) * sizeof(WCHAR));
805 memcpy(lpszResName, lpszName, length * sizeof(WCHAR));
806 lpszResName[length] = 0;
807
808 fRet = lpEnumFunc(hmod, lpszType, lpszResName, lParam);
809 free(lpszResName);
810 }
811 else {
812 lpszName = (LPWSTR)paResDirEntries[i].u1.Id;
813 fRet = lpEnumFunc(hmod, lpszType, lpszName, lParam);
814 }
815 }
816 }
817 else
818 {
819 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
820 fRet = FALSE;
821 }
822
823 return fRet > 0;
824}
825//******************************************************************************
826//******************************************************************************
827BOOL Win32ImageBase::enumResourceLanguagesA(HMODULE hmod, LPCSTR lpszType,
828 LPCSTR lpszName,
829 ENUMRESLANGPROCA lpEnumFunc,
830 LONG lParam)
831{
832 PIMAGE_RESOURCE_DIRECTORY pResDirRet;
833 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
834 BOOL fRet;
835
836 if (pResRootDir == NULL)
837 {
838 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
839 return FALSE;
840 }
841
842 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
843 {
844 SetLastError(ERROR_NOACCESS);
845 return FALSE;
846 }
847
848 pResDirRet = getResSubDirA(pResRootDir, lpszType);
849 if(!pResDirRet) {
850 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
851 return FALSE;
852 }
853 pResDirRet = getResSubDirA(pResDirRet, lpszName);
854 if(!pResDirRet) {
855 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
856 return FALSE;
857 }
858
859 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirRet + sizeof(*pResDirRet));
860 if(pResDirRet->NumberOfNamedEntries) {
861 DebugInt3();
862 }
863 paResDirEntries += pResDirRet->NumberOfNamedEntries;
864
865 for(int i = 0;i < pResDirRet->NumberOfIdEntries;i++)
866 {
867 fRet = lpEnumFunc(hmod, lpszType, lpszName, paResDirEntries[i].u1.Id, lParam);
868 if(!fRet)
869 break;
870 }
871 return fRet;
872}
873//******************************************************************************
874//******************************************************************************
875BOOL Win32ImageBase::enumResourceLanguagesW(HMODULE hmod, LPCWSTR lpszType,
876 LPCWSTR lpszName,
877 ENUMRESLANGPROCW lpEnumFunc,
878 LONG lParam)
879{
880 PIMAGE_RESOURCE_DIRECTORY pResDirRet;
881 PIMAGE_RESOURCE_DIRECTORY_ENTRY paResDirEntries;
882 BOOL fRet;
883
884 if (pResRootDir == NULL)
885 {
886 SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
887 return FALSE;
888 }
889
890 if ((ULONG)lpEnumFunc < 0x10000 || (ULONG)lpEnumFunc >= 0xc0000000)
891 {
892 SetLastError(ERROR_NOACCESS);
893 return FALSE;
894 }
895
896 pResDirRet = getResSubDirW(pResRootDir, lpszType);
897 if(!pResDirRet) {
898 SetLastError(ERROR_RESOURCE_TYPE_NOT_FOUND);
899 return FALSE;
900 }
901 pResDirRet = getResSubDirW(pResDirRet, lpszName);
902 if(!pResDirRet) {
903 SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
904 return FALSE;
905 }
906
907 paResDirEntries = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDirRet + sizeof(*pResDirRet));
908 if(pResDirRet->NumberOfNamedEntries) {
909 DebugInt3();
910 }
911 paResDirEntries += pResDirRet->NumberOfNamedEntries;
912
913 for(int i = 0;i < pResDirRet->NumberOfIdEntries;i++)
914 {
915 fRet = lpEnumFunc(hmod, lpszType, lpszName, paResDirEntries[i].u1.Id, lParam);
916 if(!fRet)
917 break;
918 }
919 return fRet;
920}
921//******************************************************************************
922//******************************************************************************
Note: See TracBrowser for help on using the repository browser.