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>
17 #include "wine/winbase16.h"
23 #include "debugtools.h"
25 DEFAULT_DEBUG_CHANNEL(resource
)
27 #define NEXT_TYPEINFO(pTypeInfo) ((NE_TYPEINFO *)((char*)((pTypeInfo) + 1) + \
28 (pTypeInfo)->count * sizeof(NE_NAMEINFO)))
30 static FARPROC16 DefResourceHandlerProc
= (FARPROC16
)0xffffffff;
32 /***********************************************************************
35 * Find the type and resource id from their names.
36 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
38 static DWORD
NE_FindNameTableId( NE_MODULE
*pModule
, LPCSTR typeId
, LPCSTR resId
)
40 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
41 NE_NAMEINFO
*pNameInfo
;
47 for (; pTypeInfo
->type_id
!= 0;
48 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+1) +
49 pTypeInfo
->count
* sizeof(NE_NAMEINFO
)))
51 if (pTypeInfo
->type_id
!= 0x800f) continue;
52 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
53 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
55 TRACE("NameTable entry: type=%04x id=%04x\n",
56 pTypeInfo
->type_id
, pNameInfo
->id
);
57 handle
= LoadResource16( pModule
->self
,
58 (HRSRC16
)((int)pNameInfo
- (int)pModule
) );
59 for(p
= (WORD
*)LockResource16(handle
); p
&& *p
; p
= (WORD
*)((char*)p
+*p
))
61 TRACE(" type=%04x '%s' id=%04x '%s'\n",
62 p
[1], (char *)(p
+3), p
[2],
63 (char *)(p
+3)+strlen((char *)(p
+3))+1 );
64 /* Check for correct type */
68 if (!HIWORD(typeId
)) continue;
69 if (lstrcmpiA( typeId
,
70 (char *)(p
+ 3) )) continue;
72 else if (HIWORD(typeId
) || (((DWORD
)typeId
& ~0x8000)!= p
[1]))
75 /* Now check for the id */
79 if (!HIWORD(resId
)) continue;
81 (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
84 else if (HIWORD(resId
) || (((DWORD
)resId
& ~0x8000) != p
[2]))
87 /* If we get here, we've found the entry */
90 ret
= MAKELONG( p
[1], p
[2] );
93 FreeResource16( handle
);
100 /***********************************************************************
103 * Find header struct for a particular resource type.
105 NE_TYPEINFO
*NE_FindTypeSection( LPBYTE pResTab
,
106 NE_TYPEINFO
*pTypeInfo
, LPCSTR typeId
)
108 /* start from pTypeInfo */
110 if (HIWORD(typeId
) != 0) /* Named type */
113 BYTE len
= strlen( str
);
114 while (pTypeInfo
->type_id
)
116 if (!(pTypeInfo
->type_id
& 0x8000))
118 BYTE
*p
= pResTab
+ pTypeInfo
->type_id
;
119 if ((*p
== len
) && !lstrncmpiA( p
+1, str
, len
))
121 TRACE(" Found type '%s'\n", str
);
125 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
126 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
129 else /* Numeric type id */
131 WORD id
= LOWORD(typeId
) | 0x8000;
132 while (pTypeInfo
->type_id
)
134 if (pTypeInfo
->type_id
== id
)
136 TRACE(" Found type %04x\n", id
);
139 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
140 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
146 /***********************************************************************
147 * NE_FindResourceFromType
149 * Find a resource once the type info structure has been found.
151 NE_NAMEINFO
*NE_FindResourceFromType( LPBYTE pResTab
,
152 NE_TYPEINFO
*pTypeInfo
, LPCSTR resId
)
156 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
158 if (HIWORD(resId
) != 0) /* Named resource */
161 BYTE len
= strlen( str
);
162 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
164 if (pNameInfo
->id
& 0x8000) continue;
165 p
= pResTab
+ pNameInfo
->id
;
166 if ((*p
== len
) && !lstrncmpiA( p
+1, str
, len
))
170 else /* Numeric resource id */
172 WORD id
= LOWORD(resId
) | 0x8000;
173 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
174 if (pNameInfo
->id
== id
)
181 /***********************************************************************
182 * NE_DefResourceHandler
184 * This is the default LoadProc() function.
186 HGLOBAL16 WINAPI
NE_DefResourceHandler( HGLOBAL16 hMemObj
, HMODULE16 hModule
,
190 NE_MODULE
* pModule
= NE_GetPtr( hModule
);
191 if (pModule
&& (pModule
->flags
& NE_FFLAGS_BUILTIN
))
194 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
195 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
198 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
200 handle
= AllocResource16( hModule
, hRsrc
, 0 );
204 /* NOTE: hRsrcMap points to start of built-in resource data */
205 memcpy( GlobalLock16( handle
),
206 (char *)pModule
->hRsrcMap
+ (pNameInfo
->offset
<< sizeShift
),
207 pNameInfo
->length
<< sizeShift
);
211 if (pModule
&& (fd
= NE_OpenFile( pModule
)) >= 0)
214 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
215 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
217 TRACE("loading, pos=%d, len=%d\n",
218 (int)pNameInfo
->offset
<< sizeShift
,
219 (int)pNameInfo
->length
<< sizeShift
);
221 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
223 handle
= AllocResource16( hModule
, hRsrc
, 0 );
228 SetFilePointer( fd
, (int)pNameInfo
->offset
<< sizeShift
, NULL
, SEEK_SET
);
229 ReadFile( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
,
237 /***********************************************************************
238 * NE_InitResourceHandler
240 * Fill in 'resloader' fields in the resource table.
242 BOOL
NE_InitResourceHandler( HMODULE16 hModule
)
244 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
245 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
247 if ( DefResourceHandlerProc
== (FARPROC16
)0xffffffff )
249 HMODULE16 hModule
= GetModuleHandle16( "KERNEL" );
250 int ordinal
= hModule
? NE_GetOrdinal( hModule
, "DefResourceHandler" ) : 0;
253 DefResourceHandlerProc
= NE_GetEntryPointEx( hModule
, ordinal
, FALSE
);
255 DefResourceHandlerProc
= NULL
;
258 TRACE("InitResourceHandler[%04x]\n", hModule
);
260 while(pTypeInfo
->type_id
)
262 pTypeInfo
->resloader
= DefResourceHandlerProc
;
263 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
269 /**********************************************************************
270 * SetResourceHandler (KERNEL.43)
272 FARPROC16 WINAPI
SetResourceHandler16( HMODULE16 hModule
, SEGPTR typeId
,
273 FARPROC16 resourceHandler
)
275 FARPROC16 prevHandler
= NULL
;
276 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
277 LPBYTE pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
278 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)(pResTab
+ 2);
280 if (!pModule
|| !pModule
->res_table
) return NULL
;
282 TRACE("module=%04x type=%s\n",
283 hModule
, debugres_a(PTR_SEG_TO_LIN(typeId
)) );
287 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, PTR_SEG_TO_LIN(typeId
) )))
289 prevHandler
= pTypeInfo
->resloader
;
290 pTypeInfo
->resloader
= resourceHandler
;
291 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
297 /**********************************************************************
300 HRSRC16
NE_FindResource( NE_MODULE
*pModule
, LPCSTR name
, LPCSTR type
)
302 NE_TYPEINFO
*pTypeInfo
;
303 NE_NAMEINFO
*pNameInfo
;
306 if (!pModule
|| !pModule
->res_table
) return 0;
308 TRACE("module=%04x name=%s type=%s\n",
309 pModule
->self
, debugres_a(PTR_SEG_TO_LIN(name
)),
310 debugres_a(PTR_SEG_TO_LIN(type
)) );
312 if (HIWORD(name
)) /* Check for '#xxx' name */
316 if (!(name
= (LPCSTR
)atoi( ptr
+ 1 )))
318 WARN("Incorrect resource name: %s\n", ptr
);
323 if (HIWORD(type
)) /* Check for '#xxx' type */
327 if (!(type
= (LPCSTR
)atoi( ptr
+ 1 )))
329 WARN("Incorrect resource type: %s\n", ptr
);
334 if (HIWORD(type
) || HIWORD(name
))
336 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
339 type
= (LPCSTR
)(int)LOWORD(id
);
340 name
= (LPCSTR
)(int)HIWORD(id
);
344 pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
345 pTypeInfo
= (NE_TYPEINFO
*)( pResTab
+ 2 );
349 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, type
)))
351 if ((pNameInfo
= NE_FindResourceFromType( pResTab
, pTypeInfo
, name
)))
353 TRACE(" Found id %08lx\n", (DWORD
)name
);
354 return (HRSRC16
)( (int)pNameInfo
- (int)pModule
);
356 TRACE(" Not found, going on\n" );
357 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
365 /**********************************************************************
366 * AllocResource (KERNEL.66)
368 HGLOBAL16 WINAPI
AllocResource16( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
370 NE_NAMEINFO
*pNameInfo
=NULL
;
373 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
374 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return 0;
376 TRACE("module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
378 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
379 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
380 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
381 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
382 return GLOBAL_Alloc( GMEM_FIXED
, size
, hModule
, FALSE
, FALSE
, FALSE
);
386 /**********************************************************************
387 * DirectResAlloc (KERNEL.168)
389 * Check Schulman, p. 232 for details
391 HGLOBAL16 WINAPI
DirectResAlloc16( HINSTANCE16 hInstance
, WORD wType
,
394 TRACE("(%04x,%04x,%04x)\n",
395 hInstance
, wType
, wSize
);
396 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
397 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
398 CreateCursorIndirect. */
399 TRACE("(wType=%x)\n", wType
);
400 return GLOBAL_Alloc(GMEM_MOVEABLE
, wSize
, hInstance
, FALSE
, FALSE
, FALSE
);
404 /**********************************************************************
407 INT16
NE_AccessResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
411 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return -1;
413 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
415 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
417 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
418 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
419 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
425 /**********************************************************************
428 DWORD
NE_SizeofResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
430 NE_NAMEINFO
*pNameInfo
=NULL
;
433 if (!pModule
|| !pModule
->res_table
) return 0;
435 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
437 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
438 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
439 return (DWORD
)pNameInfo
->length
<< sizeShift
;
443 /**********************************************************************
446 HGLOBAL16
NE_LoadResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
448 NE_TYPEINFO
*pTypeInfo
;
449 NE_NAMEINFO
*pNameInfo
= NULL
;
452 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
453 if (!hRsrc
|| !pModule
|| !pModule
->res_table
) return 0;
455 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
457 d
= pModule
->res_table
+ 2;
458 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
461 if (pTypeInfo
->type_id
== 0)
462 break; /* terminal entry */
463 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
466 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
468 pNameInfo
= (NE_NAMEINFO
*)(((char *)pModule
) + hRsrc
);
472 break; /* NE_NAMEINFO boundary mismatch */
474 pTypeInfo
= (NE_TYPEINFO
*)(((char *)pModule
) + d
);
479 if (pNameInfo
->handle
480 && !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
483 TRACE(" Already loaded, new count=%d\n",
488 if ( pTypeInfo
->resloader
489 && pTypeInfo
->resloader
!= DefResourceHandlerProc
)
490 pNameInfo
->handle
= Callbacks
->CallResourceHandlerProc(
491 pTypeInfo
->resloader
, pNameInfo
->handle
, pModule
->self
, hRsrc
);
493 pNameInfo
->handle
= NE_DefResourceHandler(
494 pNameInfo
->handle
, pModule
->self
, hRsrc
);
496 if (pNameInfo
->handle
)
499 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
502 return pNameInfo
->handle
;
508 /**********************************************************************
511 BOOL16
NE_FreeResource( NE_MODULE
*pModule
, HGLOBAL16 handle
)
513 NE_TYPEINFO
*pTypeInfo
;
514 NE_NAMEINFO
*pNameInfo
;
517 if (!handle
|| !pModule
|| !pModule
->res_table
) return handle
;
519 TRACE("handle=%04x\n", handle
);
521 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
522 while (pTypeInfo
->type_id
)
524 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
525 for (count
= pTypeInfo
->count
; count
> 0; count
--)
527 if (pNameInfo
->handle
== handle
)
529 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
530 if (pNameInfo
->usage
== 0)
532 GlobalFree16( pNameInfo
->handle
);
533 pNameInfo
->handle
= 0;
534 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
540 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;