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

Last change on this file since 1131 was 1131, checked in by sandervl, 26 years ago

version fixes, resource lookup change + lstrcmpniW added

File size: 15.8 KB
Line 
1/* $Id: winimgres.cpp,v 1.19 1999-10-04 20:52:34 sandervl Exp $ */
2
3/*
4 * Win32 PE Image class (resource methods)
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 * TODO: Check created resource objects before loading the resource!
12 * TODO: Once the resource handling in PE2LX/win32k is changed,
13 * getVersionStruct/Size can be moved into the Win32ImageBase class
14 *
15 */
16#include <os2win.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include <misc.h>
22#include <winimagebase.h>
23#include <winimagepe2lx.h>
24#include <winimagepeldr.h>
25#include <winimagelx.h>
26#include <winres.h>
27#include <winresmenu.h>
28#include <unicode.h>
29#include <heapstring.h>
30#include "pefile.h"
31#include "oslibmisc.h"
32
33//******************************************************************************
34//Assuming names are case insensitive
35//PE spec says names & ids are sorted; keep on searching just to be sure
36//******************************************************************************
37PIMAGE_RESOURCE_DATA_ENTRY
38 Win32ImageBase::getPEResourceEntry(ULONG id, ULONG type, ULONG lang)
39{
40 PIMAGE_RESOURCE_DIRECTORY prdType;
41 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
42 PIMAGE_RESOURCE_DIR_STRING_U pstring;
43 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
44 ULONG nodeData[3], i, j, nameOffset;
45 BOOL fFound = FALSE, fNumType;
46
47 /* set pointer to first resource type entry */
48 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
49
50 /* loop through all resource directory entry types */
51 //1st level -> types
52 //2nd level -> names
53 //3rd level -> language
54 nodeData[0] = id;
55 nodeData[1] = lang;
56 nodeData[2] = 0xFFFFFFFF;
57
58 fNumType = TRUE; //assume numeric
59 if(HIWORD(type) != 0) {//string id?
60 for(i=0;i<MAX_RES;i++) {
61 if(stricmp((char *)type, ResTypes[i]) == 0)
62 break;
63 }
64 if(i == MAX_RES) {//custom resource type
65 fNumType = FALSE;
66 }
67 else type = i;
68 }
69
70 for (i=0; i<pResDir->NumberOfNamedEntries+pResDir->NumberOfIdEntries; i++) {
71 /* locate directory or each resource type */
72 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)pResDir + (int)prde->u2.OffsetToData);
73
74 if(i < pResDir->NumberOfNamedEntries)
75 {//name or id entry?
76 //SvL: 30-10-'97, high bit is set, so clear to get real offset
77 nameOffset = prde->u1.Name & ~0x80000000;
78
79 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + nameOffset);
80 char *typename = (char *)malloc(pstring->Length+1);
81 lstrcpynWtoA(typename, pstring->NameString, pstring->Length+1);
82 typename[pstring->Length] = 0;
83
84 if(!fNumType) {
85 if(stricmp(typename, (char *)type) == 0) {
86 fFound = TRUE;
87 }
88 }
89 else {
90 for(j=0;j<MAX_RES;j++) {
91 if(stricmp(typename, ResTypes[j]) == 0)
92 break;
93 }
94 if(j == type) {
95 fFound = TRUE;
96 }
97 }
98 free(typename);
99 }
100 else {
101 if(prde->u1.Id == type) {
102 fFound = TRUE;
103 }
104 }
105 if(fFound) {
106 if((ULONG)prdType & 0x80000000) {//subdirectory?
107 pData = ProcessResSubDir(prdType, &nodeData[0], 2);
108 }
109 else {
110 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType;
111 dprintf(("getResource: not a subdir!!\n"));
112 }
113 break;
114 }
115 /* increment to next entry */
116 prde++;
117 }
118 return pData;
119}
120//******************************************************************************
121//level: 2 ids
122// 3 languages
123//******************************************************************************
124PIMAGE_RESOURCE_DATA_ENTRY
125 Win32ImageBase::ProcessResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType,
126 ULONG *nodeData, int level)
127{
128 PIMAGE_RESOURCE_DIRECTORY prdType2;
129 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
130 PIMAGE_RESOURCE_DIR_STRING_U pstring;
131 PIMAGE_RESOURCE_DATA_ENTRY pData;
132 BOOL fFound = FALSE, fNumId;
133 ULONG nrres, nameOffset;
134 char *resname;
135 int i;
136
137 if(*nodeData == 0xFFFFFFFF) {//shouldn't happen!
138 dprintf(("ProcessResSubDir: *nodeData == 0xFFFFFFFF!\n"));
139 return(NULL);
140 }
141 prdType = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)prdType & ~0x80000000);
142 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdType + sizeof(IMAGE_RESOURCE_DIRECTORY));
143
144 //level 2 (id) -> get first id?
145 //level 3 (lang) -> get first language?
146 if(*nodeData == IDLANG_GETFIRST) {
147 nrres = prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries;
148 fNumId = (prdType->NumberOfNamedEntries == 0);
149 }
150 else {
151 fNumId = HIWORD(*nodeData) == 0;
152
153 if(fNumId) {//numeric or string id?
154 nrres = prdType->NumberOfIdEntries;
155 prde += prdType->NumberOfNamedEntries; //skip name entries
156 }
157 else nrres = prdType->NumberOfNamedEntries;
158 }
159
160 for(i=0;i<nrres;i++) {
161 /* locate directory or each resource type */
162 prdType2 = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)pResDir + (ULONG)prde->u2.OffsetToData);
163
164 if(*nodeData == IDLANG_GETFIRST) {
165 fFound = TRUE; //always take the first one
166 }
167 else
168 if(!fNumId) {//name or id entry?
169 nameOffset = prde->u1.Name;
170 if(prde->u1.s.NameIsString) //unicode directory string /*PLF Sat 97-06-21 22:30:35*/
171 nameOffset &= ~0x80000000;
172
173 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + nameOffset);
174
175 resname = (char *)malloc(pstring->Length+1);
176 lstrcpynWtoA(resname, pstring->NameString, pstring->Length+1);
177 resname[pstring->Length] = 0;
178 if(stricmp(resname, (char *)*nodeData) == 0) {
179 fFound = TRUE;
180 }
181 free(resname);
182 }
183 else {
184 if(*nodeData == prde->u1.Id)
185 fFound = TRUE;
186 }
187
188 if(fFound) {
189 if((ULONG)prdType2 & 0x80000000) {//subdirectory?
190 return ProcessResSubDir(prdType2, nodeData+1, 3);
191 }
192 else {
193 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType2;
194 if(pData->Size) {//winamp17 winzip archive has resource with size 0
195 return(pData);
196 }
197 else return(NULL);
198 }
199 }
200 prde++;
201 }
202 return(NULL);
203}
204//******************************************************************************
205//******************************************************************************
206ULONG Win32ImageBase::getPEResourceSize(ULONG id, ULONG type, ULONG lang)
207{
208 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
209
210 pData = getPEResourceEntry(id, type, lang);
211 if(pData == NULL) {
212 dprintf(("Win32ImageBase::getPEResourceSize: couldn't find resource %d (type %d, lang %d)", id, type, lang));
213 return 0;
214 }
215 return pData->Size;
216}
217//******************************************************************************
218//******************************************************************************
219HRSRC Win32ImageBase::findResourceA(LPCSTR lpszName, LPSTR lpszType, ULONG lang)
220{
221 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
222 Win32Resource *res;
223 BOOL fNumType;
224 char *winres = NULL;
225 ULONG id, type;
226 int i, stringid = -1, j;
227
228 fNumType = TRUE; //assume numeric
229 if(HIWORD(lpszType) != 0) {//string id?
230 for(i=0;i<MAX_RES;i++) {
231 if(stricmp(lpszType, ResTypes[i]) == 0)
232 break;
233 }
234 if(i == MAX_RES) {//custom resource type
235 fNumType = FALSE;
236 type = (ULONG)lpszType;
237 }
238 else type = i;
239 }
240 else type = (ULONG)lpszType;
241
242 //String format: tables of 16 strings stored as one resource
243 //upper 12 bits of resource id passed by user determines block (res id)
244 //lower 4 bits are an index into the string table
245 if(fNumType) {
246 if(type == NTRT_STRING) {
247 stringid = (ULONG)lpszName & 0xF;
248 id = (((ULONG)lpszName) >> 4)+1;
249 }
250 else id = (ULONG)lpszName;
251 }
252 else {
253 if(stricmp((char *)type, ResTypes[NTRT_STRING]) == 0) {
254 stringid = (ULONG)lpszName & 0xF;
255 id = (((ULONG)lpszName) >> 4)+1;
256 }
257 else id = (ULONG)lpszName;
258 }
259
260 pData = getPEResourceEntry(id, type, lang);
261 if(pData == NULL) {
262 if(HIWORD(id)) {
263 dprintf(("Win32ImageBase::getPEResource: couldn't find resource %s (type %d, lang %d)", id, type, lang));
264 }
265 else dprintf(("Win32ImageBase::getPEResource: couldn't find resource %d (type %d, lang %d)", id, type, lang));
266 return 0;
267 }
268 //pResourceSectionStart contains the virtual address of the imagebase in the PE header
269 //for the resource section (images loaded by the pe.exe)
270 //For LX images, this is 0 as OffsetToData contains a relative offset
271 char *resdata = (char *)((char *)pResDir + pData->OffsetToData - pResourceSectionStart);
272 if(stringid != -1) {//search for string in table
273 USHORT *unicodestr = (USHORT *)resdata;
274
275 for(i=0;i<stringid;i++) {
276 unicodestr += *unicodestr+1;
277 }
278 res = new Win32Resource(this, id, NTRT_STRING, (*unicodestr+1)*sizeof(WCHAR),
279 (char *)(unicodestr+1));
280 if(res == NULL) {
281 dprintf(("new Win32Resource failed!\n"));
282 return(NULL);
283 }
284 }
285 else {
286 switch(type) {
287 case NTRT_MENU:
288 res = new Win32MenuRes(this, id, type, pData->Size, resdata);
289 break;
290 default:
291 res = new Win32Resource(this, id, type, pData->Size, resdata);
292 break;
293 }
294
295 }
296
297 return (HRSRC) res;
298}
299//******************************************************************************
300//******************************************************************************
301HRSRC Win32Pe2LxImage::findResourceA(LPCSTR lpszName, LPSTR lpszType, ULONG lang)
302{
303 Win32Resource *res = NULL;
304 HRSRC hres;
305 int i;
306 LPSTR szType = (LPSTR)lpszType;
307
308 if(HIWORD(lpszType) != 0) {//type name, translate to id
309 for(i=0;i<MAX_RES;i++) {
310 if(strcmp(lpszType, ResTypes[i]) == 0)
311 break;
312 }
313 if(i == MAX_RES) {//custom resource type, stored as rcdata
314 dprintf(("FindResourceA custom type %s\n", lpszType));
315 lpszType = (LPSTR)NTRT_RCDATA;
316 }
317 else lpszType = (LPSTR)i;
318
319 szType = (LPSTR)lpszType;
320 }
321 switch((int)szType) {
322 case NTRT_GROUP_ICON:
323 szType = (LPSTR)NTRT_ICON;
324 break;
325 case NTRT_GROUP_CURSOR:
326 szType = (LPSTR)NTRT_CURSOR;
327 break;
328 case NTRT_VERSION:
329 szType = (LPSTR)NTRT_RCDATA;
330 break;
331 case NTRT_STRING:
332 case NTRT_MENU:
333 case NTRT_ICON:
334 case NTRT_BITMAP:
335 case NTRT_CURSOR:
336 case NTRT_DIALOG:
337 case NTRT_RCDATA:
338 case NTRT_ACCELERATORS:
339 szType = lpszType;
340 break;
341 default: //unknown are stored as rcdata
342 szType = (LPSTR)NTRT_RCDATA;
343 break;
344 }
345 dprintf(("FindResourceA from %X type %d (%X)\n", hinstance, szType, lpszType));
346
347 if(HIWORD(lpszName) != 0) {//convert string name identifier to numeric id
348 dprintf(("FindResource %s\n", lpszName));
349 if(lpszName[0] == '#') {// #344
350 lpszName = (LPCSTR)atoi(&lpszName[1]);
351 }
352 else lpszName = (LPCSTR)convertNameId((char *)lpszName);
353 }
354 else dprintf(("FindResource %d\n", (int)lpszName));
355
356 hres = O32_FindResource(hinstance, lpszName, szType);
357 if(hres)
358 {
359 switch((ULONG)szType) {
360 case NTRT_MENU:
361 res = new Win32MenuRes(this, hres, (ULONG)lpszName, (ULONG)szType);
362 break;
363 default:
364 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
365 break;
366 }
367 }
368
369 if(hres == NULL && HIWORD(lpszName) == 0 && (int)szType == NTRT_STRING) {
370 hres = O32_FindResource(hinstance, (LPCSTR)(((int)lpszName - 1)*16), (LPCSTR)NTRT_RCDATA);
371 if(hres)
372 {
373 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
374 }
375 else dprintf(("FindResourceA can't find string %d\n", (int)lpszName));
376 }
377 dprintf(("FindResourceA returned %X (%X)\n", hres, GetLastError()));
378
379 return (HRSRC)res;
380}
381//******************************************************************************
382//******************************************************************************
383HRSRC Win32ImageBase::findResourceW(LPWSTR lpszName, LPWSTR lpszType, ULONG lang)
384{
385 HRSRC hres;
386 char *astring1 = NULL, *astring2 = NULL;
387
388 if(HIWORD(lpszName) != 0) {
389 astring1 = UnicodeToAsciiString(lpszName);
390 }
391 else astring1 = (char *)lpszName;
392
393 if(HIWORD(lpszType) != 0) {
394 astring2 = UnicodeToAsciiString(lpszType);
395 }
396 else astring2 = (char *)lpszType;
397
398 hres = (HRSRC) findResourceA(astring1, astring2);
399
400 if(HIWORD(astring1)) FreeAsciiString(astring1);
401 if(HIWORD(astring2)) FreeAsciiString(astring2);
402
403 return(hres);
404}
405//******************************************************************************
406//TODO:
407//******************************************************************************
408ULONG Win32Pe2LxImage::getResourceSizeA(LPCSTR lpszName, LPSTR lpszType, ULONG lang)
409{
410 DebugInt3();
411 return 0;
412}
413//******************************************************************************
414//******************************************************************************
415ULONG Win32ImageBase::getResourceSizeA(LPCSTR lpszName, LPSTR lpszType, ULONG lang)
416{
417 return getPEResourceSize((ULONG)lpszName, (ULONG)lpszType, lang);
418}
419//******************************************************************************
420//******************************************************************************
421ULONG Win32ImageBase::getResourceSizeW(LPCWSTR lpszName, LPWSTR lpszType, ULONG lang)
422{
423 char *astring1 = NULL, *astring2 = NULL;
424 ULONG ressize;
425
426 if(HIWORD(lpszName) != 0) {
427 astring1 = UnicodeToAsciiString((LPWSTR)lpszName);
428 }
429 else astring1 = (char *)lpszName;
430
431 if(HIWORD(lpszType) != 0) {
432 astring2 = UnicodeToAsciiString(lpszType);
433 }
434 else astring2 = (char *)lpszType;
435
436 ressize = getResourceSizeA(astring2, astring1, lang);
437
438 if(HIWORD(astring1)) FreeAsciiString(astring1);
439 if(HIWORD(astring2)) FreeAsciiString(astring2);
440
441 return(ressize);
442}
443//******************************************************************************
444//******************************************************************************
445ULONG Win32Pe2LxImage::getVersionSize()
446{
447 if(getVersionId() == -1) {
448 dprintf(("GetVersionSize: %s has no version resource!\n", szModule));
449 return(0);
450 }
451 return OSLibGetResourceSize(hinstance, getVersionId());
452}
453//******************************************************************************
454//******************************************************************************
455BOOL Win32Pe2LxImage::getVersionStruct(char *verstruct, ULONG bufLength)
456{
457 if(getVersionId() == -1) {
458 dprintf(("GetVersionStruct: %s has no version resource!\n", szModule));
459 return(FALSE);
460 }
461 return OSLibGetResource(hinstance, getVersionId(), verstruct, bufLength);
462}
463//******************************************************************************
464//******************************************************************************
465ULONG Win32ImageBase::getVersionSize()
466{
467 return getResourceSizeA((LPCSTR)1, (LPSTR)NTRT_VERSION);
468}
469//******************************************************************************
470//******************************************************************************
471BOOL Win32ImageBase::getVersionStruct(char *verstruct, ULONG bufLength)
472{
473 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
474
475 if(verstruct == NULL || bufLength == 0) {
476 SetLastError(ERROR_INVALID_PARAMETER);
477 return FALSE;
478 }
479 pData = getPEResourceEntry(ID_GETFIRST, NTRT_VERSION);
480 if(pData == NULL) {
481 dprintf(("Win32PeLdrImage::getVersionStruct: couldn't find version resource!"));
482 return 0;
483 }
484 char *resdata = (char *)((char *)pResDir + pData->OffsetToData - pResourceSectionStart);
485 memcpy(verstruct, resdata, min(bufLength, pData->Size));
486 return TRUE;
487}
488//******************************************************************************
489//******************************************************************************
Note: See TracBrowser for help on using the repository browser.