Release 950109
[wine/multimedia.git] / loader / ne_resource.c
blob9a3e56d072a03998688698f668356dc71ea3a7db
1 /*
2 static char RCSId[] = "$Id: ne_resource.c,v 1.4 1993/07/04 04:04:21 root Exp root $";
3 static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
4 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include "windows.h"
13 #include "neexe.h"
14 #include "peexe.h"
15 #include "arch.h"
16 #include "dlls.h"
17 #include "library.h"
18 #include "heap.h"
19 #include "resource.h"
20 #include "stddebug.h"
21 #include "debug.h"
23 /**********************************************************************
24 * NE_LoadNameTable
26 static void NE_LoadNameTable(struct w_files *wpnt)
28 struct resource_typeinfo_s typeinfo;
29 struct resource_nameinfo_s nameinfo;
30 unsigned short size_shift;
31 RESNAMTAB *top, *new;
32 char read_buf[1024];
33 char *p;
34 int i;
35 unsigned short len;
36 off_t saved_pos;
38 top = NULL;
40 * Move to beginning of resource table.
42 lseek(wpnt->fd, wpnt->mz_header->ne_offset +
43 wpnt->ne->ne_header->resource_tab_offset, SEEK_SET);
46 * Read block size.
48 if (read(wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift))
49 return;
51 size_shift = CONV_SHORT(size_shift);
54 * Find resource.
56 typeinfo.type_id = 0xffff;
57 while (typeinfo.type_id != 0)
59 if (read(wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo))
60 break;
62 if (typeinfo.type_id == 0)
63 break;
65 if (typeinfo.type_id == 0x800f)
67 for (i = 0; i < typeinfo.count; i++)
69 if (read(wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
70 break;
72 saved_pos = lseek(wpnt->fd, 0, SEEK_CUR);
73 lseek(wpnt->fd, (long) nameinfo.offset << size_shift,
74 SEEK_SET);
75 read(wpnt->fd, &len, sizeof(len));
76 while (len)
78 new = (RESNAMTAB *) GlobalQuickAlloc(sizeof(*new));
79 new->next = top;
80 top = new;
82 read(wpnt->fd, &new->type_ord, 2);
83 read(wpnt->fd, &new->id_ord, 2);
84 read(wpnt->fd, read_buf, len - 6);
86 p = read_buf + strlen(read_buf) + 1;
87 strncpy(new->id, p, MAX_NAME_LENGTH);
88 new->id[MAX_NAME_LENGTH - 1] = '\0';
90 read(wpnt->fd, &len, sizeof(len));
92 lseek(wpnt->fd, saved_pos, SEEK_SET);
94 } else
95 lseek(wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
97 wpnt->ne->resnamtab = top;
100 static int type_match(int type_id1, int type_id2, int fd, off_t off)
102 off_t old_pos;
103 unsigned char c;
104 size_t nbytes;
105 char name[256];
107 if (type_id1 == -1)
108 return 1;
109 if ((type_id1 & 0xffff0000) == 0) {
110 if ((type_id2 & 0x8000) == 0)
111 return 0;
112 return (type_id1 & 0x000f) == (type_id2 & 0x000f);
114 if ((type_id2 & 0x8000) != 0)
115 return 0;
116 dprintf_resource(stddeb, "type_compare: type_id2=%04X !\n", type_id2);
118 old_pos = lseek(fd, 0, SEEK_CUR);
119 lseek(fd, off + type_id2, SEEK_SET);
120 read(fd, &c, 1);
121 nbytes = CONV_CHAR_TO_LONG(c);
123 dprintf_resource(stddeb, "type_compare: namesize=%d\n", nbytes);
124 read(fd, name, nbytes);
125 lseek(fd, old_pos, SEEK_SET);
126 name[nbytes] = '\0';
127 dprintf_resource(stddeb, "type_compare: name=`%s'\n", name);
128 return strcasecmp((char *) type_id1, name) == 0;
131 /**********************************************************************
132 * FindResourceByNumber
134 static int FindResourceByNumber(RESOURCE *r, int type_id, int resource_id)
136 struct resource_typeinfo_s typeinfo;
137 struct resource_nameinfo_s nameinfo;
138 unsigned short size_shift;
139 int i;
140 off_t rtoff;
142 dprintf_resource(stddeb, "FindResourceByNumber: type_id =%x,m res_id = %x\n",
143 type_id, resource_id);
145 /* Move to beginning of resource table */
146 rtoff = (r->wpnt->mz_header->ne_offset +
147 r->wpnt->ne->ne_header->resource_tab_offset);
148 lseek(r->wpnt->fd, rtoff, SEEK_SET);
150 /* Read block size */
151 if (read(r->wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift)) {
152 printf("FindResourceByNumber (%d) bad block size !\n",(int) resource_id);
153 return -1;
155 size_shift = CONV_SHORT(size_shift);
157 /* Find resource */
158 for (;;) {
159 if (read(r->wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
160 printf("FindResourceByNumber (%X) bad typeinfo size !\n", resource_id);
161 return -1;
163 dprintf_resource(stddeb, "FindResourceByNumber type=%X count=%d ?=%ld searched=%08X\n",
164 typeinfo.type_id, typeinfo.count, typeinfo.reserved, type_id);
165 if (typeinfo.type_id == 0)
166 break;
167 if (type_match(type_id, typeinfo.type_id, r->wpnt->fd, rtoff)) {
169 for (i = 0; i < typeinfo.count; i++) {
170 #ifndef WINELIB
171 if (read(r->wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
172 #else
173 if (!load_nameinfo(r->wpnt->fd, &nameinfo))
174 #endif
176 printf("FindResourceByNumber (%X) bad nameinfo size !\n", resource_id);
177 return -1;
179 dprintf_resource(stddeb, "FindResource: search type=%X id=%X // type=%X id=%X\n",
180 type_id, resource_id, typeinfo.type_id, nameinfo.id);
181 if (nameinfo.id == resource_id) {
182 r->size = nameinfo.length << size_shift;
183 r->offset = nameinfo.offset << size_shift;
184 return size_shift;
188 else
189 lseek(r->wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
191 return -1;
194 /**********************************************************************
195 * FindResourceByName
197 static int FindResourceByName(RESOURCE *r, int type_id, char *resource_name)
199 struct resource_typeinfo_s typeinfo;
200 struct resource_nameinfo_s nameinfo;
201 unsigned short size_shift;
202 off_t old_pos, new_pos;
203 unsigned char nbytes;
204 char name[256];
205 int i;
206 off_t rtoff;
208 /* Check for loaded name table */
209 if (r->wpnt->ne->resnamtab != NULL) {
210 RESNAMTAB *e;
212 for (e = r->wpnt->ne->resnamtab; e != NULL; e = e->next)
213 if (e->type_ord == (type_id & 0x000f) &&
214 strcasecmp(e->id, resource_name) == 0)
216 return FindResourceByNumber(r, type_id, e->id_ord);
218 return -1;
221 /* Move to beginning of resource table */
222 rtoff = (r->wpnt->mz_header->ne_offset +
223 r->wpnt->ne->ne_header->resource_tab_offset);
224 lseek(r->wpnt->fd, rtoff, SEEK_SET);
226 /* Read block size */
227 if (read(r->wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift))
229 printf("FindResourceByName (%s) bad block size !\n", resource_name);
230 return -1;
232 size_shift = CONV_SHORT (size_shift);
234 /* Find resource */
235 for (;;)
237 if (read(r->wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
238 printf("FindResourceByName (%s) bad typeinfo size !\n", resource_name);
239 return -1;
241 dprintf_resource(stddeb, "FindResourceByName typeinfo.type_id=%X count=%d type_id=%X\n",
242 typeinfo.type_id, typeinfo.count, type_id);
243 if (typeinfo.type_id == 0)
244 break;
245 if (type_match(type_id, typeinfo.type_id, r->wpnt->fd, rtoff))
247 for (i = 0; i < typeinfo.count; i++)
249 #ifndef WINELIB
250 if (read(r->wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
251 #else
252 if (!load_nameinfo (r->wpnt->fd, &nameinfo))
253 #endif
255 printf("FindResourceByName (%s) bad nameinfo size !\n", resource_name);
256 return -1;
259 if ((nameinfo.id & 0x8000) != 0) continue;
261 dprintf_resource(stddeb, "FindResourceByName // nameinfo.id=%04X !\n", nameinfo.id);
262 old_pos = lseek(r->wpnt->fd, 0, SEEK_CUR);
263 new_pos = rtoff + nameinfo.id;
264 lseek(r->wpnt->fd, new_pos, SEEK_SET);
265 read(r->wpnt->fd, &nbytes, 1);
266 dprintf_resource(stddeb, "FindResourceByName // namesize=%d !\n", nbytes);
267 nbytes = CONV_CHAR_TO_LONG (nbytes);
268 read(r->wpnt->fd, name, nbytes);
269 lseek(r->wpnt->fd, old_pos, SEEK_SET);
270 name[nbytes] = '\0';
271 dprintf_resource(stddeb, "FindResourceByName type_id=%X (%d of %d) name='%s' resource_name='%s'\n",
272 typeinfo.type_id, i + 1, typeinfo.count,
273 name, resource_name);
274 if (strcasecmp(name, resource_name) == 0) {
275 r->size = nameinfo.length << size_shift;
276 r->offset = nameinfo.offset << size_shift;
277 return size_shift;
281 else
282 lseek(r->wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
284 return -1;
288 /**********************************************************************
289 * GetRsrcCount [internal]
291 int GetRsrcCount(HINSTANCE hInst, int type_id)
293 struct w_files *wpnt;
294 struct resource_typeinfo_s typeinfo;
295 struct resource_nameinfo_s nameinfo;
296 unsigned short size_shift;
297 off_t rtoff;
299 if (hInst == 0)
300 return 0;
301 dprintf_resource(stddeb, "GetRsrcCount hInst=%04X typename=%08X\n",
302 hInst, type_id);
304 if ((wpnt = GetFileInfo(hInst)) == NULL)
305 return 0;
307 * Move to beginning of resource table.
309 rtoff = (wpnt->mz_header->ne_offset +
310 wpnt->ne->ne_header->resource_tab_offset);
311 lseek(wpnt->fd, rtoff, SEEK_SET);
313 * Read block size.
315 if (read(wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift)) {
316 printf("GetRsrcCount // bad block size !\n");
317 return -1;
319 size_shift = CONV_SHORT (size_shift);
320 for (;;) {
321 if (read(wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
322 printf("GetRsrcCount // bad typeinfo size !\n");
323 return 0;
325 dprintf_resource(stddeb, "GetRsrcCount // typeinfo.type_id=%X count=%d type_id=%X\n",
326 typeinfo.type_id, typeinfo.count, type_id);
327 if (typeinfo.type_id == 0)
328 break;
329 if (type_match(type_id, typeinfo.type_id, wpnt->fd, rtoff))
330 return typeinfo.count;
331 else
332 lseek(wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
334 return 0;
337 /**********************************************************************
338 * NE_FindResource [KERNEL.60]
340 int NE_FindResource(HANDLE instance, LPSTR resource_name, LPSTR type_name,
341 RESOURCE *r)
343 int type, x;
345 dprintf_resource(stddeb, "NE_FindResource hInst=%04X typename=%p resname=%p\n",
346 instance, type_name, resource_name);
348 r->size = r->offset = 0;
350 /* nametable loaded ? */
351 if (r->wpnt->ne->resnamtab == NULL)
352 NE_LoadNameTable(r->wpnt);
354 if (((int) type_name & 0xffff0000) == 0)
355 type = (int) type_name;
356 else {
357 if (type_name[0] == '\0')
358 type = -1;
359 if (type_name[0] == '#')
360 type = atoi(type_name + 1);
361 else
362 type = (int) type_name;
365 if (((int) resource_name & 0xffff0000) == 0)
366 x = FindResourceByNumber(r, type, (int) resource_name | 0x8000);
367 else {
368 if (resource_name[0] == '\0')
369 x = FindResourceByNumber(r, type, -1);
370 if (resource_name[0] == '#')
371 x = FindResourceByNumber(r, type, atoi(resource_name + 1));
372 else
373 x = FindResourceByName(r, type, resource_name);
375 if (x == -1) {
376 printf("NE_FindResource hInst=%04X typename=%08X resname=%08X not found!\n",
377 instance, (int) type_name, (int) resource_name);
378 return 0;
380 return 1;