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>
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 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( (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 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
, 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 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
, 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_GetPtr16( 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 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 );
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_GetPtr16( hModule
);
219 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
221 TRACE(resource
,"InitResourceHandler[%04x]\n", hModule
);
223 while(pTypeInfo
->type_id
)
225 pTypeInfo
->resloader
= (FARPROC16
)&NE_DefResourceHandler
;
226 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
232 /**********************************************************************
233 * SetResourceHandler (KERNEL.43)
235 FARPROC16 WINAPI
SetResourceHandler( HMODULE16 hModule
, SEGPTR typeId
,
236 FARPROC16 resourceHandler
)
238 FARPROC16 prevHandler
= NULL
;
239 NE_MODULE
*pModule
= MODULE_GetPtr16( hModule
);
240 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
242 if (!pModule
|| !pModule
->res_table
) return NULL
;
244 TRACE( resource
, "module=%04x type=%s\n",
245 hModule
, debugres_a(PTR_SEG_TO_LIN(typeId
)) );
249 if (!(pTypeInfo
= NE_FindTypeSection( pModule
, pTypeInfo
, typeId
)))
251 prevHandler
= pTypeInfo
->resloader
;
252 pTypeInfo
->resloader
= resourceHandler
;
253 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
259 /**********************************************************************
260 * FindResource16 (KERNEL.60)
262 HRSRC16 WINAPI
FindResource16( HMODULE16 hModule
, SEGPTR name
, SEGPTR type
)
264 NE_TYPEINFO
*pTypeInfo
;
267 NE_MODULE
*pModule
= MODULE_GetPtr16( hModule
);
268 if (!pModule
|| !pModule
->res_table
) return 0;
270 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
272 TRACE( resource
, "module=%04x name=%s type=%s\n",
273 hModule
, debugres_a(PTR_SEG_TO_LIN(name
)),
274 debugres_a(PTR_SEG_TO_LIN(type
)) );
276 if (HIWORD(name
)) /* Check for '#xxx' name */
278 char *ptr
= PTR_SEG_TO_LIN( name
);
280 if (!(name
= (SEGPTR
)atoi( ptr
+ 1 )))
282 WARN(resource
, "Incorrect resource name: %s\n", ptr
);
287 if (HIWORD(type
)) /* Check for '#xxx' type */
289 char *ptr
= PTR_SEG_TO_LIN( type
);
291 if (!(type
= (SEGPTR
)atoi( ptr
+ 1 )))
293 WARN(resource
, "Incorrect resource type: %s\n", ptr
);
298 if (HIWORD(type
) || HIWORD(name
))
300 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
308 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
312 if (!(pTypeInfo
= NE_FindTypeSection( pModule
, pTypeInfo
, type
)))
314 if ((hRsrc
= NE_FindResourceFromType(pModule
, pTypeInfo
, name
)))
316 TRACE(resource
, " Found id %08lx\n", name
);
319 TRACE(resource
, " Not found, going on\n" );
320 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
323 WARN(resource
, "failed!\n");
328 /**********************************************************************
329 * AllocResource (KERNEL.66)
331 HGLOBAL16 WINAPI
AllocResource( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
333 NE_NAMEINFO
*pNameInfo
=NULL
;
336 NE_MODULE
*pModule
= MODULE_GetPtr16( hModule
);
337 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return 0;
339 TRACE( resource
, "module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
341 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
343 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
344 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
345 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
346 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
347 return GLOBAL_Alloc( GMEM_FIXED
, size
, hModule
, FALSE
, FALSE
, FALSE
);
351 /**********************************************************************
352 * DirectResAlloc (KERNEL.168)
354 * Check Schulman, p. 232 for details
356 HGLOBAL16 WINAPI
DirectResAlloc( HINSTANCE16 hInstance
, WORD wType
,
359 TRACE(resource
,"(%04x,%04x,%04x)\n",
360 hInstance
, wType
, wSize
);
361 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
362 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
363 CreateCursorIndirect. */
364 fprintf(stderr
, "DirectResAlloc: wType = %x\n", wType
);
365 return GLOBAL_Alloc(GMEM_MOVEABLE
, wSize
, hInstance
, FALSE
, FALSE
, FALSE
);
369 /**********************************************************************
370 * AccessResource16 (KERNEL.64)
372 INT16 WINAPI
AccessResource16( HINSTANCE16 hModule
, HRSRC16 hRsrc
)
376 NE_MODULE
*pModule
= MODULE_GetPtr16( hModule
);
377 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return -1;
379 TRACE(resource
, "module=%04x res=%04x\n", hModule
, hRsrc
);
381 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
383 if ((fd
= _lopen32( NE_MODULE_NAME(pModule
), OF_READ
)) != -1)
385 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
386 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
387 _llseek32( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
393 /**********************************************************************
394 * SizeofResource16 (KERNEL.65)
396 DWORD WINAPI
SizeofResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
398 NE_NAMEINFO
*pNameInfo
=NULL
;
401 NE_MODULE
*pModule
= MODULE_GetPtr16( hModule
);
402 if (!pModule
|| !pModule
->res_table
) return 0;
404 TRACE(resource
, "module=%04x res=%04x\n", hModule
, hRsrc
);
406 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
408 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
409 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
410 return (DWORD
)pNameInfo
->length
<< sizeShift
;
414 /**********************************************************************
415 * LoadResource16 (KERNEL.61)
417 HGLOBAL16 WINAPI
LoadResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
419 NE_TYPEINFO
*pTypeInfo
;
420 NE_NAMEINFO
*pNameInfo
= NULL
;
421 NE_MODULE
*pModule
= MODULE_GetPtr16( hModule
);
424 TRACE( resource
, "module=%04x res=%04x\n", hModule
, hRsrc
);
425 if (!hRsrc
|| !pModule
|| !pModule
->res_table
) return 0;
427 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
429 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
431 d
= pModule
->res_table
+ 2;
432 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
435 if (pTypeInfo
->type_id
== 0)
436 break; /* terminal entry */
437 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
440 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
442 pNameInfo
= (NE_NAMEINFO
*)(((char *)pModule
) + hRsrc
);
446 break; /* NE_NAMEINFO boundary mismatch */
448 pTypeInfo
= (NE_TYPEINFO
*)(((char *)pModule
) + d
);
453 RESOURCEHANDLER16 loader
;
454 if (pNameInfo
->handle
455 && !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
458 TRACE(resource
, " Already loaded, new count=%d\n",
463 if (pTypeInfo
->resloader
)
464 loader
= (RESOURCEHANDLER16
)pTypeInfo
->resloader
;
465 else /* this is really bad */
467 fprintf( stderr
, "[%04x]: Missing resource handler!!!...\n", hModule
);
468 loader
= NE_DefResourceHandler
;
471 /* Finally call resource loader */
473 if ((pNameInfo
->handle
= loader(pNameInfo
->handle
, hModule
, hRsrc
)))
476 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
479 return pNameInfo
->handle
;
485 /**********************************************************************
486 * LockResource16 (KERNEL.62)
489 SEGPTR WINAPI
WIN16_LockResource16( HGLOBAL16 handle
)
491 TRACE( resource
, "handle=%04x\n", handle
);
492 if (!handle
) return (SEGPTR
)0;
494 /* May need to reload the resource if discarded */
496 return (SEGPTR
)WIN16_GlobalLock16( handle
);
499 /* Winelib 16-bit version */
500 LPVOID WINAPI
LockResource16( HGLOBAL16 handle
)
502 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
504 return (LPVOID
)PTR_SEG_TO_LIN( WIN16_LockResource16( handle
) );
508 /**********************************************************************
509 * FreeResource16 (KERNEL.63)
511 BOOL16 WINAPI
FreeResource16( HGLOBAL16 handle
)
513 NE_TYPEINFO
*pTypeInfo
;
514 NE_NAMEINFO
*pNameInfo
;
516 HMODULE16 hModule
= GetExePtr( handle
);
517 NE_MODULE
*pModule
= MODULE_GetPtr16( hModule
);
519 if (!handle
|| !pModule
|| !pModule
->res_table
) return handle
;
521 TRACE(resource
, "handle=%04x\n", handle
);
523 assert( !__winelib
); /* Can't use Win16 resource functions in Winelib */
525 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
526 while (pTypeInfo
->type_id
)
528 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
529 for (count
= pTypeInfo
->count
; count
> 0; count
--)
531 if (pNameInfo
->handle
== handle
)
533 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
534 if (pNameInfo
->usage
== 0)
536 GlobalFree16( pNameInfo
->handle
);
537 pNameInfo
->handle
= 0;
538 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
544 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;
547 TRACE(resource
, "[%04x]: no intrinsic resource for %04x, assuming DirectResAlloc()!\n",
549 GlobalFree16( handle
);