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"
24 #include "debugtools.h"
26 DEFAULT_DEBUG_CHANNEL(resource
)
28 #define NEXT_TYPEINFO(pTypeInfo) ((NE_TYPEINFO *)((char*)((pTypeInfo) + 1) + \
29 (pTypeInfo)->count * sizeof(NE_NAMEINFO)))
31 static FARPROC16 DefResourceHandlerProc
= (FARPROC16
)0xffffffff;
33 /***********************************************************************
36 * Find the type and resource id from their names.
37 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
39 static DWORD
NE_FindNameTableId( NE_MODULE
*pModule
, LPCSTR typeId
, LPCSTR resId
)
41 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
42 NE_NAMEINFO
*pNameInfo
;
48 for (; pTypeInfo
->type_id
!= 0;
49 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+1) +
50 pTypeInfo
->count
* sizeof(NE_NAMEINFO
)))
52 if (pTypeInfo
->type_id
!= 0x800f) continue;
53 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
54 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
56 TRACE("NameTable entry: type=%04x id=%04x\n",
57 pTypeInfo
->type_id
, pNameInfo
->id
);
58 handle
= LoadResource16( pModule
->self
,
59 (HRSRC16
)((int)pNameInfo
- (int)pModule
) );
60 for(p
= (WORD
*)LockResource16(handle
); p
&& *p
; p
= (WORD
*)((char*)p
+*p
))
62 TRACE(" type=%04x '%s' id=%04x '%s'\n",
63 p
[1], (char *)(p
+3), p
[2],
64 (char *)(p
+3)+strlen((char *)(p
+3))+1 );
65 /* Check for correct type */
69 if (!HIWORD(typeId
)) continue;
70 if (lstrcmpiA( typeId
,
71 (char *)(p
+ 3) )) continue;
73 else if (HIWORD(typeId
) || (((DWORD
)typeId
& ~0x8000)!= p
[1]))
76 /* Now check for the id */
80 if (!HIWORD(resId
)) continue;
82 (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
85 else if (HIWORD(resId
) || (((DWORD
)resId
& ~0x8000) != p
[2]))
88 /* If we get here, we've found the entry */
91 ret
= MAKELONG( p
[1], p
[2] );
94 FreeResource16( handle
);
101 /***********************************************************************
104 * Find header struct for a particular resource type.
106 NE_TYPEINFO
*NE_FindTypeSection( LPBYTE pResTab
,
107 NE_TYPEINFO
*pTypeInfo
, LPCSTR typeId
)
109 /* start from pTypeInfo */
111 if (HIWORD(typeId
) != 0) /* Named type */
114 BYTE len
= strlen( str
);
115 while (pTypeInfo
->type_id
)
117 if (!(pTypeInfo
->type_id
& 0x8000))
119 BYTE
*p
= pResTab
+ pTypeInfo
->type_id
;
120 if ((*p
== len
) && !lstrncmpiA( p
+1, str
, len
))
122 TRACE(" Found type '%s'\n", str
);
126 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
127 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
130 else /* Numeric type id */
132 WORD id
= LOWORD(typeId
) | 0x8000;
133 while (pTypeInfo
->type_id
)
135 if (pTypeInfo
->type_id
== id
)
137 TRACE(" Found type %04x\n", id
);
140 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
141 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
147 /***********************************************************************
148 * NE_FindResourceFromType
150 * Find a resource once the type info structure has been found.
152 NE_NAMEINFO
*NE_FindResourceFromType( LPBYTE pResTab
,
153 NE_TYPEINFO
*pTypeInfo
, LPCSTR resId
)
157 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
159 if (HIWORD(resId
) != 0) /* Named resource */
162 BYTE len
= strlen( str
);
163 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
165 if (pNameInfo
->id
& 0x8000) continue;
166 p
= pResTab
+ pNameInfo
->id
;
167 if ((*p
== len
) && !lstrncmpiA( p
+1, str
, len
))
171 else /* Numeric resource id */
173 WORD id
= LOWORD(resId
) | 0x8000;
174 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
175 if (pNameInfo
->id
== id
)
182 /***********************************************************************
183 * NE_DefResourceHandler
185 * This is the default LoadProc() function.
187 HGLOBAL16 WINAPI
NE_DefResourceHandler( HGLOBAL16 hMemObj
, HMODULE16 hModule
,
191 NE_MODULE
* pModule
= NE_GetPtr( hModule
);
192 if (pModule
&& (fd
= NE_OpenFile( pModule
)) >= 0)
195 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
196 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
198 TRACE("loading, pos=%d, len=%d\n",
199 (int)pNameInfo
->offset
<< sizeShift
,
200 (int)pNameInfo
->length
<< sizeShift
);
202 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
204 handle
= AllocResource16( hModule
, hRsrc
, 0 );
209 SetFilePointer( fd
, (int)pNameInfo
->offset
<< sizeShift
, NULL
, SEEK_SET
);
210 ReadFile( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
,
218 /***********************************************************************
219 * NE_InitResourceHandler
221 * Fill in 'resloader' fields in the resource table.
223 BOOL
NE_InitResourceHandler( HMODULE16 hModule
)
225 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
226 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
228 if ( DefResourceHandlerProc
== (FARPROC16
)0xffffffff )
230 HMODULE16 hModule
= GetModuleHandle16( "KERNEL" );
231 int ordinal
= hModule
? NE_GetOrdinal( hModule
, "DefResourceHandler" ) : 0;
234 DefResourceHandlerProc
= NE_GetEntryPointEx( hModule
, ordinal
, FALSE
);
236 DefResourceHandlerProc
= NULL
;
239 TRACE("InitResourceHandler[%04x]\n", hModule
);
241 while(pTypeInfo
->type_id
)
243 pTypeInfo
->resloader
= DefResourceHandlerProc
;
244 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
250 /**********************************************************************
251 * SetResourceHandler (KERNEL.43)
253 FARPROC16 WINAPI
SetResourceHandler16( HMODULE16 hModule
, SEGPTR typeId
,
254 FARPROC16 resourceHandler
)
256 FARPROC16 prevHandler
= NULL
;
257 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
258 LPBYTE pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
259 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)(pResTab
+ 2);
261 if (!pModule
|| !pModule
->res_table
) return NULL
;
263 TRACE("module=%04x type=%s\n",
264 hModule
, debugres_a(PTR_SEG_TO_LIN(typeId
)) );
268 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, PTR_SEG_TO_LIN(typeId
) )))
270 prevHandler
= pTypeInfo
->resloader
;
271 pTypeInfo
->resloader
= resourceHandler
;
272 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
278 /**********************************************************************
281 HRSRC16
NE_FindResource( NE_MODULE
*pModule
, LPCSTR name
, LPCSTR type
)
283 NE_TYPEINFO
*pTypeInfo
;
284 NE_NAMEINFO
*pNameInfo
;
287 if (!pModule
|| !pModule
->res_table
) return 0;
289 TRACE("module=%04x name=%s type=%s\n",
290 pModule
->self
, debugres_a(PTR_SEG_TO_LIN(name
)),
291 debugres_a(PTR_SEG_TO_LIN(type
)) );
293 if (HIWORD(name
)) /* Check for '#xxx' name */
297 if (!(name
= (LPCSTR
)atoi( ptr
+ 1 )))
299 WARN("Incorrect resource name: %s\n", ptr
);
304 if (HIWORD(type
)) /* Check for '#xxx' type */
308 if (!(type
= (LPCSTR
)atoi( ptr
+ 1 )))
310 WARN("Incorrect resource type: %s\n", ptr
);
315 if (HIWORD(type
) || HIWORD(name
))
317 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
320 type
= (LPCSTR
)(int)LOWORD(id
);
321 name
= (LPCSTR
)(int)HIWORD(id
);
325 pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
326 pTypeInfo
= (NE_TYPEINFO
*)( pResTab
+ 2 );
330 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, type
)))
332 if ((pNameInfo
= NE_FindResourceFromType( pResTab
, pTypeInfo
, name
)))
334 TRACE(" Found id %08lx\n", (DWORD
)name
);
335 return (HRSRC16
)( (int)pNameInfo
- (int)pModule
);
337 TRACE(" Not found, going on\n" );
338 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
346 /**********************************************************************
347 * AllocResource (KERNEL.66)
349 HGLOBAL16 WINAPI
AllocResource16( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
351 NE_NAMEINFO
*pNameInfo
=NULL
;
354 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
355 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return 0;
357 TRACE("module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
359 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
360 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
361 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
362 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
363 return GLOBAL_Alloc( GMEM_FIXED
, size
, hModule
, FALSE
, FALSE
, FALSE
);
367 /**********************************************************************
368 * DirectResAlloc (KERNEL.168)
370 * Check Schulman, p. 232 for details
372 HGLOBAL16 WINAPI
DirectResAlloc16( HINSTANCE16 hInstance
, WORD wType
,
375 TRACE("(%04x,%04x,%04x)\n",
376 hInstance
, wType
, wSize
);
377 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
378 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
379 CreateCursorIndirect. */
380 TRACE("(wType=%x)\n", wType
);
381 return GLOBAL_Alloc(GMEM_MOVEABLE
, wSize
, hInstance
, FALSE
, FALSE
, FALSE
);
385 /**********************************************************************
388 INT16
NE_AccessResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
392 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return -1;
394 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
396 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
398 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
399 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
400 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
406 /**********************************************************************
409 DWORD
NE_SizeofResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
411 NE_NAMEINFO
*pNameInfo
=NULL
;
414 if (!pModule
|| !pModule
->res_table
) return 0;
416 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
418 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
419 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
420 return (DWORD
)pNameInfo
->length
<< sizeShift
;
424 /**********************************************************************
427 HGLOBAL16
NE_LoadResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
429 NE_TYPEINFO
*pTypeInfo
;
430 NE_NAMEINFO
*pNameInfo
= NULL
;
433 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
434 if (!hRsrc
|| !pModule
|| !pModule
->res_table
) return 0;
436 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
438 d
= pModule
->res_table
+ 2;
439 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
442 if (pTypeInfo
->type_id
== 0)
443 break; /* terminal entry */
444 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
447 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
449 pNameInfo
= (NE_NAMEINFO
*)(((char *)pModule
) + hRsrc
);
453 break; /* NE_NAMEINFO boundary mismatch */
455 pTypeInfo
= (NE_TYPEINFO
*)(((char *)pModule
) + d
);
460 if (pNameInfo
->handle
461 && !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
464 TRACE(" Already loaded, new count=%d\n",
469 if ( pTypeInfo
->resloader
470 && pTypeInfo
->resloader
!= DefResourceHandlerProc
)
471 pNameInfo
->handle
= Callbacks
->CallResourceHandlerProc(
472 pTypeInfo
->resloader
, pNameInfo
->handle
, pModule
->self
, hRsrc
);
474 pNameInfo
->handle
= NE_DefResourceHandler(
475 pNameInfo
->handle
, pModule
->self
, hRsrc
);
477 if (pNameInfo
->handle
)
480 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
483 return pNameInfo
->handle
;
489 /**********************************************************************
492 BOOL16
NE_FreeResource( NE_MODULE
*pModule
, HGLOBAL16 handle
)
494 NE_TYPEINFO
*pTypeInfo
;
495 NE_NAMEINFO
*pNameInfo
;
498 if (!handle
|| !pModule
|| !pModule
->res_table
) return handle
;
500 TRACE("handle=%04x\n", handle
);
502 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
503 while (pTypeInfo
->type_id
)
505 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
506 for (count
= pTypeInfo
->count
; count
> 0; count
--)
508 if (pNameInfo
->handle
== handle
)
510 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
511 if (pNameInfo
->usage
== 0)
513 GlobalFree16( pNameInfo
->handle
);
514 pNameInfo
->handle
= 0;
515 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
521 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;