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

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

(menu) resource changes

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