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

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

Resource support for DIB type (DISABLED)

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