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

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

string resource loading changes

File size: 13.1 KB
Line 
1/* $Id: winimgres.cpp,v 1.26 1999-11-05 12:54:50 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, 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 id = (ULONG)lpszName;
263
264 pData = getPEResourceEntry(id, type, lang);
265 if(pData == NULL) {
266 if(HIWORD(id)) {
267 dprintf(("Win32ImageBase::getPEResource %s: couldn't find resource %s (type %d, lang %d)", szModule, id, type, lang));
268 }
269 else dprintf(("Win32ImageBase::getPEResource %s: couldn't find resource %d (type %d, lang %d)", szModule, id, type, lang));
270 return 0;
271 }
272 //pResourceSectionStart contains the virtual address of the imagebase in the PE header
273 //for the resource section (images loaded by the pe.exe)
274 //For LX images, this is 0 as OffsetToData contains a relative offset
275 char *resdata = (char *)((char *)pResDir + pData->OffsetToData - pResourceSectionStart);
276 res = new Win32Resource(this, id, type, pData->Size, resdata);
277
278 return (HRSRC) res;
279}
280//******************************************************************************
281//******************************************************************************
282HRSRC Win32ImageBase::findResourceW(LPWSTR lpszName, LPWSTR lpszType, ULONG lang)
283{
284 HRSRC hres;
285 char *astring1 = NULL, *astring2 = NULL;
286
287 if(HIWORD(lpszName) != 0) {
288 astring1 = UnicodeToAsciiString(lpszName);
289 }
290 else astring1 = (char *)lpszName;
291
292 if(HIWORD(lpszType) != 0) {
293 astring2 = UnicodeToAsciiString(lpszType);
294 }
295 else astring2 = (char *)lpszType;
296
297 hres = (HRSRC) findResourceA(astring1, astring2);
298
299 if(HIWORD(astring1)) FreeAsciiString(astring1);
300 if(HIWORD(astring2)) FreeAsciiString(astring2);
301
302 return(hres);
303}
304//******************************************************************************
305//TODO:
306//******************************************************************************
307#if 0
308ULONG Win32Pe2LxImage::getResourceSizeA(LPCSTR lpszName, LPSTR lpszType, ULONG lang)
309{
310 DebugInt3();
311 return 0;
312}
313#endif
314//******************************************************************************
315//******************************************************************************
316ULONG Win32ImageBase::getResourceSizeA(LPCSTR lpszName, LPSTR lpszType, ULONG lang)
317{
318 return getPEResourceSize((ULONG)lpszName, (ULONG)lpszType, lang);
319}
320//******************************************************************************
321//******************************************************************************
322ULONG Win32ImageBase::getResourceSizeW(LPCWSTR lpszName, LPWSTR lpszType, ULONG lang)
323{
324 char *astring1 = NULL, *astring2 = NULL;
325 ULONG ressize;
326
327 if(HIWORD(lpszName) != 0) {
328 astring1 = UnicodeToAsciiString((LPWSTR)lpszName);
329 }
330 else astring1 = (char *)lpszName;
331
332 if(HIWORD(lpszType) != 0) {
333 astring2 = UnicodeToAsciiString(lpszType);
334 }
335 else astring2 = (char *)lpszType;
336
337 ressize = getResourceSizeA(astring2, astring1, lang);
338
339 if(HIWORD(astring1)) FreeAsciiString(astring1);
340 if(HIWORD(astring2)) FreeAsciiString(astring2);
341
342 return(ressize);
343}
344//******************************************************************************
345//******************************************************************************
346#if 0
347ULONG Win32Pe2LxImage::getVersionSize()
348{
349 if(getVersionId() == -1) {
350 dprintf(("GetVersionSize: %s has no version resource!\n", szModule));
351 return(0);
352 }
353 return OSLibGetResourceSize(hinstance, getVersionId());
354}
355//******************************************************************************
356//******************************************************************************
357BOOL Win32Pe2LxImage::getVersionStruct(char *verstruct, ULONG bufLength)
358{
359 if(getVersionId() == -1) {
360 dprintf(("GetVersionStruct: %s has no version resource!\n", szModule));
361 return(FALSE);
362 }
363 return OSLibGetResource(hinstance, getVersionId(), verstruct, bufLength);
364}
365#endif
366//******************************************************************************
367//******************************************************************************
368ULONG Win32ImageBase::getVersionSize()
369{
370 return getResourceSizeA((LPCSTR)1, (LPSTR)NTRT_VERSION);
371}
372//******************************************************************************
373//******************************************************************************
374BOOL Win32ImageBase::getVersionStruct(char *verstruct, ULONG bufLength)
375{
376 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
377
378 if(verstruct == NULL || bufLength == 0) {
379 SetLastError(ERROR_INVALID_PARAMETER);
380 return FALSE;
381 }
382 pData = getPEResourceEntry(ID_GETFIRST, NTRT_VERSION);
383 if(pData == NULL) {
384 dprintf(("Win32PeLdrImage::getVersionStruct: couldn't find version resource!"));
385 return 0;
386 }
387 char *resdata = (char *)((char *)pResDir + pData->OffsetToData - pResourceSectionStart);
388 memcpy(verstruct, resdata, min(bufLength, pData->Size));
389 return TRUE;
390}
391//******************************************************************************
392//******************************************************************************
Note: See TracBrowser for help on using the repository browser.