2 * NE resource functions
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
6 * Copyright 1997 Alex Korobka
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
, LPCSTR typeId
, LPCSTR 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 TRACE(resource
, "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 TRACE(resource
," 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( typeId
,
66 (char *)(p
+ 3) )) continue;
68 else if (HIWORD(typeId
) || (((DWORD
)typeId
& ~0x8000)!= p
[1]))
71 /* Now check for the id */
75 if (!HIWORD(resId
)) continue;
76 if (lstrcmpi32A( resId
,
77 (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
80 else if (HIWORD(resId
) || (((DWORD
)resId
& ~0x8000) != p
[2]))
83 /* If we get here, we've found the entry */
85 TRACE(resource
, " 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
, LPCSTR typeId
)
104 /* start from pTypeInfo */
106 if (HIWORD(typeId
) != 0) /* Named type */
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 TRACE(resource
, " Found type '%s'\n", str
);
121 TRACE(resource
, " 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 TRACE(resource
, " Found type %04x\n", id
);
135 TRACE(resource
, " 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
, LPCSTR resId
)
152 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
154 if (HIWORD(resId
) != 0) /* Named resource */
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
= NE_GetPtr( hModule
);
187 if (pModule
&& (fd
= NE_OpenFile( pModule
)) >= 0)
190 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
191 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
193 TRACE(resource
, "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
= AllocResource( hModule
, hRsrc
, 0 );
204 SetFilePointer( fd
, (int)pNameInfo
->offset
<< sizeShift
, NULL
, SEEK_SET
);
205 ReadFile( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
,
213 /***********************************************************************
214 * NE_InitResourceHandler
216 * Fill in 'resloader' fields in the resource table.
218 BOOL32
NE_InitResourceHandler( HMODULE16 hModule
)
220 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
221 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
223 FARPROC16 handler
= MODULE_GetWndProcEntry16("DefResourceHandler");
225 TRACE(resource
,"InitResourceHandler[%04x]\n", hModule
);
227 while(pTypeInfo
->type_id
)
229 pTypeInfo
->resloader
= handler
;
230 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
236 /**********************************************************************
237 * SetResourceHandler (KERNEL.43)
239 FARPROC16 WINAPI
SetResourceHandler( HMODULE16 hModule
, SEGPTR typeId
,
240 FARPROC16 resourceHandler
)
242 FARPROC16 prevHandler
= NULL
;
243 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
244 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
246 if (!pModule
|| !pModule
->res_table
) return NULL
;
248 TRACE( resource
, "module=%04x type=%s\n",
249 hModule
, debugres_a(PTR_SEG_TO_LIN(typeId
)) );
253 if (!(pTypeInfo
= NE_FindTypeSection( pModule
, pTypeInfo
, PTR_SEG_TO_LIN(typeId
) )))
255 prevHandler
= pTypeInfo
->resloader
;
256 pTypeInfo
->resloader
= resourceHandler
;
257 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
263 /**********************************************************************
266 HRSRC16
NE_FindResource( NE_MODULE
*pModule
, LPCSTR name
, LPCSTR type
)
268 NE_TYPEINFO
*pTypeInfo
;
271 if (!pModule
|| !pModule
->res_table
) return 0;
273 TRACE( resource
, "module=%04x name=%s type=%s\n",
274 pModule
->self
, debugres_a(PTR_SEG_TO_LIN(name
)),
275 debugres_a(PTR_SEG_TO_LIN(type
)) );
277 if (HIWORD(name
)) /* Check for '#xxx' name */
281 if (!(name
= (LPCSTR
)atoi( ptr
+ 1 )))
283 WARN(resource
, "Incorrect resource name: %s\n", ptr
);
288 if (HIWORD(type
)) /* Check for '#xxx' type */
292 if (!(type
= (LPCSTR
)atoi( ptr
+ 1 )))
294 WARN(resource
, "Incorrect resource type: %s\n", ptr
);
299 if (HIWORD(type
) || HIWORD(name
))
301 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
304 type
= (LPCSTR
)(int)LOWORD(id
);
305 name
= (LPCSTR
)(int)HIWORD(id
);
309 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
313 if (!(pTypeInfo
= NE_FindTypeSection( pModule
, pTypeInfo
, type
)))
315 if ((hRsrc
= NE_FindResourceFromType(pModule
, pTypeInfo
, name
)))
317 TRACE(resource
, " Found id %08lx\n", (DWORD
)name
);
320 TRACE(resource
, " Not found, going on\n" );
321 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
324 WARN(resource
, "failed!\n");
329 /**********************************************************************
330 * AllocResource (KERNEL.66)
332 HGLOBAL16 WINAPI
AllocResource( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
334 NE_NAMEINFO
*pNameInfo
=NULL
;
337 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
338 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return 0;
340 TRACE( resource
, "module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
342 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
343 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
344 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
345 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
346 return GLOBAL_Alloc( GMEM_FIXED
, size
, hModule
, FALSE
, FALSE
, FALSE
);
350 /**********************************************************************
351 * DirectResAlloc (KERNEL.168)
353 * Check Schulman, p. 232 for details
355 HGLOBAL16 WINAPI
DirectResAlloc( HINSTANCE16 hInstance
, WORD wType
,
358 TRACE(resource
,"(%04x,%04x,%04x)\n",
359 hInstance
, wType
, wSize
);
360 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
361 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
362 CreateCursorIndirect. */
363 TRACE(resource
, "(wType=%x)\n", wType
);
364 return GLOBAL_Alloc(GMEM_MOVEABLE
, wSize
, hInstance
, FALSE
, FALSE
, FALSE
);
368 /**********************************************************************
371 INT16
NE_AccessResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
375 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return -1;
377 TRACE(resource
, "module=%04x res=%04x\n", pModule
->self
, hRsrc
);
379 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
381 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
382 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
383 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
389 /**********************************************************************
392 DWORD
NE_SizeofResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
394 NE_NAMEINFO
*pNameInfo
=NULL
;
397 if (!pModule
|| !pModule
->res_table
) return 0;
399 TRACE(resource
, "module=%04x res=%04x\n", pModule
->self
, hRsrc
);
401 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
402 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
403 return (DWORD
)pNameInfo
->length
<< sizeShift
;
407 /**********************************************************************
410 HGLOBAL16
NE_LoadResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
412 NE_TYPEINFO
*pTypeInfo
;
413 NE_NAMEINFO
*pNameInfo
= NULL
;
416 TRACE( resource
, "module=%04x res=%04x\n", pModule
->self
, hRsrc
);
417 if (!hRsrc
|| !pModule
|| !pModule
->res_table
) return 0;
419 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
421 d
= pModule
->res_table
+ 2;
422 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
425 if (pTypeInfo
->type_id
== 0)
426 break; /* terminal entry */
427 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
430 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
432 pNameInfo
= (NE_NAMEINFO
*)(((char *)pModule
) + hRsrc
);
436 break; /* NE_NAMEINFO boundary mismatch */
438 pTypeInfo
= (NE_TYPEINFO
*)(((char *)pModule
) + d
);
443 if (pNameInfo
->handle
444 && !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
447 TRACE(resource
, " Already loaded, new count=%d\n",
452 if (pTypeInfo
->resloader
)
453 pNameInfo
->handle
= Callbacks
->CallResourceHandlerProc(
454 pTypeInfo
->resloader
, pNameInfo
->handle
, pModule
->self
, hRsrc
);
455 else /* this is really bad */
457 ERR(resource
, "[%04x]: Missing resource handler!\n", pModule
->self
);
458 pNameInfo
->handle
= NE_DefResourceHandler(
459 pNameInfo
->handle
, pModule
->self
, hRsrc
);
462 if (pNameInfo
->handle
)
465 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
468 return pNameInfo
->handle
;
474 /**********************************************************************
477 BOOL16
NE_FreeResource( NE_MODULE
*pModule
, HGLOBAL16 handle
)
479 NE_TYPEINFO
*pTypeInfo
;
480 NE_NAMEINFO
*pNameInfo
;
483 if (!handle
|| !pModule
|| !pModule
->res_table
) return handle
;
485 TRACE(resource
, "handle=%04x\n", handle
);
487 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
488 while (pTypeInfo
->type_id
)
490 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
491 for (count
= pTypeInfo
->count
; count
> 0; count
--)
493 if (pNameInfo
->handle
== handle
)
495 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
496 if (pNameInfo
->usage
== 0)
498 GlobalFree16( pNameInfo
->handle
);
499 pNameInfo
->handle
= 0;
500 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
506 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;
509 TRACE(resource
, "[%04x]: no intrinsic resource for %04x, assuming DirectResAlloc()!\n",
510 pModule
->self
, handle
);
511 GlobalFree16( handle
);