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

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

Fix: ODINCRT support

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