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

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

* empty log message *

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