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

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

Fix: removed ODINCRT remains

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