Release 941122
[wine/multimedia.git] / loader / ne_resource.c
blobaeeab19700b3cc54927a8431aa2167ddd8becd7d
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"
17 #include "stddebug.h"
18 #include "debug.h"
20 /**********************************************************************
21 * NE_LoadNameTable
23 static void NE_LoadNameTable(struct w_files *wpnt)
25 struct resource_typeinfo_s typeinfo;
26 struct resource_nameinfo_s nameinfo;
27 unsigned short size_shift;
28 RESNAMTAB *top, *new;
29 char read_buf[1024];
30 char *p;
31 int i;
32 unsigned short len;
33 off_t saved_pos;
35 top = NULL;
37 * Move to beginning of resource table.
39 lseek(wpnt->fd, wpnt->mz_header->ne_offset +
40 wpnt->ne->ne_header->resource_tab_offset, SEEK_SET);
43 * Read block size.
45 if (read(wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift))
46 return;
48 size_shift = CONV_SHORT(size_shift);
51 * Find resource.
53 typeinfo.type_id = 0xffff;
54 while (typeinfo.type_id != 0)
56 if (read(wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo))
57 break;
59 if (typeinfo.type_id == 0)
60 break;
62 if (typeinfo.type_id == 0x800f)
64 for (i = 0; i < typeinfo.count; i++)
66 if (read(wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
67 break;
69 saved_pos = lseek(wpnt->fd, 0, SEEK_CUR);
70 lseek(wpnt->fd, (long) nameinfo.offset << size_shift,
71 SEEK_SET);
72 read(wpnt->fd, &len, sizeof(len));
73 while (len)
75 new = (RESNAMTAB *) GlobalQuickAlloc(sizeof(*new));
76 new->next = top;
77 top = new;
79 read(wpnt->fd, &new->type_ord, 2);
80 read(wpnt->fd, &new->id_ord, 2);
81 read(wpnt->fd, read_buf, len - 6);
83 p = read_buf + strlen(read_buf) + 1;
84 strncpy(new->id, p, MAX_NAME_LENGTH);
85 new->id[MAX_NAME_LENGTH - 1] = '\0';
87 read(wpnt->fd, &len, sizeof(len));
89 lseek(wpnt->fd, saved_pos, SEEK_SET);
91 } else
92 lseek(wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
94 wpnt->ne->resnamtab = top;
97 static int type_match(int type_id1, int type_id2, int fd, off_t off)
99 off_t old_pos;
100 unsigned char c;
101 size_t nbytes;
102 char name[256];
104 if (type_id1 == -1)
105 return 1;
106 if ((type_id1 & 0xffff0000) == 0) {
107 if ((type_id2 & 0x8000) == 0)
108 return 0;
109 return (type_id1 & 0x000f) == (type_id2 & 0x000f);
111 if ((type_id2 & 0x8000) != 0)
112 return 0;
113 dprintf_resource(stddeb, "type_compare: type_id2=%04X !\n", type_id2);
115 old_pos = lseek(fd, 0, SEEK_CUR);
116 lseek(fd, off + type_id2, SEEK_SET);
117 read(fd, &c, 1);
118 nbytes = CONV_CHAR_TO_LONG(c);
120 dprintf_resource(stddeb, "type_compare: namesize=%d\n", nbytes);
121 read(fd, name, nbytes);
122 lseek(fd, old_pos, SEEK_SET);
123 name[nbytes] = '\0';
124 dprintf_resource(stddeb, "type_compare: name=`%s'\n", name);
125 return strcasecmp((char *) type_id1, name) == 0;
128 /**********************************************************************
129 * FindResourceByNumber
131 static int FindResourceByNumber(RESOURCE *r, int type_id, int resource_id)
133 struct resource_typeinfo_s typeinfo;
134 struct resource_nameinfo_s nameinfo;
135 unsigned short size_shift;
136 int i;
137 off_t rtoff;
139 dprintf_resource(stddeb, "FindResourceByNumber: type_id =%x,m res_id = %x\n",
140 type_id, resource_id);
142 /* Move to beginning of resource table */
143 rtoff = (r->wpnt->mz_header->ne_offset +
144 r->wpnt->ne->ne_header->resource_tab_offset);
145 lseek(r->wpnt->fd, rtoff, SEEK_SET);
147 /* Read block size */
148 if (read(r->wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift)) {
149 printf("FindResourceByNumber (%d) bad block size !\n",(int) resource_id);
150 return -1;
152 size_shift = CONV_SHORT(size_shift);
154 /* Find resource */
155 for (;;) {
156 if (read(r->wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
157 printf("FindResourceByNumber (%X) bad typeinfo size !\n", resource_id);
158 return -1;
160 dprintf_resource(stddeb, "FindResourceByNumber type=%X count=%d ?=%ld searched=%08X\n",
161 typeinfo.type_id, typeinfo.count, typeinfo.reserved, type_id);
162 if (typeinfo.type_id == 0)
163 break;
164 if (type_match(type_id, typeinfo.type_id, r->wpnt->fd, rtoff)) {
166 for (i = 0; i < typeinfo.count; i++) {
167 #ifndef WINELIB
168 if (read(r->wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
169 #else
170 if (!load_nameinfo(r->wpnt->fd, &nameinfo))
171 #endif
173 printf("FindResourceByNumber (%X) bad nameinfo size !\n", resource_id);
174 return -1;
176 dprintf_resource(stddeb, "FindResource: search type=%X id=%X // type=%X id=%X\n",
177 type_id, resource_id, typeinfo.type_id, nameinfo.id);
178 if (nameinfo.id == resource_id) {
179 r->size = nameinfo.length << size_shift;
180 r->offset = nameinfo.offset << size_shift;
181 return size_shift;
185 else
186 lseek(r->wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
188 return -1;
191 /**********************************************************************
192 * FindResourceByName
194 static int FindResourceByName(RESOURCE *r, int type_id, char *resource_name)
196 struct resource_typeinfo_s typeinfo;
197 struct resource_nameinfo_s nameinfo;
198 unsigned short size_shift;
199 off_t old_pos, new_pos;
200 unsigned char nbytes;
201 char name[256];
202 int i;
203 off_t rtoff;
205 /* Check for loaded name table */
206 if (r->wpnt->ne->resnamtab != NULL) {
207 RESNAMTAB *e;
209 for (e = r->wpnt->ne->resnamtab; e != NULL; e = e->next)
210 if (e->type_ord == (type_id & 0x000f) &&
211 strcasecmp(e->id, resource_name) == 0)
213 return FindResourceByNumber(r, type_id, e->id_ord);
215 return -1;
218 /* Move to beginning of resource table */
219 rtoff = (r->wpnt->mz_header->ne_offset +
220 r->wpnt->ne->ne_header->resource_tab_offset);
221 lseek(r->wpnt->fd, rtoff, SEEK_SET);
223 /* Read block size */
224 if (read(r->wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift))
226 printf("FindResourceByName (%s) bad block size !\n", resource_name);
227 return -1;
229 size_shift = CONV_SHORT (size_shift);
231 /* Find resource */
232 for (;;)
234 if (read(r->wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
235 printf("FindResourceByName (%s) bad typeinfo size !\n", resource_name);
236 return -1;
238 dprintf_resource(stddeb, "FindResourceByName typeinfo.type_id=%X count=%d type_id=%X\n",
239 typeinfo.type_id, typeinfo.count, type_id);
240 if (typeinfo.type_id == 0)
241 break;
242 if (type_match(type_id, typeinfo.type_id, r->wpnt->fd, rtoff))
244 for (i = 0; i < typeinfo.count; i++)
246 #ifndef WINELIB
247 if (read(r->wpnt->fd, &nameinfo, sizeof(nameinfo)) != sizeof(nameinfo))
248 #else
249 if (!load_nameinfo (r->wpnt->fd, &nameinfo))
250 #endif
252 printf("FindResourceByName (%s) bad nameinfo size !\n", resource_name);
253 return -1;
256 if ((nameinfo.id & 0x8000) != 0) continue;
258 dprintf_resource(stddeb, "FindResourceByName // nameinfo.id=%04X !\n", nameinfo.id);
259 old_pos = lseek(r->wpnt->fd, 0, SEEK_CUR);
260 new_pos = rtoff + nameinfo.id;
261 lseek(r->wpnt->fd, new_pos, SEEK_SET);
262 read(r->wpnt->fd, &nbytes, 1);
263 dprintf_resource(stddeb, "FindResourceByName // namesize=%d !\n", nbytes);
264 nbytes = CONV_CHAR_TO_LONG (nbytes);
265 read(r->wpnt->fd, name, nbytes);
266 lseek(r->wpnt->fd, old_pos, SEEK_SET);
267 name[nbytes] = '\0';
268 dprintf_resource(stddeb, "FindResourceByName type_id=%X (%d of %d) name='%s' resource_name='%s'\n",
269 typeinfo.type_id, i + 1, typeinfo.count,
270 name, resource_name);
271 if (strcasecmp(name, resource_name) == 0) {
272 r->size = nameinfo.length << size_shift;
273 r->offset = nameinfo.offset << size_shift;
274 return size_shift;
278 else
279 lseek(r->wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
281 return -1;
285 /**********************************************************************
286 * GetRsrcCount [internal]
288 int GetRsrcCount(HINSTANCE hInst, int type_id)
290 struct w_files *wpnt;
291 struct resource_typeinfo_s typeinfo;
292 struct resource_nameinfo_s nameinfo;
293 unsigned short size_shift;
294 off_t rtoff;
296 if (hInst == 0)
297 return 0;
298 dprintf_resource(stddeb, "GetRsrcCount hInst=%04X typename=%08X\n",
299 hInst, type_id);
301 if ((wpnt = GetFileInfo(hInst)) == NULL)
302 return 0;
304 * Move to beginning of resource table.
306 rtoff = (wpnt->mz_header->ne_offset +
307 wpnt->ne->ne_header->resource_tab_offset);
308 lseek(wpnt->fd, rtoff, SEEK_SET);
310 * Read block size.
312 if (read(wpnt->fd, &size_shift, sizeof(size_shift)) != sizeof(size_shift)) {
313 printf("GetRsrcCount // bad block size !\n");
314 return -1;
316 size_shift = CONV_SHORT (size_shift);
317 for (;;) {
318 if (read(wpnt->fd, &typeinfo, sizeof(typeinfo)) != sizeof(typeinfo)) {
319 printf("GetRsrcCount // bad typeinfo size !\n");
320 return 0;
322 dprintf_resource(stddeb, "GetRsrcCount // typeinfo.type_id=%X count=%d type_id=%X\n",
323 typeinfo.type_id, typeinfo.count, type_id);
324 if (typeinfo.type_id == 0)
325 break;
326 if (type_match(type_id, typeinfo.type_id, wpnt->fd, rtoff))
327 return typeinfo.count;
328 else
329 lseek(wpnt->fd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
331 return 0;
334 /**********************************************************************
335 * NE_FindResource [KERNEL.60]
337 int NE_FindResource(HANDLE instance, LPSTR resource_name, LPSTR type_name,
338 RESOURCE *r)
340 int type, x;
342 dprintf_resource(stddeb, "NE_FindResource hInst=%04X typename=%p resname=%p\n",
343 instance, type_name, resource_name);
345 r->size = r->offset = 0;
347 /* nametable loaded ? */
348 if (r->wpnt->ne->resnamtab == NULL)
349 NE_LoadNameTable(r->wpnt);
351 if (((int) type_name & 0xffff0000) == 0)
352 type = (int) type_name;
353 else {
354 if (type_name[0] == '\0')
355 type = -1;
356 if (type_name[0] == '#')
357 type = atoi(type_name + 1);
358 else
359 type = (int) type_name;
362 if (((int) resource_name & 0xffff0000) == 0)
363 x = FindResourceByNumber(r, type, (int) resource_name | 0x8000);
364 else {
365 if (resource_name[0] == '\0')
366 x = FindResourceByNumber(r, type, -1);
367 if (resource_name[0] == '#')
368 x = FindResourceByNumber(r, type, atoi(resource_name + 1));
369 else
370 x = FindResourceByName(r, type, resource_name);
372 if (x == -1) {
373 printf("NE_FindResource hInst=%04X typename=%08X resname=%08X not found!\n",
374 instance, (int) type_name, (int) resource_name);
375 return 0;
377 return 1;