Release 941017
[wine/gsoc-2012-control.git] / loader / ne_resource.c
blob25e0b4cd98bbb5e144707c264af67a45514aa6b7
1 static char RCSId[] = "$Id: ne_resource.c,v 1.4 1993/07/04 04:04:21 root Exp root $";
2 static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include "windows.h"
12 #include "neexe.h"
13 #include "peexe.h"
14 #include "arch.h"
15 #include "dlls.h"
16 #include "resource.h"
18 /* #define DEBUG_RESOURCE */
20 static int ResourceFd = -1;
21 static HANDLE ResourceInst = 0;
22 static struct w_files *ResourceFileInfo;
24 /**********************************************************************
25 * RSC_LoadNameTable
27 void RSC_LoadNameTable(void)
29 struct resource_typeinfo_s typeinfo;
30 struct resource_nameinfo_s nameinfo;
31 unsigned short size_shift;
32 RESNAMTAB *top, *new;
33 char read_buf[1024];
34 char *p;
35 int i;
36 unsigned short len;
37 off_t rtoff;
38 off_t saved_pos;
40 top = NULL;
43 * Move to beginning of resource table.
45 rtoff = (ResourceFileInfo->mz_header->ne_offset +
46 ResourceFileInfo->ne->ne_header->resource_tab_offset);
47 lseek(ResourceFd, rtoff, SEEK_SET);
50 * Read block size.
52 if (read(ResourceFd, &size_shift, sizeof(size_shift)) !=
53 sizeof(size_shift))
55 return;
57 size_shift = CONV_SHORT(size_shift);
60 * Find resource.
62 typeinfo.type_id = 0xffff;
63 while (typeinfo.type_id != 0)
65 if (!load_typeinfo (ResourceFd, &typeinfo))
66 break;
68 if (typeinfo.type_id == 0)
69 break;
70 if (typeinfo.type_id == 0x800f)
72 for (i = 0; i < typeinfo.count; i++)
74 if (read(ResourceFd, &nameinfo, sizeof(nameinfo)) !=
75 sizeof(nameinfo))
77 break;
80 saved_pos = lseek(ResourceFd, 0, SEEK_CUR);
81 lseek(ResourceFd, (long) nameinfo.offset << size_shift,
82 SEEK_SET);
83 read(ResourceFd, &len, sizeof(len));
84 while (len)
86 new = (RESNAMTAB *) GlobalQuickAlloc(sizeof(*new));
87 new->next = top;
88 top = new;
90 read(ResourceFd, &new->type_ord, 2);
91 read(ResourceFd, &new->id_ord, 2);
92 read(ResourceFd, read_buf, len - 6);
94 p = read_buf + strlen(read_buf) + 1;
95 strncpy(new->id, p, MAX_NAME_LENGTH);
96 new->id[MAX_NAME_LENGTH - 1] = '\0';
98 read(ResourceFd, &len, sizeof(len));
101 lseek(ResourceFd, saved_pos, SEEK_SET);
103 break;
105 else
107 lseek(ResourceFd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
110 ResourceFileInfo->ne->resnamtab = top;
113 /**********************************************************************
114 * OpenResourceFile
117 OpenResourceFile(HANDLE instance)
119 struct w_files *w;
120 char *res_file;
122 if (ResourceInst == instance)
123 return ResourceFd;
125 w = GetFileInfo(instance);
126 if (w == NULL)
127 return -1;
128 ResourceFileInfo = w;
129 res_file = w->filename;
131 if (ResourceFd >= 0)
132 close(ResourceFd);
134 ResourceInst = instance;
135 ResourceFd = open (res_file, O_RDONLY);
136 #if 1
137 #ifndef WINELIB
138 if (w->ne->resnamtab == (RESNAMTAB *) -1)
140 RSC_LoadNameTable();
142 #endif
143 #endif
145 #ifdef DEBUG_RESOURCE
146 printf("OpenResourceFile(%04X) // file='%s' hFile=%04X !\n",
147 instance, w->filename, ResourceFd);
148 #endif
149 return ResourceFd;
152 int load_typeinfo (int fd, struct resource_typeinfo_s *typeinfo)
154 return read (fd, typeinfo, sizeof (*typeinfo)) == sizeof (*typeinfo);
157 int type_match(int type_id1, int type_id2, int fd, off_t off)
159 off_t old_pos;
160 unsigned char c;
161 size_t nbytes;
162 char name[256];
164 if (type_id1 == -1)
165 return 1;
166 if ((type_id1 & 0xffff0000) == 0) {
167 if ((type_id2 & 0x8000) == 0)
168 return 0;
169 return (type_id1 & 0x000f) == (type_id2 & 0x000f);
171 if ((type_id2 & 0x8000) != 0)
172 return 0;
173 #ifdef DEBUG_RESOURCE
174 printf("type_compare: type_id2=%04X !\n", type_id2);
175 #endif
176 old_pos = lseek(fd, 0, SEEK_CUR);
177 lseek(fd, off + type_id2, SEEK_SET);
178 read(fd, &c, 1);
179 nbytes = CONV_CHAR_TO_LONG (c);
180 #ifdef DEBUG_RESOURCE
181 printf("type_compare: namesize=%d\n", nbytes);
182 #endif
183 read(fd, name, nbytes);
184 lseek(fd, old_pos, SEEK_SET);
185 name[nbytes] = '\0';
186 #ifdef DEBUG_RESOURCE
187 printf("type_compare: name=`%s'\n", name);
188 #endif
189 return strcasecmp((char *) type_id1, name) == 0;
192 /**********************************************************************
193 * FindResourceByNumber
196 FindResourceByNumber(struct resource_nameinfo_s *result_p,
197 int type_id, int resource_id)
199 struct resource_typeinfo_s typeinfo;
200 struct resource_nameinfo_s nameinfo;
201 unsigned short size_shift;
202 int i;
203 off_t rtoff;
206 * Move to beginning of resource table.
208 rtoff = (ResourceFileInfo->mz_header->ne_offset +
209 ResourceFileInfo->ne->ne_header->resource_tab_offset);
210 lseek(ResourceFd, rtoff, SEEK_SET);
213 * Read block size.
215 if (read(ResourceFd, &size_shift, sizeof(size_shift)) !=
216 sizeof(size_shift))
218 printf("FindResourceByNumber (%d) bad block size !\n",(int) resource_id);
219 return -1;
221 size_shift = CONV_SHORT(size_shift);
223 * Find resource.
225 for (;;) {
226 if (!load_typeinfo (ResourceFd, &typeinfo)){
227 printf("FindResourceByNumber (%X) bad typeinfo size !\n", resource_id);
228 return -1;
230 #ifdef DEBUG_RESOURCE
231 printf("FindResourceByNumber type=%X count=%d ?=%d searched=%08X\n",
232 typeinfo.type_id, typeinfo.count, typeinfo.reserved, type_id);
233 #endif
234 if (typeinfo.type_id == 0) break;
235 if (type_match(type_id, typeinfo.type_id, ResourceFd, rtoff)) {
237 for (i = 0; i < typeinfo.count; i++) {
238 #ifndef WINELIB
239 if (read(ResourceFd, &nameinfo, sizeof(nameinfo)) !=
240 sizeof(nameinfo))
241 #else
242 if (!load_nameinfo (ResourceFd, &nameinfo))
243 #endif
245 printf("FindResourceByNumber (%X) bad nameinfo size !\n", resource_id);
246 return -1;
248 #ifdef DEBUG_RESOURCE
249 printf("FindResource: search type=%X id=%X // type=%X id=%X\n",
250 type_id, resource_id, typeinfo.type_id, nameinfo.id);
251 #endif
252 if (nameinfo.id == resource_id) {
253 memcpy(result_p, &nameinfo, sizeof(nameinfo));
254 return size_shift;
258 else {
259 lseek(ResourceFd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
262 return -1;
265 /**********************************************************************
266 * FindResourceByName
269 FindResourceByName(struct resource_nameinfo_s *result_p,
270 int type_id, char *resource_name)
272 struct resource_typeinfo_s typeinfo;
273 struct resource_nameinfo_s nameinfo;
274 unsigned short size_shift;
275 off_t old_pos, new_pos;
276 unsigned char nbytes;
277 char name[256];
278 int i;
279 off_t rtoff;
282 * Check for loaded name table.
284 if (ResourceFileInfo->ne->resnamtab != NULL)
286 RESNAMTAB *e;
288 for (e = ResourceFileInfo->ne->resnamtab; e != NULL; e = e->next)
290 if (e->type_ord == (type_id & 0x000f) &&
291 strcasecmp(e->id, resource_name) == 0)
293 return FindResourceByNumber(result_p, type_id, e->id_ord);
297 return -1;
301 * Move to beginning of resource table.
303 rtoff = (ResourceFileInfo->mz_header->ne_offset +
304 ResourceFileInfo->ne->ne_header->resource_tab_offset);
305 lseek(ResourceFd, rtoff, SEEK_SET);
308 * Read block size.
310 if (read(ResourceFd, &size_shift, sizeof(size_shift)) !=
311 sizeof(size_shift))
313 printf("FindResourceByName (%s) bad block size !\n", resource_name);
314 return -1;
316 size_shift = CONV_SHORT (size_shift);
319 * Find resource.
321 for (;;)
323 if (!load_typeinfo (ResourceFd, &typeinfo))
325 printf("FindResourceByName (%s) bad typeinfo size !\n", resource_name);
326 return -1;
328 #ifdef DEBUG_RESOURCE
329 printf("FindResourceByName typeinfo.type_id=%X count=%d type_id=%X\n",
330 typeinfo.type_id, typeinfo.count, type_id);
331 #endif
332 if (typeinfo.type_id == 0) break;
333 if (type_match(type_id, typeinfo.type_id, ResourceFd, rtoff))
335 for (i = 0; i < typeinfo.count; i++)
337 #ifndef WINELIB
338 if (read(ResourceFd, &nameinfo, sizeof(nameinfo)) !=
339 sizeof(nameinfo))
340 #else
341 if (!load_nameinfo (ResourceFd, &nameinfo))
342 #endif
344 printf("FindResourceByName (%s) bad nameinfo size !\n", resource_name);
345 return -1;
348 if ((nameinfo.id & 0x8000) != 0) continue;
350 #ifdef DEBUG_RESOURCE
351 printf("FindResourceByName // nameinfo.id=%04X !\n", nameinfo.id);
352 #endif
353 old_pos = lseek(ResourceFd, 0, SEEK_CUR);
354 new_pos = rtoff + nameinfo.id;
355 lseek(ResourceFd, new_pos, SEEK_SET);
356 read(ResourceFd, &nbytes, 1);
357 #ifdef DEBUG_RESOURCE
358 printf("FindResourceByName // namesize=%d !\n", nbytes);
359 #endif
360 nbytes = CONV_CHAR_TO_LONG (nbytes);
361 read(ResourceFd, name, nbytes);
362 lseek(ResourceFd, old_pos, SEEK_SET);
363 name[nbytes] = '\0';
364 #ifdef DEBUG_RESOURCE
365 printf("FindResourceByName type_id=%X (%d of %d) name='%s' resource_name='%s'\n",
366 typeinfo.type_id, i + 1, typeinfo.count,
367 name, resource_name);
368 #endif
369 if (strcasecmp(name, resource_name) == 0)
371 memcpy(result_p, &nameinfo, sizeof(nameinfo));
372 return size_shift;
376 else {
377 lseek(ResourceFd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
380 return -1;
384 /**********************************************************************
385 * GetRsrcCount [internal]
387 int GetRsrcCount(HINSTANCE hInst, int type_id)
389 struct resource_typeinfo_s typeinfo;
390 struct resource_nameinfo_s nameinfo;
391 unsigned short size_shift;
392 off_t rtoff;
394 if (hInst == 0) return 0;
395 #ifdef DEBUG_RESOURCE
396 printf("GetRsrcCount hInst=%04X typename=%08X\n", hInst, type_id);
397 #endif
398 if (OpenResourceFile(hInst) < 0) return 0;
401 * Move to beginning of resource table.
403 rtoff = (ResourceFileInfo->mz_header->ne_offset +
404 ResourceFileInfo->ne->ne_header->resource_tab_offset);
405 lseek(ResourceFd, rtoff, SEEK_SET);
407 * Read block size.
409 if (read(ResourceFd, &size_shift, sizeof(size_shift)) != sizeof(size_shift)) {
410 printf("GetRsrcCount // bad block size !\n");
411 return -1;
413 size_shift = CONV_SHORT (size_shift);
414 for (;;) {
415 if (!load_typeinfo (ResourceFd, &typeinfo)) {
416 printf("GetRsrcCount // bad typeinfo size !\n");
417 return 0;
419 #ifdef DEBUG_RESOURCE
420 printf("GetRsrcCount // typeinfo.type_id=%X count=%d type_id=%X\n",
421 typeinfo.type_id, typeinfo.count, type_id);
422 #endif
423 if (typeinfo.type_id == 0) break;
424 if (type_match(type_id, typeinfo.type_id, ResourceFd, rtoff)) {
425 return typeinfo.count;
427 else {
428 lseek(ResourceFd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
431 return 0;
434 /**********************************************************************
435 * NE_FindResource [KERNEL.60]
438 NE_FindResource(HANDLE instance, LPSTR resource_name, LPSTR type_name,
439 RESOURCE *r)
441 int type;
443 #ifdef DEBUG_RESOURCE
444 printf("NE_FindResource hInst=%04X typename=%08X resname=%08X\n",
445 instance, type_name, resource_name);
446 #endif
448 ResourceFd = r->fd;
449 ResourceFileInfo = r->wpnt;
451 /* nametable loaded ? */
452 if (r->wpnt->ne->resnamtab == NULL)
453 RSC_LoadNameTable();
455 if (((int) type_name & 0xffff0000) == 0)
457 type = (int) type_name;
459 else if (type_name[0] == '\0')
461 type = -1;
463 else if (type_name[0] == '#')
465 type = atoi(type_name + 1);
467 else
469 type = (int) type_name;
471 if (((int) resource_name & 0xffff0000) == 0)
473 r->size_shift = FindResourceByNumber(&r->nameinfo, type,
474 (int) resource_name | 0x8000);
476 else if (resource_name[0] == '\0')
478 r->size_shift = FindResourceByNumber(&r->nameinfo, type, -1);
480 else if (resource_name[0] == '#')
482 r->size_shift = FindResourceByNumber(&r->nameinfo, type,
483 atoi(resource_name + 1));
485 else
487 r->size_shift = FindResourceByName(&r->nameinfo, type, resource_name);
490 if (r->size_shift == -1)
492 printf("NE_FindResource hInst=%04X typename=%08X resname=%08X not found!\n",
493 instance, (int) type_name, (int) resource_name);
494 return 0;
496 r->size = r->nameinfo.length << r->size_shift;
497 r->offset = r->nameinfo.offset << r->size_shift;
498 return 1;