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

Last change on this file since 1146 was 1146, checked in by phaller, 26 years ago

Fix: problems while initializing SHELL32/NEW

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