4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
12 #include <sys/types.h>
25 #define NEXT_TYPEINFO(pTypeInfo) ((NE_TYPEINFO *)((char*)((pTypeInfo) + 1) + \
26 (pTypeInfo)->count * sizeof(NE_NAMEINFO)))
28 /***********************************************************************
31 * Find the type and resource id from their names.
32 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
34 static DWORD
NE_FindNameTableId( NE_MODULE
*pModule
, SEGPTR typeId
, SEGPTR resId
)
36 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
37 NE_NAMEINFO
*pNameInfo
;
43 for (; pTypeInfo
->type_id
!= 0;
44 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+1) +
45 pTypeInfo
->count
* sizeof(NE_NAMEINFO
)))
47 if (pTypeInfo
->type_id
!= 0x800f) continue;
48 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
49 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
51 dprintf_resource( stddeb
, "NameTable entry: type=%04x id=%04x\n",
52 pTypeInfo
->type_id
, pNameInfo
->id
);
53 handle
= LoadResource16( pModule
->self
,
54 (HRSRC16
)((int)pNameInfo
- (int)pModule
) );
55 for(p
= (WORD
*)LockResource16(handle
); p
&& *p
; p
= (WORD
*)((char*)p
+*p
))
57 dprintf_resource( stddeb
," type=%04x '%s' id=%04x '%s'\n",
58 p
[1], (char *)(p
+3), p
[2],
59 (char *)(p
+3)+strlen((char *)(p
+3))+1 );
60 /* Check for correct type */
64 if (!HIWORD(typeId
)) continue;
65 if (lstrcmpi32A( (char *)PTR_SEG_TO_LIN(typeId
),
66 (char *)(p
+ 3) )) continue;
68 else if (HIWORD(typeId
) || ((typeId
& ~0x8000)!= p
[1]))
71 /* Now check for the id */
75 if (!HIWORD(resId
)) continue;
76 if (lstrcmpi32A( (char *)PTR_SEG_TO_LIN(resId
),
77 (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
80 else if (HIWORD(resId
) || ((resId
& ~0x8000) != p
[2]))
83 /* If we get here, we've found the entry */
85 dprintf_resource( stddeb
, " Found!\n" );
86 ret
= MAKELONG( p
[1], p
[2] );
89 FreeResource16( handle
);
96 /***********************************************************************
99 * Find header struct for a particular resource type.
101 static NE_TYPEINFO
* NE_FindTypeSection( NE_MODULE
*pModule
,
102 NE_TYPEINFO
*pTypeInfo
, SEGPTR typeId
)
104 /* start from pTypeInfo */
106 if (HIWORD(typeId
) != 0) /* Named type */
108 char *str
= (char *)PTR_SEG_TO_LIN( typeId
);
109 BYTE len
= strlen( str
);
110 while (pTypeInfo
->type_id
)
112 if (!(pTypeInfo
->type_id
& 0x8000))
114 BYTE
*p
= (BYTE
*)pModule
+ pModule
->res_table
+ pTypeInfo
->type_id
;
115 if ((*p
== len
) && !lstrncmpi32A( p
+1, str
, len
))
117 dprintf_resource( stddeb
, " Found type '%s'\n", str
);
121 dprintf_resource( stddeb
, " Skipping type %04x\n", pTypeInfo
->type_id
);
122 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
125 else /* Numeric type id */
127 WORD id
= LOWORD(typeId
) | 0x8000;
128 while (pTypeInfo
->type_id
)
130 if (pTypeInfo
->type_id
== id
)
132 dprintf_resource( stddeb
, " Found type %04x\n", id
);
135 dprintf_resource( stddeb
, " Skipping type %04x\n", pTypeInfo
->type_id
);
136 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
142 /***********************************************************************
143 * NE_FindResourceFromType
145 * Find a resource once the type info structure has been found.
147 static HRSRC16
NE_FindResourceFromType( NE_MODULE
*pModule
,
148 NE_TYPEINFO
*pTypeInfo
, SEGPTR resId
)
152 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
154 if (HIWORD(resId
) != 0) /* Named resource */
156 char *str
= (char *)PTR_SEG_TO_LIN( resId
);
157 BYTE len
= strlen( str
);
158 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
160 if (pNameInfo
->id
& 0x8000) continue;
161 p
= (BYTE
*)pModule
+ pModule
->res_table
+ pNameInfo
->id
;
162 if ((*p
== len
) && !lstrncmpi32A( p
+1, str
, len
))
163 return (HRSRC16
)((int)pNameInfo
- (int)pModule
);
166 else /* Numeric resource id */
168 WORD id
= LOWORD(resId
) | 0x8000;
169 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
170 if (pNameInfo
->id
== id
)
171 return (HRSRC16
)((int)pNameInfo
- (int)pModule
);
177 /***********************************************************************
178 * NE_DefResourceHandler
180 * This is the default LoadProc() function.
182 HGLOBAL16 WINAPI
NE_DefResourceHandler( HGLOBAL16 hMemObj
, HMODULE16 hModule
,
186 NE_MODULE
* pModule
= MODULE_GetPtr( hModule
);
187 if ( pModule
&& (fd
= MODULE_OpenFile( hModule
)) >= 0)
190 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
191 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
193 dprintf_resource( stddeb
, "NEResourceHandler: loading, pos=%d, len=%d\n",
194 (int)pNameInfo
->offset
<< sizeShift
,
195 (int)pNameInfo
->length
<< sizeShift
);
197 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
199 handle
= NE_AllocResource( hModule
, hRsrc
, 0 );
203 lseek( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
204 read( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
);
211 /***********************************************************************
212 * NE_InitResourceHandler
214 * Fill in 'resloader' fields in the resource table.
216 BOOL32
NE_InitResourceHandler( HMODULE16 hModule
)
218 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
219 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
221 dprintf_resource(stddeb
,"InitResourceHandler[%04x]\n", hModule
);
223 while(pTypeInfo
->type_id
)
225 pTypeInfo
->resloader
= (DWORD
)&NE_DefResourceHandler
;
226 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
231 /***********************************************************************
232 * NE_SetResourceHandler
234 FARPROC32
NE_SetResourceHandler( HMODULE16 hModule
, SEGPTR typeId
,
235 FARPROC32 resourceHandler
)
237 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
238 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
239 FARPROC32 prevHandler
= NULL
;
243 pTypeInfo
= NE_FindTypeSection( pModule
, pTypeInfo
, typeId
);
246 prevHandler
= (FARPROC32
)pTypeInfo
->resloader
;
247 pTypeInfo
->resloader
= (DWORD
)resourceHandler
;
248 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
250 } while( pTypeInfo
);
254 /***********************************************************************
257 HRSRC16
NE_FindResource( HMODULE16 hModule
, SEGPTR typeId
, SEGPTR resId
)
259 NE_TYPEINFO
*pTypeInfo
;
262 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
263 if (!pModule
|| !pModule
->res_table
) return 0;
264 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
266 if (HIWORD(typeId
) || HIWORD(resId
))
268 DWORD id
= NE_FindNameTableId( pModule
, typeId
, resId
);
278 pTypeInfo
= NE_FindTypeSection( pModule
, pTypeInfo
, typeId
);
281 hRsrc
= NE_FindResourceFromType(pModule
, pTypeInfo
, resId
);
284 dprintf_resource( stddeb
, " Found id %08lx\n", resId
);
287 dprintf_resource( stddeb
, " Not found, going on\n" );
288 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
290 } while( pTypeInfo
);
292 dprintf_resource( stddeb
, "failed!\n");
297 /***********************************************************************
300 HGLOBAL16
NE_AllocResource( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
302 NE_NAMEINFO
*pNameInfo
=NULL
;
305 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
306 if (!pModule
|| !pModule
->res_table
) return 0;
307 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
309 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
311 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
312 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
313 return GLOBAL_Alloc( GMEM_FIXED
, size
, hModule
, FALSE
, FALSE
, FALSE
);
317 /***********************************************************************
320 int NE_AccessResource( HMODULE16 hModule
, HRSRC16 hRsrc
)
322 NE_NAMEINFO
*pNameInfo
=NULL
;
325 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
326 if (!pModule
|| !pModule
->res_table
) return -1;
328 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
331 if ((fd
= _lopen32( NE_MODULE_NAME(pModule
), OF_READ
)) != -1)
333 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
334 _llseek32( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
340 /***********************************************************************
343 DWORD
NE_SizeofResource( HMODULE16 hModule
, HRSRC16 hRsrc
)
345 NE_NAMEINFO
*pNameInfo
=NULL
;
348 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
349 if (!pModule
|| !pModule
->res_table
) return 0;
350 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
352 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
354 return (DWORD
)pNameInfo
->length
<< sizeShift
;
358 /***********************************************************************
361 HGLOBAL16
NE_LoadResource( HMODULE16 hModule
, HRSRC16 hRsrc
)
363 NE_TYPEINFO
*pTypeInfo
;
364 NE_NAMEINFO
*pNameInfo
= NULL
;
365 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
368 if (!hRsrc
|| !pModule
|| !pModule
->res_table
) return 0;
370 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
372 d
= pModule
->res_table
+ 2;
373 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
377 if (pTypeInfo
->type_id
== 0)
378 break; /* terminal entry */
379 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
382 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
384 pNameInfo
= (NE_NAMEINFO
*)(((char *)pModule
) + hRsrc
);
388 break; /* NE_NAMEINFO boundary mismatch */
390 pTypeInfo
= (NE_TYPEINFO
*)(((char *)pModule
) + d
);
395 RESOURCEHANDLER16 __r16loader
;
396 if (pNameInfo
->handle
397 && !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
400 dprintf_resource( stddeb
, " Already loaded, new count=%d\n",
405 if (pTypeInfo
->resloader
)
406 __r16loader
= (RESOURCEHANDLER16
)pTypeInfo
->resloader
;
407 else /* this is really bad */
409 fprintf( stderr
, "[%04x]: Missing resource handler!!!...\n", hModule
);
410 __r16loader
= NE_DefResourceHandler
;
413 /* Finally call resource loader */
415 if ((pNameInfo
->handle
= __r16loader(pNameInfo
->handle
, hModule
, hRsrc
)))
418 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
421 return pNameInfo
->handle
;
427 /***********************************************************************
430 SEGPTR
NE_LockResource( HMODULE16 hModule
, HGLOBAL16 handle
)
432 /* May need to reload the resource if discarded */
434 return (SEGPTR
)WIN16_GlobalLock16( handle
);
438 /***********************************************************************
441 BOOL32
NE_FreeResource( HMODULE16 hModule
, HGLOBAL16 handle
)
443 NE_TYPEINFO
*pTypeInfo
;
444 NE_NAMEINFO
*pNameInfo
;
447 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
448 if (!handle
|| !pModule
|| !pModule
->res_table
) return handle
;
449 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
450 while (pTypeInfo
->type_id
)
452 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
453 for (count
= pTypeInfo
->count
; count
> 0; count
--)
455 if (pNameInfo
->handle
== handle
)
457 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
458 if (pNameInfo
->usage
== 0)
460 GlobalFree16( pNameInfo
->handle
);
461 pNameInfo
->handle
= 0;
467 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;
470 dprintf_resource(stddeb
, "NE_FreeResource[%04x]: no intrinsic resource for %04x\n",
472 GlobalFree16( handle
); /* it could have been DirectResAlloc()'ed */