3 * Copyright 1993 Robert J. Amstadt
4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
24 #define NEXT_TYPEINFO(pTypeInfo) ((NE_TYPEINFO *)((char*)((pTypeInfo) + 1) + \
25 (pTypeInfo)->count * sizeof(NE_NAMEINFO)))
27 /***********************************************************************
30 * Find the type and resource id from their names.
31 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
33 static DWORD
NE_FindNameTableId( NE_MODULE
*pModule
, SEGPTR typeId
, SEGPTR resId
)
35 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
36 NE_NAMEINFO
*pNameInfo
;
42 for (; pTypeInfo
->type_id
!= 0;
43 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+1) +
44 pTypeInfo
->count
* sizeof(NE_NAMEINFO
)))
46 if (pTypeInfo
->type_id
!= 0x800f) continue;
47 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
48 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
50 dprintf_resource( stddeb
, "NameTable entry: type=%04x id=%04x\n",
51 pTypeInfo
->type_id
, pNameInfo
->id
);
52 handle
= LoadResource16( pModule
->self
,
53 (HRSRC16
)((int)pNameInfo
- (int)pModule
) );
54 for(p
= (WORD
*)LockResource16(handle
); p
&& *p
; p
= (WORD
*)((char*)p
+*p
))
56 dprintf_resource( stddeb
," type=%04x '%s' id=%04x '%s'\n",
57 p
[1], (char *)(p
+3), p
[2],
58 (char *)(p
+3)+strlen((char *)(p
+3))+1 );
59 /* Check for correct type */
63 if (!HIWORD(typeId
)) continue;
64 if (lstrcmpi32A( (char *)PTR_SEG_TO_LIN(typeId
),
65 (char *)(p
+ 3) )) continue;
67 else if (HIWORD(typeId
) || ((typeId
& ~0x8000)!= p
[1]))
70 /* Now check for the id */
74 if (!HIWORD(resId
)) continue;
75 if (lstrcmpi32A( (char *)PTR_SEG_TO_LIN(resId
),
76 (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
79 else if (HIWORD(resId
) || ((resId
& ~0x8000) != p
[2]))
82 /* If we get here, we've found the entry */
84 dprintf_resource( stddeb
, " Found!\n" );
85 ret
= MAKELONG( p
[1], p
[2] );
88 FreeResource16( handle
);
95 /***********************************************************************
98 * Find header struct for a particular resource type.
100 static NE_TYPEINFO
* NE_FindTypeSection( NE_MODULE
*pModule
,
101 NE_TYPEINFO
*pTypeInfo
, SEGPTR typeId
)
103 /* start from pTypeInfo */
105 if (HIWORD(typeId
) != 0) /* Named type */
107 char *str
= (char *)PTR_SEG_TO_LIN( typeId
);
108 BYTE len
= strlen( str
);
109 while (pTypeInfo
->type_id
)
111 if (!(pTypeInfo
->type_id
& 0x8000))
113 BYTE
*p
= (BYTE
*)pModule
+ pModule
->res_table
+ pTypeInfo
->type_id
;
114 if ((*p
== len
) && !lstrncmpi32A( p
+1, str
, len
))
116 dprintf_resource( stddeb
, " Found type '%s'\n", str
);
120 dprintf_resource( stddeb
, " Skipping type %04x\n", pTypeInfo
->type_id
);
121 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
124 else /* Numeric type id */
126 WORD id
= LOWORD(typeId
) | 0x8000;
127 while (pTypeInfo
->type_id
)
129 if (pTypeInfo
->type_id
== id
)
131 dprintf_resource( stddeb
, " Found type %04x\n", id
);
134 dprintf_resource( stddeb
, " Skipping type %04x\n", pTypeInfo
->type_id
);
135 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
141 /***********************************************************************
142 * NE_FindResourceFromType
144 * Find a resource once the type info structure has been found.
146 static HRSRC16
NE_FindResourceFromType( NE_MODULE
*pModule
,
147 NE_TYPEINFO
*pTypeInfo
, SEGPTR resId
)
151 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
153 if (HIWORD(resId
) != 0) /* Named resource */
155 char *str
= (char *)PTR_SEG_TO_LIN( resId
);
156 BYTE len
= strlen( str
);
157 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
159 if (pNameInfo
->id
& 0x8000) continue;
160 p
= (BYTE
*)pModule
+ pModule
->res_table
+ pNameInfo
->id
;
161 if ((*p
== len
) && !lstrncmpi32A( p
+1, str
, len
))
162 return (HRSRC16
)((int)pNameInfo
- (int)pModule
);
165 else /* Numeric resource id */
167 WORD id
= LOWORD(resId
) | 0x8000;
168 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
169 if (pNameInfo
->id
== id
)
170 return (HRSRC16
)((int)pNameInfo
- (int)pModule
);
176 /***********************************************************************
177 * NE_DefResourceHandler
179 * This is the default LoadProc() function.
181 HGLOBAL16 WINAPI
NE_DefResourceHandler( HGLOBAL16 hMemObj
, HMODULE16 hModule
,
185 NE_MODULE
* pModule
= MODULE_GetPtr( hModule
);
186 if ( pModule
&& (fd
= MODULE_OpenFile( hModule
)) >= 0)
189 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
190 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
192 dprintf_resource( stddeb
, "NEResourceHandler: loading, pos=%d, len=%d\n",
193 (int)pNameInfo
->offset
<< sizeShift
,
194 (int)pNameInfo
->length
<< sizeShift
);
196 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
198 handle
= NE_AllocResource( hModule
, hRsrc
, 0 );
202 lseek( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
203 read( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
);
210 /***********************************************************************
211 * NE_InitResourceHandler
213 * Fill in 'resloader' fields in the resource table.
215 BOOL32
NE_InitResourceHandler( HMODULE16 hModule
)
217 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
218 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
220 dprintf_resource(stddeb
,"InitResourceHandler[%04x]\n", hModule
);
222 while(pTypeInfo
->type_id
)
224 pTypeInfo
->resloader
= (DWORD
)&NE_DefResourceHandler
;
225 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
230 /***********************************************************************
231 * NE_SetResourceHandler
233 FARPROC32
NE_SetResourceHandler( HMODULE16 hModule
, SEGPTR typeId
,
234 FARPROC32 resourceHandler
)
236 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
237 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
238 FARPROC32 prevHandler
= NULL
;
242 pTypeInfo
= NE_FindTypeSection( pModule
, pTypeInfo
, typeId
);
245 prevHandler
= (FARPROC32
)pTypeInfo
->resloader
;
246 pTypeInfo
->resloader
= (DWORD
)resourceHandler
;
247 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
249 } while( pTypeInfo
);
253 /***********************************************************************
256 HRSRC16
NE_FindResource( HMODULE16 hModule
, SEGPTR typeId
, SEGPTR resId
)
258 NE_TYPEINFO
*pTypeInfo
;
261 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
262 if (!pModule
|| !pModule
->res_table
) return 0;
263 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
265 if (HIWORD(typeId
) || HIWORD(resId
))
267 DWORD id
= NE_FindNameTableId( pModule
, typeId
, resId
);
277 pTypeInfo
= NE_FindTypeSection( pModule
, pTypeInfo
, typeId
);
280 hRsrc
= NE_FindResourceFromType(pModule
, pTypeInfo
, resId
);
283 dprintf_resource( stddeb
, " Found id %08lx\n", resId
);
286 dprintf_resource( stddeb
, " Not found, going on\n" );
287 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
289 } while( pTypeInfo
);
291 dprintf_resource( stddeb
, "failed!\n");
296 /***********************************************************************
299 HGLOBAL16
NE_AllocResource( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
301 NE_NAMEINFO
*pNameInfo
=NULL
;
304 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
305 if (!pModule
|| !pModule
->res_table
) return 0;
306 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
307 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
308 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
309 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
310 return GLOBAL_Alloc( GMEM_FIXED
, size
, hModule
, FALSE
, FALSE
, FALSE
);
314 /***********************************************************************
317 int NE_AccessResource( HMODULE16 hModule
, HRSRC16 hRsrc
)
319 NE_NAMEINFO
*pNameInfo
=NULL
;
322 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
323 if (!pModule
|| !pModule
->res_table
) return -1;
324 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
326 if ((fd
= _lopen32( NE_MODULE_NAME(pModule
), OF_READ
)) != -1)
328 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
329 _llseek32( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
335 /***********************************************************************
338 DWORD
NE_SizeofResource( HMODULE16 hModule
, HRSRC16 hRsrc
)
340 NE_NAMEINFO
*pNameInfo
=NULL
;
343 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
344 if (!pModule
|| !pModule
->res_table
) return 0;
345 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
346 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
347 return (DWORD
)pNameInfo
->length
<< sizeShift
;
351 /***********************************************************************
354 HGLOBAL16
NE_LoadResource( HMODULE16 hModule
, HRSRC16 hRsrc
)
356 NE_TYPEINFO
*pTypeInfo
;
357 NE_NAMEINFO
*pNameInfo
= NULL
;
358 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
361 if (!hRsrc
|| !pModule
|| !pModule
->res_table
) return 0;
363 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
365 d
= pModule
->res_table
+ 2;
366 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
369 if (pTypeInfo
->type_id
== 0)
370 break; /* terminal entry */
371 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
374 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
376 pNameInfo
= (NE_NAMEINFO
*)(((char *)pModule
) + hRsrc
);
380 break; /* NE_NAMEINFO boundary mismatch */
382 pTypeInfo
= (NE_TYPEINFO
*)(((char *)pModule
) + d
);
387 RESOURCEHANDLER16 __r16loader
;
388 if (pNameInfo
->handle
389 && !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
392 dprintf_resource( stddeb
, " Already loaded, new count=%d\n",
397 if (pTypeInfo
->resloader
)
398 __r16loader
= (RESOURCEHANDLER16
)pTypeInfo
->resloader
;
399 else /* this is really bad */
401 fprintf( stderr
, "[%04x]: Missing resource handler!!!...\n", hModule
);
402 __r16loader
= NE_DefResourceHandler
;
405 /* Finally call resource loader */
407 if ((pNameInfo
->handle
= __r16loader(pNameInfo
->handle
, hModule
, hRsrc
)))
410 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
413 return pNameInfo
->handle
;
419 /***********************************************************************
422 SEGPTR
NE_LockResource( HMODULE16 hModule
, HGLOBAL16 handle
)
424 /* May need to reload the resource if discarded */
426 return (SEGPTR
)WIN16_GlobalLock16( handle
);
430 /***********************************************************************
433 BOOL32
NE_FreeResource( HMODULE16 hModule
, HGLOBAL16 handle
)
435 NE_TYPEINFO
*pTypeInfo
;
436 NE_NAMEINFO
*pNameInfo
;
439 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
440 if (!handle
|| !pModule
|| !pModule
->res_table
) return handle
;
441 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
442 while (pTypeInfo
->type_id
)
444 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
445 for (count
= pTypeInfo
->count
; count
> 0; count
--)
447 if (pNameInfo
->handle
== handle
)
449 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
450 if (pNameInfo
->usage
== 0)
452 GlobalFree16( pNameInfo
->handle
);
453 pNameInfo
->handle
= 0;
454 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
460 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;
463 dprintf_resource(stddeb
, "NE_FreeResource[%04x]: no intrinsic resource for %04x\n",
465 GlobalFree16( handle
); /* it could have been DirectResAlloc()'ed */