Release 960611
[wine] / loader / ne_resource.c
1 #ifndef WINELIB
2 /*
3  *
4  * Copyright 1993 Robert J. Amstadt
5  * Copyright 1995 Alexandre Julliard
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include "windows.h"
16 #include "arch.h"
17 #include "dos_fs.h"
18 #include "global.h"
19 #include "ldt.h"
20 #include "module.h"
21 #include "neexe.h"
22 #include "resource.h"
23 #include "stddebug.h"
24 #include "debug.h"
25
26
27 /***********************************************************************
28  *           NE_FindNameTableId
29  *
30  * Find the type and resource id from their names.
31  * Return value is MAKELONG( typeId, resId ), or 0 if not found.
32  */
33 static DWORD NE_FindNameTableId( HMODULE hModule, SEGPTR typeId, SEGPTR resId )
34 {
35     NE_MODULE *pModule;
36     NE_TYPEINFO *pTypeInfo;
37     NE_NAMEINFO *pNameInfo;
38     HGLOBAL handle;
39     WORD *p;
40     DWORD ret = 0;
41     int count;
42
43     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
44     pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
45     for (; pTypeInfo->type_id != 0;
46              pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
47                                        pTypeInfo->count * sizeof(NE_NAMEINFO)))
48     {
49         if (pTypeInfo->type_id != 0x800f) continue;
50         pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
51         for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
52         {
53             dprintf_resource( stddeb, "NameTable entry: type=%04x id=%04x\n",
54                               pTypeInfo->type_id, pNameInfo->id );
55             handle = LoadResource( hModule, 
56                                    (HANDLE)((int)pNameInfo - (int)pModule) );
57             for(p = (WORD*)LockResource(handle); p && *p; p = (WORD *)((char*)p+*p))
58             {
59                 dprintf_resource( stddeb,"  type=%04x '%s' id=%04x '%s'\n",
60                                   p[1], (char *)(p+3), p[2],
61                                   (char *)(p+3)+strlen((char *)(p+3))+1 );
62                 /* Check for correct type */
63
64                 if (p[1] & 0x8000)
65                 {
66                     if (!HIWORD(typeId)) continue;
67                     if (lstrcmpi32A( (char *)PTR_SEG_TO_LIN(typeId),
68                                      (char *)(p + 3) )) continue;
69                 }
70                 else if (HIWORD(typeId) || ((typeId & ~0x8000)!= p[1]))
71                   continue;
72
73                 /* Now check for the id */
74
75                 if (p[2] & 0x8000)
76                 {
77                     if (!HIWORD(resId)) continue;
78                     if (lstrcmpi32A( (char *)PTR_SEG_TO_LIN(resId),
79                                (char*)(p+3)+strlen((char*)(p+3))+1 )) continue;
80                     
81                 }
82                 else if (HIWORD(resId) || ((resId & ~0x8000) != p[2]))
83                   continue;
84
85                 /* If we get here, we've found the entry */
86
87                 dprintf_resource( stddeb, "  Found!\n" );
88                 ret = MAKELONG( p[1], p[2] );
89                 break;
90             }
91             FreeResource( handle );
92             if (ret) return ret;
93         }
94     }
95     return 0;
96 }
97
98
99 /***********************************************************************
100  *           NE_FindResourceFromType
101  *
102  * Find a resource once the type info structure has been found.
103  */
104 static HRSRC NE_FindResourceFromType( NE_MODULE *pModule,
105                                       NE_TYPEINFO *pTypeInfo, SEGPTR resId )
106 {
107     BYTE *p;
108     int count;
109     NE_NAMEINFO *pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
110
111     if (HIWORD(resId) != 0)  /* Named resource */
112     {
113         char *str = (char *)PTR_SEG_TO_LIN( resId );
114         BYTE len = strlen( str );
115         for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
116         {
117             if (pNameInfo->id & 0x8000) continue;
118             p = (BYTE *)pModule + pModule->res_table + pNameInfo->id;
119             if ((*p == len) && !lstrncmpi32A( p+1, str, len ))
120                 return (HRSRC)((int)pNameInfo - (int)pModule);
121         }
122     }
123     else  /* Numeric resource id */
124     {
125         WORD id = LOWORD(resId) | 0x8000;
126         for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
127             if (pNameInfo->id == id) 
128               return (HRSRC)((int)pNameInfo - (int)pModule);
129     }
130     return 0;
131 }
132
133
134 /***********************************************************************
135  *           NE_FindResource
136  */
137 HRSRC NE_FindResource( HMODULE hModule, SEGPTR typeId, SEGPTR resId )
138 {
139     NE_TYPEINFO *pTypeInfo;
140     HRSRC hRsrc;
141
142     NE_MODULE *pModule = MODULE_GetPtr( hModule );
143     if (!pModule || !pModule->res_table) return 0;
144     pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
145
146     if (HIWORD(typeId) || HIWORD(resId))
147     {
148         /* Search the names in the nametable */
149         DWORD id = NE_FindNameTableId( hModule, typeId, resId );
150         if (id)  /* found */
151         {
152             typeId = LOWORD(id);
153             resId  = HIWORD(id);
154         }
155     }
156
157     if (HIWORD(typeId) != 0)  /* Named type */
158     {
159         char *str = (char *)PTR_SEG_TO_LIN( typeId );
160         BYTE len = strlen( str );
161         while (pTypeInfo->type_id)
162         {
163             if (!(pTypeInfo->type_id & 0x8000))
164             {
165                 BYTE *p = (BYTE*)pModule+pModule->res_table+pTypeInfo->type_id;
166                 if ((*p == len) && !lstrncmpi32A( p+1, str, len ))
167                 {
168                     dprintf_resource( stddeb, "  Found type '%s'\n", str );
169                     hRsrc = NE_FindResourceFromType(pModule, pTypeInfo, resId);
170                     if (hRsrc)
171                     {
172                         dprintf_resource( stddeb, "    Found id %08lx\n", resId );
173                         return hRsrc;
174                     }
175                     dprintf_resource( stddeb, "    Not found, going on\n" );
176                 }
177             }
178             dprintf_resource( stddeb, "  Skipping type %04x\n",
179                               pTypeInfo->type_id );
180             pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
181                                        pTypeInfo->count * sizeof(NE_NAMEINFO));
182         }
183     }
184     else  /* Numeric type id */
185     {
186         WORD id = LOWORD(typeId) | 0x8000;
187         while (pTypeInfo->type_id)
188         {
189             if (pTypeInfo->type_id == id)
190             {
191                 dprintf_resource( stddeb, "  Found type %04x\n", id );
192                 hRsrc = NE_FindResourceFromType( pModule, pTypeInfo, resId );
193                 if (hRsrc)
194                 {
195                     dprintf_resource( stddeb, "    Found id %08lx\n", resId );
196                     return hRsrc;
197                 }
198                 dprintf_resource( stddeb, "    Not found, going on\n" );
199             }
200             dprintf_resource( stddeb, "  Skipping type %04x\n",
201                               pTypeInfo->type_id );
202             pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
203                                        pTypeInfo->count * sizeof(NE_NAMEINFO));
204         }
205     }
206     return 0;
207 }
208
209
210
211 /***********************************************************************
212  *           NE_AllocResource
213  */
214 HGLOBAL NE_AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size )
215 {
216     NE_NAMEINFO *pNameInfo=NULL;
217     WORD sizeShift;
218
219     NE_MODULE *pModule = MODULE_GetPtr( hModule );
220     if (!pModule || !pModule->res_table) return 0;
221     sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
222 #ifndef WINELIB
223     pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
224 #endif
225     if (size < (DWORD)pNameInfo->length << sizeShift)
226         size = (DWORD)pNameInfo->length << sizeShift;
227     return GLOBAL_Alloc( GMEM_FIXED, size, hModule, FALSE, FALSE, FALSE );
228 }
229
230
231 /***********************************************************************
232  *           NE_AccessResource
233  */
234 int NE_AccessResource( HMODULE hModule, HRSRC hRsrc )
235 {
236     NE_NAMEINFO *pNameInfo=NULL;
237     int fd;
238
239     NE_MODULE *pModule = MODULE_GetPtr( hModule );
240     if (!pModule || !pModule->res_table) return -1;
241 #ifndef WINELIB
242     pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
243 #endif
244
245     if ((fd = _lopen( NE_MODULE_NAME(pModule), OF_READ )) != -1)
246     {
247         WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
248         _llseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
249     }
250     return fd;
251 }
252
253
254 /***********************************************************************
255  *           NE_SizeofResource
256  */
257 DWORD NE_SizeofResource( HMODULE hModule, HRSRC hRsrc )
258 {
259     NE_NAMEINFO *pNameInfo=NULL;
260     WORD sizeShift;
261
262     NE_MODULE *pModule = MODULE_GetPtr( hModule );
263     if (!pModule || !pModule->res_table) return 0;
264     sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
265 #ifndef WINELIB
266     pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
267 #endif
268     return (DWORD)pNameInfo->length << sizeShift;
269 }
270
271
272 /***********************************************************************
273  *           NE_LoadResource
274  */
275 HGLOBAL NE_LoadResource( HMODULE hModule,  HRSRC hRsrc )
276 {
277     NE_NAMEINFO *pNameInfo=NULL;
278     WORD sizeShift;
279     int fd;
280
281     NE_MODULE *pModule = MODULE_GetPtr( hModule );
282     if (!pModule || !pModule->res_table) return 0;
283 #ifndef WINELIB
284     pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
285 #endif
286     if (pNameInfo->handle)
287     {
288         pNameInfo->usage++;
289         dprintf_resource( stddeb, "  Already loaded, new count=%d\n",
290                           pNameInfo->usage );
291         return pNameInfo->handle;
292     }
293     sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
294     dprintf_resource( stddeb, "  Loading, pos=%d, len=%d\n",
295                       (int)pNameInfo->offset << sizeShift,
296                       (int)pNameInfo->length << sizeShift );
297     if ((fd = MODULE_OpenFile( hModule )) == -1) return 0;
298     pNameInfo->handle = NE_AllocResource( hModule, hRsrc, 0 );
299     pNameInfo->usage = 1;
300     lseek( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
301     read( fd, GlobalLock16( pNameInfo->handle ),
302           (int)pNameInfo->length << sizeShift );
303     return pNameInfo->handle;
304 }
305
306
307 /***********************************************************************
308  *           NE_LockResource
309  */
310 SEGPTR NE_LockResource( HMODULE hModule, HGLOBAL handle )
311 {
312     /* May need to reload the resource if discarded */
313
314     return (SEGPTR)WIN16_GlobalLock16( handle );
315 }
316
317
318 /***********************************************************************
319  *           NE_FreeResource
320  */
321 BOOL NE_FreeResource( HMODULE hModule, HGLOBAL handle )
322 {
323     NE_TYPEINFO *pTypeInfo;
324     NE_NAMEINFO *pNameInfo;
325     WORD count;
326
327     NE_MODULE *pModule = MODULE_GetPtr( hModule );
328     if (!pModule || !pModule->res_table) return FALSE;
329     pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
330     while (pTypeInfo->type_id)
331     {
332         pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
333         for (count = pTypeInfo->count; count > 0; count--)
334         {
335             if (pNameInfo->handle == handle)
336             {
337                 if (pNameInfo->usage > 0) pNameInfo->usage--;
338                 if (pNameInfo->usage == 0)
339                 {
340                     GlobalFree16( pNameInfo->handle );
341                     pNameInfo->handle = 0;
342                 }
343                 return TRUE;
344             }
345             pNameInfo++;
346         }
347         pTypeInfo = (NE_TYPEINFO *)pNameInfo;
348     }
349     fprintf( stderr, "FreeResource: %04x %04x not found!\n", hModule, handle );
350     return FALSE;
351 }
352 #endif /* WINELIB */