2 * NE resource functions
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
6 * Copyright 1997 Alex Korobka
13 #include <sys/types.h>
26 #define NEXT_TYPEINFO(pTypeInfo) ((NE_TYPEINFO *)((char*)((pTypeInfo) + 1) + \
27 (pTypeInfo)->count * sizeof(NE_NAMEINFO)))
29 /***********************************************************************
32 * Find the type and resource id from their names.
33 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
35 static DWORD
NE_FindNameTableId( NE_MODULE
*pModule
, SEGPTR typeId
, SEGPTR resId
)
37 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
38 NE_NAMEINFO
*pNameInfo
;
44 for (; pTypeInfo
->type_id
!= 0;
45 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+1) +
46 pTypeInfo
->count
* sizeof(NE_NAMEINFO
)))
48 if (pTypeInfo
->type_id
!= 0x800f) continue;
49 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
50 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
52 TRACE(resource
, "NameTable entry: type=%04x id=%04x\n",
53 pTypeInfo
->type_id
, pNameInfo
->id
);
54 handle
= LoadResource16( pModule
->self
,
55 (HRSRC16
)((int)pNameInfo
- (int)pModule
) );
56 for(p
= (WORD
*)LockResource16(handle
); p
&& *p
; p
= (WORD
*)((char*)p
+*p
))
58 TRACE(resource
," type=%04x '%s' id=%04x '%s'\n",
59 p
[1], (char *)(p
+3), p
[2],
60 (char *)(p
+3)+strlen((char *)(p
+3))+1 );
61 /* Check for correct type */
65 if (!HIWORD(typeId
)) continue;
66 if (lstrcmpi32A( (char *)PTR_SEG_TO_LIN(typeId
),
67 (char *)(p
+ 3) )) continue;
69 else if (HIWORD(typeId
) || ((typeId
& ~0x8000)!= p
[1]))
72 /* Now check for the id */
76 if (!HIWORD(resId
)) continue;
77 if (lstrcmpi32A( (char *)PTR_SEG_TO_LIN(resId
),
78 (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
81 else if (HIWORD(resId
) || ((resId
& ~0x8000) != p
[2]))
84 /* If we get here, we've found the entry */
86 TRACE(resource
, " Found!\n" );
87 ret
= MAKELONG( p
[1], p
[2] );
90 FreeResource16( handle
);
97 /***********************************************************************
100 * Find header struct for a particular resource type.
102 static NE_TYPEINFO
* NE_FindTypeSection( NE_MODULE
*pModule
,
103 NE_TYPEINFO
*pTypeInfo
, SEGPTR typeId
)
105 /* start from pTypeInfo */
107 if (HIWORD(typeId
) != 0) /* Named type */
109 char *str
= (char *)PTR_SEG_TO_LIN( typeId
);
110 BYTE len
= strlen( str
);
111 while (pTypeInfo
->type_id
)
113 if (!(pTypeInfo
->type_id
& 0x8000))
115 BYTE
*p
= (BYTE
*)pModule
+ pModule
->res_table
+ pTypeInfo
->type_id
;
116 if ((*p
== len
) && !lstrncmpi32A( p
+1, str
, len
))
118 TRACE(resource
, " Found type '%s'\n", str
);
122 TRACE(resource
, " Skipping type %04x\n", pTypeInfo
->type_id
);
123 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
126 else /* Numeric type id */
128 WORD id
= LOWORD(typeId
) | 0x8000;
129 while (pTypeInfo
->type_id
)
131 if (pTypeInfo
->type_id
== id
)
133 TRACE(resource
, " Found type %04x\n", id
);
136 TRACE(resource
, " Skipping type %04x\n", pTypeInfo
->type_id
);
137 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
143 /***********************************************************************
144 * NE_FindResourceFromType
146 * Find a resource once the type info structure has been found.
148 static HRSRC16
NE_FindResourceFromType( NE_MODULE
*pModule
,
149 NE_TYPEINFO
*pTypeInfo
, SEGPTR resId
)
153 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
155 if (HIWORD(resId
) != 0) /* Named resource */
157 char *str
= (char *)PTR_SEG_TO_LIN( resId
);
158 BYTE len
= strlen( str
);
159 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
161 if (pNameInfo
->id
& 0x8000) continue;
162 p
= (BYTE
*)pModule
+ pModule
->res_table
+ pNameInfo
->id
;
163 if ((*p
== len
) && !lstrncmpi32A( p
+1, str
, len
))
164 return (HRSRC16
)((int)pNameInfo
- (int)pModule
);
167 else /* Numeric resource id */
169 WORD id
= LOWORD(resId
) | 0x8000;
170 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
171 if (pNameInfo
->id
== id
)
172 return (HRSRC16
)((int)pNameInfo
- (int)pModule
);
178 /***********************************************************************
179 * NE_DefResourceHandler
181 * This is the default LoadProc() function.
183 HGLOBAL16 WINAPI
NE_DefResourceHandler( HGLOBAL16 hMemObj
, HMODULE16 hModule
,
187 NE_MODULE
* pModule
= NE_GetPtr( hModule
);
188 if (pModule
&& (fd
= NE_OpenFile( pModule
)) >= 0)
191 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
192 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
194 TRACE(resource
, "loading, pos=%d, len=%d\n",
195 (int)pNameInfo
->offset
<< sizeShift
,
196 (int)pNameInfo
->length
<< sizeShift
);
198 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
200 handle
= AllocResource( hModule
, hRsrc
, 0 );
204 lseek( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
205 read( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
);
212 /***********************************************************************
213 * NE_InitResourceHandler
215 * Fill in 'resloader' fields in the resource table.
217 BOOL32
NE_InitResourceHandler( HMODULE16 hModule
)
219 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
220 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
222 FARPROC16 handler
= MODULE_GetWndProcEntry16("DefResourceHandler");
224 TRACE(resource
,"InitResourceHandler[%04x]\n", hModule
);
226 while(pTypeInfo
->type_id
)
228 pTypeInfo
->resloader
= handler
;
229 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
235 /**********************************************************************
236 * SetResourceHandler (KERNEL.43)
238 FARPROC16 WINAPI
SetResourceHandler( HMODULE16 hModule
, SEGPTR typeId
,
239 FARPROC16 resourceHandler
)
241 FARPROC16 prevHandler
= NULL
;
242 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
243 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
245 if (!pModule
|| !pModule
->res_table
) return NULL
;
247 TRACE( resource
, "module=%04x type=%s\n",
248 hModule
, debugres_a(PTR_SEG_TO_LIN(typeId
)) );
252 if (!(pTypeInfo
= NE_FindTypeSection( pModule
, pTypeInfo
, typeId
)))
254 prevHandler
= pTypeInfo
->resloader
;
255 pTypeInfo
->resloader
= resourceHandler
;
256 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
262 /**********************************************************************
263 * FindResource16 (KERNEL.60)
265 HRSRC16 WINAPI
FindResource16( HMODULE16 hModule
, SEGPTR name
, SEGPTR type
)
267 NE_TYPEINFO
*pTypeInfo
;
270 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
271 if (!pModule
|| !pModule
->res_table
) return 0;
273 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
275 TRACE( resource
, "module=%04x name=%s type=%s\n",
276 hModule
, debugres_a(PTR_SEG_TO_LIN(name
)),
277 debugres_a(PTR_SEG_TO_LIN(type
)) );
279 if (HIWORD(name
)) /* Check for '#xxx' name */
281 char *ptr
= PTR_SEG_TO_LIN( name
);
283 if (!(name
= (SEGPTR
)atoi( ptr
+ 1 )))
285 WARN(resource
, "Incorrect resource name: %s\n", ptr
);
290 if (HIWORD(type
)) /* Check for '#xxx' type */
292 char *ptr
= PTR_SEG_TO_LIN( type
);
294 if (!(type
= (SEGPTR
)atoi( ptr
+ 1 )))
296 WARN(resource
, "Incorrect resource type: %s\n", ptr
);
301 if (HIWORD(type
) || HIWORD(name
))
303 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
311 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
315 if (!(pTypeInfo
= NE_FindTypeSection( pModule
, pTypeInfo
, type
)))
317 if ((hRsrc
= NE_FindResourceFromType(pModule
, pTypeInfo
, name
)))
319 TRACE(resource
, " Found id %08lx\n", name
);
322 TRACE(resource
, " Not found, going on\n" );
323 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
326 WARN(resource
, "failed!\n");
331 /**********************************************************************
332 * AllocResource (KERNEL.66)
334 HGLOBAL16 WINAPI
AllocResource( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
336 NE_NAMEINFO
*pNameInfo
=NULL
;
339 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
340 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return 0;
342 TRACE( resource
, "module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
344 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
346 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
347 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
348 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
349 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
350 return GLOBAL_Alloc( GMEM_FIXED
, size
, hModule
, FALSE
, FALSE
, FALSE
);
354 /**********************************************************************
355 * DirectResAlloc (KERNEL.168)
357 * Check Schulman, p. 232 for details
359 HGLOBAL16 WINAPI
DirectResAlloc( HINSTANCE16 hInstance
, WORD wType
,
362 TRACE(resource
,"(%04x,%04x,%04x)\n",
363 hInstance
, wType
, wSize
);
364 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
365 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
366 CreateCursorIndirect. */
367 TRACE(resource
, "(wType=%x)\n", wType
);
368 return GLOBAL_Alloc(GMEM_MOVEABLE
, wSize
, hInstance
, FALSE
, FALSE
, FALSE
);
372 /**********************************************************************
373 * AccessResource16 (KERNEL.64)
375 INT16 WINAPI
AccessResource16( HINSTANCE16 hModule
, HRSRC16 hRsrc
)
379 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
380 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return -1;
382 TRACE(resource
, "module=%04x res=%04x\n", hModule
, hRsrc
);
384 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
386 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
388 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
389 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
390 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
396 /**********************************************************************
397 * SizeofResource16 (KERNEL.65)
399 DWORD WINAPI
SizeofResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
401 NE_NAMEINFO
*pNameInfo
=NULL
;
404 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
405 if (!pModule
|| !pModule
->res_table
) return 0;
407 TRACE(resource
, "module=%04x res=%04x\n", hModule
, hRsrc
);
409 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
411 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
412 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
413 return (DWORD
)pNameInfo
->length
<< sizeShift
;
417 /**********************************************************************
418 * LoadResource16 (KERNEL.61)
420 HGLOBAL16 WINAPI
LoadResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
422 NE_TYPEINFO
*pTypeInfo
;
423 NE_NAMEINFO
*pNameInfo
= NULL
;
424 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
427 TRACE( resource
, "module=%04x res=%04x\n", hModule
, hRsrc
);
428 if (!hRsrc
|| !pModule
|| !pModule
->res_table
) return 0;
430 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
432 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
434 d
= pModule
->res_table
+ 2;
435 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
438 if (pTypeInfo
->type_id
== 0)
439 break; /* terminal entry */
440 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
443 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
445 pNameInfo
= (NE_NAMEINFO
*)(((char *)pModule
) + hRsrc
);
449 break; /* NE_NAMEINFO boundary mismatch */
451 pTypeInfo
= (NE_TYPEINFO
*)(((char *)pModule
) + d
);
456 if (pNameInfo
->handle
457 && !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
460 TRACE(resource
, " Already loaded, new count=%d\n",
465 if (pTypeInfo
->resloader
)
466 pNameInfo
->handle
= Callbacks
->CallResourceHandlerProc(
467 pTypeInfo
->resloader
, pNameInfo
->handle
, hModule
, hRsrc
);
468 else /* this is really bad */
470 ERR(resource
, "[%04x]: Missing resource handler!\n", hModule
);
471 pNameInfo
->handle
= NE_DefResourceHandler(
472 pNameInfo
->handle
, hModule
, hRsrc
);
475 if (pNameInfo
->handle
)
478 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
481 return pNameInfo
->handle
;
487 /**********************************************************************
488 * LockResource16 (KERNEL.62)
491 SEGPTR WINAPI
WIN16_LockResource16( HGLOBAL16 handle
)
493 TRACE( resource
, "handle=%04x\n", handle
);
494 if (!handle
) return (SEGPTR
)0;
496 /* May need to reload the resource if discarded */
498 return (SEGPTR
)WIN16_GlobalLock16( handle
);
501 /* Winelib 16-bit version */
502 LPVOID WINAPI
LockResource16( HGLOBAL16 handle
)
504 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
506 return (LPVOID
)PTR_SEG_TO_LIN( WIN16_LockResource16( handle
) );
510 /**********************************************************************
511 * FreeResource16 (KERNEL.63)
513 BOOL16 WINAPI
FreeResource16( HGLOBAL16 handle
)
515 NE_TYPEINFO
*pTypeInfo
;
516 NE_NAMEINFO
*pNameInfo
;
518 NE_MODULE
*pModule
= NE_GetPtr( FarGetOwner(handle
) );
520 if (!handle
|| !pModule
|| !pModule
->res_table
) return handle
;
522 TRACE(resource
, "handle=%04x\n", handle
);
524 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
526 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
527 while (pTypeInfo
->type_id
)
529 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
530 for (count
= pTypeInfo
->count
; count
> 0; count
--)
532 if (pNameInfo
->handle
== handle
)
534 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
535 if (pNameInfo
->usage
== 0)
537 GlobalFree16( pNameInfo
->handle
);
538 pNameInfo
->handle
= 0;
539 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
545 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;
548 TRACE(resource
, "[%04x]: no intrinsic resource for %04x, assuming DirectResAlloc()!\n",
549 pModule
->self
, handle
);
550 GlobalFree16( handle
);