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

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

Fix: Someone with strong stomach should take care of the resource loader code

File size: 13.1 KB
Line 
1/* $Id: winimgres.cpp,v 1.4 1999-06-23 19:36:24 phaller Exp $ */
2
3/*
4 *
5 * Project Odin Software License can be found in LICENSE.TXT
6 *
7 */
8/*
9 * Win32 PE Image class (resource methods)
10 *
11 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
12 *
13 */
14#include <os2win.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include "misc.h"
19#include "nameid.h"
20#include "winimage.h"
21#include "windll.h"
22#include "winexe.h"
23#include "winres.h"
24#include "pefile.h"
25#include "unicode.h"
26
27char *ResTypes[MAX_RES] =
28 {"niks", "CURSOR", "BITMAP", "ICON", "MENU", "DIALOG", "STRING",
29 "FONTDIR", "FONT", "ACCELERATOR", "RCDATA", "MESSAGETABLE",
30 "GROUP_CURSOR", "niks", "GROUP_ICON", "niks", "VERSION"};
31
32
33//******************************************************************************
34//TODO: use OS/2 unicode stuff
35//******************************************************************************
36char *extremelyuglyUnicodeToAscii(int length, WCHAR *NameString)
37{
38static char asciistring[256];
39int i;
40
41 if(length >= 255) length = 255;
42 for(i=0;i<length;i++) {
43 asciistring[i] = NameString[i] & 0xFF;
44 }
45 asciistring[length] = 0;
46 return(asciistring);
47}
48//******************************************************************************
49//******************************************************************************
50
51//******************************************************************************
52//Assuming names are case insensitive
53//PE spec says names & ids are sorted; keep on searching just to be sure
54//******************************************************************************
55Win32Resource *Win32Image::getPEResource(ULONG id, ULONG type, ULONG lang)
56{
57 PIMAGE_RESOURCE_DIRECTORY prdType;
58 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
59 PIMAGE_RESOURCE_DATA_ENTRY pData = NULL;
60 Win32Resource *res;
61 ULONG nodeData[3];
62 ULONG nrres;
63 BOOL fFound = FALSE, fNumId;
64 char *winres = NULL;
65 int i, stringid = -1, j;
66
67 /* set pointer to first resource type entry */
68 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)pResDir + sizeof(IMAGE_RESOURCE_DIRECTORY));
69
70 /* loop through all resource directory entry types */
71 //1st level -> types
72 //2nd level -> names
73 //3rd level -> language
74 nodeData[0] = id;
75 nodeData[1] = lang;
76 nodeData[2] = 0xFFFFFFFF;
77
78 nrres = pResDir->NumberOfIdEntries + pResDir->NumberOfNamedEntries;
79 fNumId = TRUE; //assume numeric
80 if(((ULONG)type >> 16) != 0) {//string id?
81 for(i=0;i<MAX_RES;i++) {
82 if(stricmp((char *)type, ResTypes[i]) == 0)
83 break;
84 }
85 if(i == MAX_RES) {//custom resource type
86 nrres = pResDir->NumberOfNamedEntries;
87 fNumId = FALSE;
88 }
89 else type = i;
90 }
91
92 //String format: tables of 16 strings stored as one resource
93 //upper 12 bits of resource id passed by user determines block (res id)
94 //lower 4 bits are an index into the string table
95 if(fNumId) {
96 if(type == NTRT_STRING) {
97 stringid = id & 0xF;
98 id = (id >> 4);
99 }
100 }
101 else {
102 if(stricmp((char *)type, ResTypes[NTRT_STRING]) == 0) {
103 stringid = id & 0xF;
104 id = (id >> 4);
105 }
106 }
107
108 for(i=0;i<nrres;i++) {
109 /* locate directory or each resource type */
110 prdType = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)pResDir + (ULONG)prde->u2.OffsetToData);
111
112 if(i < prdType->NumberOfNamedEntries) {//name or id entry?
113 //SvL: 30-10-'97, high bit is set, so clear to get real offset
114 prde->u1.Name &= ~0x80000000;
115 char *resname = extremelyuglyUnicodeToAscii(*(WCHAR *)((ULONG)pResDir + (ULONG)prde->u1.Name), (WCHAR *)((ULONG)pResDir + (ULONG)prde->u1.Name + sizeof(WCHAR))); // first word = string length
116 if(!fNumId) {
117 if(stricmp(resname, (char *)type) == 0) {
118 fFound = TRUE;
119 }
120 }
121 else {
122 for(j=0;j<MAX_RES;j++) {
123 if(stricmp((char *)type, ResTypes[j]) == 0)
124 break;
125 }
126 if(j == type) {
127 fFound = TRUE;
128 }
129 }
130 }
131 else {
132 if(prde->u1.Id == type) {
133 fFound = TRUE;
134 }
135 }
136 if(fFound) {
137 if((ULONG)prdType & 0x80000000) {//subdirectory?
138 pData = ProcessResSubDir(prdType, &nodeData[0]);
139 }
140 else {
141 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType;
142 dprintf(("getResource: not a subdir!!\n"));
143 }
144 break;
145 }
146 /* increment to next entry */
147 prde++;
148 }
149 if(pData == NULL) {
150 dprintf(("getResource: res not found!\n"));
151 return(NULL);
152 }
153
154 char *resdata = (char *)((char *)pResDir + pData->OffsetToData - pResSection->virtaddr);
155 if(stringid != -1) {//search for string in table
156 USHORT *unicodestr = (USHORT *)resdata;
157
158 for(i=0;i<stringid;i++) {
159 unicodestr += *unicodestr;
160 }
161 res = new Win32Resource(this, id, NTRT_STRING, (ULONG)*unicodestr, (char *)unicodestr);
162 if(res == NULL) {
163 dprintf(("new Win32Resource failed!\n"));
164 return(NULL);
165 }
166 }
167 else res = new Win32Resource(this, id, type, pData->Size, resdata);
168
169 return res;
170}
171//******************************************************************************
172//******************************************************************************
173PIMAGE_RESOURCE_DATA_ENTRY
174 Win32Image::ProcessResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType,
175 ULONG *nodeData)
176{
177 PIMAGE_RESOURCE_DIRECTORY prdType2;
178 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
179 PIMAGE_RESOURCE_DIR_STRING_U pstring;
180 PIMAGE_RESOURCE_DATA_ENTRY pData;
181 BOOL fFound = FALSE, fNumId;
182 ULONG nrres;
183 char *resname;
184 int i;
185
186 if(*nodeData == 0xFFFFFFFF) {//shouldn't happen!
187 dprintf(("ProcessResSubDir: *nodeData == 0xFFFFFFFF!\n"));
188 return(NULL);
189 }
190 prdType = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)prdType & ~0x80000000);
191 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdType + sizeof(IMAGE_RESOURCE_DIRECTORY));
192
193 fNumId = (*nodeData >> 16) == 0;
194
195 if(fNumId) {//numeric or string id?
196 nrres = pResDir->NumberOfIdEntries;
197 prde += pResDir->NumberOfNamedEntries; //skip name entries
198 }
199 else nrres = pResDir->NumberOfNamedEntries;
200
201 for(i=0;i<nrres;i++) {
202 /* locate directory or each resource type */
203 prdType2 = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)pResDir + (ULONG)prde->u2.OffsetToData);
204
205 if(!fNumId) {//name or id entry?
206 if(prde->u1.s.NameIsString) //unicode directory string /*PLF Sat 97-06-21 22:30:35*/
207 prde->u1.Name &= ~0x80000000;
208 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((ULONG)pResDir + (ULONG)prde->u1.Name);
209 resname = extremelyuglyUnicodeToAscii(pstring->Length, pstring->NameString);
210 if(stricmp(resname, (char *)*nodeData) == 0) {
211 fFound = TRUE;
212 }
213 }
214 else {
215 if(*nodeData == prde->u1.Id)
216 fFound = TRUE;
217 }
218 if(*nodeData == LANG_GETFIRST)
219 fFound = TRUE;
220
221 if(fFound) {
222 if((ULONG)prdType2 & 0x80000000) {//subdirectory?
223 ProcessResSubDir(prdType2, nodeData+1);
224 }
225 else {
226 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType2;
227 if(pData->Size) {//winamp17 winzip archive has resource with size 0
228 return(pData);
229 }
230 else return(NULL);
231 }
232 }
233 prde++;
234 }
235 return(NULL);
236}
237//******************************************************************************
238//******************************************************************************
239HRSRC Win32Image::findResourceA(LPCSTR lpszName, LPSTR lpszType)
240{
241 Win32Resource *res = NULL;
242 HRSRC hres;
243 int i;
244 LPSTR szType = (LPSTR)lpszType;
245
246 if(fNativePEImage == TRUE) {
247 return (HRSRC) getPEResource((ULONG)lpszName, (ULONG)lpszType);
248 }
249 //else converted win32 exe/dll
250
251 if((int)lpszType >> 16 != 0) {//type name, translate to id
252 for(i=0;i<MAX_RES;i++) {
253 if(strcmp(lpszType, ResTypes[i]) == 0)
254 break;
255 }
256 if(i == MAX_RES) {//custom resource type, stored as rcdata
257 dprintf(("FindResourceA custom type %s\n", lpszType));
258 lpszType = (LPSTR)NTRT_RCDATA;
259 }
260 else lpszType = (LPSTR)i;
261
262 szType = (LPSTR)lpszType;
263 }
264 switch((int)szType) {
265 case NTRT_GROUP_ICON:
266 szType = (LPSTR)NTRT_ICON;
267 break;
268 case NTRT_GROUP_CURSOR:
269 szType = (LPSTR)NTRT_CURSOR;
270 break;
271 case NTRT_VERSION:
272 szType = (LPSTR)NTRT_RCDATA;
273 break;
274 case NTRT_STRING:
275 case NTRT_MENU:
276 case NTRT_ICON:
277 case NTRT_BITMAP:
278 case NTRT_CURSOR:
279 case NTRT_DIALOG:
280 case NTRT_RCDATA:
281 case NTRT_ACCELERATORS:
282 szType = lpszType;
283 break;
284 default: //unknown are stored as rcdata
285 szType = (LPSTR)NTRT_RCDATA;
286 break;
287 }
288 dprintf(("FindResourceA from %X type %d (%X)\n", hinstance, szType, lpszType));
289
290 if((int)lpszName >> 16 != 0) {//convert string name identifier to numeric id
291 dprintf(("FindResource %s\n", lpszName));
292 if(lpszName[0] == '#') {// #344
293 lpszName = (LPCSTR)atoi(&lpszName[1]);
294 }
295 else lpszName = (LPCSTR)ConvertNameId(hinstance, (char *)lpszName);
296 }
297 else dprintf(("FindResource %d\n", (int)lpszName));
298
299 hres = O32_FindResource(hinstance, lpszName, szType);
300 if(hres) {
301 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
302 }
303
304 if(hres == NULL && (int)lpszName >> 16 == 0 && (int)szType == NTRT_STRING) {
305 hres = O32_FindResource(hinstance, (LPCSTR)(((int)lpszName - 1)*16), (LPCSTR)NTRT_RCDATA);
306 if(hres) {
307 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
308 }
309 else dprintf(("FindResourceA can't find string %d\n", (int)lpszName));
310 }
311 dprintf(("FindResourceA returned %X (%X)\n", hres, GetLastError()));
312
313 return (HRSRC)res;
314}
315//******************************************************************************
316//******************************************************************************
317HRSRC Win32Image::findResourceW(LPWSTR lpszName, LPWSTR lpszType)
318{
319 Win32Resource *res = NULL;
320 HRSRC hres;
321 LPSTR szType = (LPSTR)lpszType;
322 int i;
323 char *astring1 = NULL, *astring2 = NULL;
324
325 if(fNativePEImage == TRUE) {//load resources directly from res section
326 if((int)lpszType >> 16 != 0) {
327 char *resname = UnicodeToAsciiString(lpszType);
328 }
329 else astring1 = (char *)lpszType;
330
331 if((int)lpszName >> 16 != 0) {
332 astring2 = UnicodeToAsciiString(lpszName);
333 }
334 else astring2 = (char *)lpszName;
335
336 hres = (HRSRC) getPEResource((ULONG)astring1, (ULONG)astring1);
337 if(astring1) FreeAsciiString(astring1);
338 if(astring2) FreeAsciiString(astring2);
339
340 return(hres);
341 }
342 //else converted win32 exe/dll
343 if((int)lpszType >> 16 != 0) {//type name, translate to id
344 char *resname = UnicodeToAsciiString(lpszType);
345 for(i=0;i<MAX_RES;i++) {
346 if(strcmp(resname, ResTypes[i]) == 0)
347 break;
348 }
349 if(i == MAX_RES) {//custom resource type, stored as rcdata
350 dprintf(("FindResourceW custom type %s\n", resname));
351 i = NTRT_RCDATA;
352 }
353 FreeAsciiString(resname);
354 lpszType = (LPWSTR)i;
355
356 szType = (LPSTR)lpszType;
357 }
358 switch((int)szType) {
359 case NTRT_GROUP_ICON:
360 szType = (LPSTR)NTRT_ICON;
361 break;
362 case NTRT_GROUP_CURSOR:
363 szType = (LPSTR)NTRT_CURSOR;
364 break;
365 case NTRT_VERSION:
366 szType = (LPSTR)NTRT_RCDATA;
367 break;
368 case NTRT_STRING:
369 case NTRT_MENU:
370 case NTRT_ICON:
371 case NTRT_BITMAP:
372 case NTRT_CURSOR:
373 case NTRT_DIALOG:
374 case NTRT_RCDATA:
375 case NTRT_ACCELERATORS:
376 szType = (LPSTR)lpszType;
377 break;
378 default: //unknown are stored as rcdata
379 szType = (LPSTR)NTRT_RCDATA;
380 break;
381 }
382 dprintf(("FindResourceW type %d\n", szType));
383
384 if((int)lpszName >> 16 != 0) {//convert string name identifier to numeric id
385 astring1 = UnicodeToAsciiString(lpszName);
386 dprintf(("FindResourceW %X %s\n", hinstance, astring1));
387 if(astring1[0] == '#') {// #344
388 lpszName = (LPWSTR)atoi(&astring1[1]);
389 }
390 else lpszName = (LPWSTR)ConvertNameId(hinstance, (char *)astring1);
391 }
392 else dprintf(("FindResourceW %X %d\n", hinstance, (int)lpszName));
393
394 hres = O32_FindResource(hinstance, (LPCSTR)lpszName, (LPCSTR)szType);
395 if(hres) {
396 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
397 }
398
399 if(hres == NULL && (int)lpszName >> 16 == 0 && (int)szType == NTRT_STRING) {
400 hres = O32_FindResource(hinstance, (LPCSTR)(((ULONG)lpszName - 1)*16), (LPCSTR)NTRT_RCDATA);
401 if(hres) {
402 res = new Win32Resource(this, hres, (ULONG)lpszName, (ULONG)szType);
403 }
404 else dprintf(("FindResourceW can't find string %d\n", (int)lpszName));
405 }
406 if(astring1) FreeAsciiString(astring1);
407
408 dprintf(("FindResourceW returned %X (%X)\n", hres, GetLastError()));
409
410 return (HRSRC)res;
411}
412//******************************************************************************
413//******************************************************************************
Note: See TracBrowser for help on using the repository browser.