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

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

PE Resource changes

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