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"
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
, LPCSTR typeId
, LPCSTR 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 (lstrcmpiA( typeId
,
67 (char *)(p
+ 3) )) continue;
69 else if (HIWORD(typeId
) || (((DWORD
)typeId
& ~0x8000)!= p
[1]))
72 /* Now check for the id */
76 if (!HIWORD(resId
)) continue;
78 (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
81 else if (HIWORD(resId
) || (((DWORD
)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 NE_TYPEINFO
*NE_FindTypeSection( LPBYTE pResTab
,
103 NE_TYPEINFO
*pTypeInfo
, LPCSTR typeId
)
105 /* start from pTypeInfo */
107 if (HIWORD(typeId
) != 0) /* Named type */
110 BYTE len
= strlen( str
);
111 while (pTypeInfo
->type_id
)
113 if (!(pTypeInfo
->type_id
& 0x8000))
115 BYTE
*p
= pResTab
+ pTypeInfo
->type_id
;
116 if ((*p
== len
) && !lstrncmpiA( 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 NE_NAMEINFO
*NE_FindResourceFromType( LPBYTE pResTab
,
149 NE_TYPEINFO
*pTypeInfo
, LPCSTR resId
)
153 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
155 if (HIWORD(resId
) != 0) /* Named resource */
158 BYTE len
= strlen( str
);
159 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
161 if (pNameInfo
->id
& 0x8000) continue;
162 p
= pResTab
+ pNameInfo
->id
;
163 if ((*p
== len
) && !lstrncmpiA( p
+1, str
, len
))
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
)
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
= AllocResource16( hModule
, hRsrc
, 0 );
205 SetFilePointer( fd
, (int)pNameInfo
->offset
<< sizeShift
, NULL
, SEEK_SET
);
206 ReadFile( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
,
214 /***********************************************************************
215 * NE_InitResourceHandler
217 * Fill in 'resloader' fields in the resource table.
219 BOOL
NE_InitResourceHandler( HMODULE16 hModule
)
221 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
222 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
224 FARPROC16 handler
= MODULE_GetWndProcEntry16("DefResourceHandler");
226 TRACE(resource
,"InitResourceHandler[%04x]\n", hModule
);
228 while(pTypeInfo
->type_id
)
230 pTypeInfo
->resloader
= handler
;
231 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
237 /**********************************************************************
238 * SetResourceHandler (KERNEL.43)
240 FARPROC16 WINAPI
SetResourceHandler16( HMODULE16 hModule
, SEGPTR typeId
,
241 FARPROC16 resourceHandler
)
243 FARPROC16 prevHandler
= NULL
;
244 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
245 LPBYTE pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
246 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)(pResTab
+ 2);
248 if (!pModule
|| !pModule
->res_table
) return NULL
;
250 TRACE( resource
, "module=%04x type=%s\n",
251 hModule
, debugres_a(PTR_SEG_TO_LIN(typeId
)) );
255 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, PTR_SEG_TO_LIN(typeId
) )))
257 prevHandler
= pTypeInfo
->resloader
;
258 pTypeInfo
->resloader
= resourceHandler
;
259 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
265 /**********************************************************************
268 HRSRC16
NE_FindResource( NE_MODULE
*pModule
, LPCSTR name
, LPCSTR type
)
270 NE_TYPEINFO
*pTypeInfo
;
271 NE_NAMEINFO
*pNameInfo
;
274 if (!pModule
|| !pModule
->res_table
) return 0;
276 TRACE( resource
, "module=%04x name=%s type=%s\n",
277 pModule
->self
, debugres_a(PTR_SEG_TO_LIN(name
)),
278 debugres_a(PTR_SEG_TO_LIN(type
)) );
280 if (HIWORD(name
)) /* Check for '#xxx' name */
284 if (!(name
= (LPCSTR
)atoi( ptr
+ 1 )))
286 WARN(resource
, "Incorrect resource name: %s\n", ptr
);
291 if (HIWORD(type
)) /* Check for '#xxx' type */
295 if (!(type
= (LPCSTR
)atoi( ptr
+ 1 )))
297 WARN(resource
, "Incorrect resource type: %s\n", ptr
);
302 if (HIWORD(type
) || HIWORD(name
))
304 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
307 type
= (LPCSTR
)(int)LOWORD(id
);
308 name
= (LPCSTR
)(int)HIWORD(id
);
312 pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
313 pTypeInfo
= (NE_TYPEINFO
*)( pResTab
+ 2 );
317 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, type
)))
319 if ((pNameInfo
= NE_FindResourceFromType( pResTab
, pTypeInfo
, name
)))
321 TRACE(resource
, " Found id %08lx\n", (DWORD
)name
);
322 return (HRSRC16
)( (int)pNameInfo
- (int)pModule
);
324 TRACE(resource
, " Not found, going on\n" );
325 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
328 WARN(resource
, "failed!\n");
333 /**********************************************************************
334 * AllocResource (KERNEL.66)
336 HGLOBAL16 WINAPI
AllocResource16( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
338 NE_NAMEINFO
*pNameInfo
=NULL
;
341 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
342 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return 0;
344 TRACE( resource
, "module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
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
DirectResAlloc16( 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 /**********************************************************************
375 INT16
NE_AccessResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
379 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return -1;
381 TRACE(resource
, "module=%04x res=%04x\n", pModule
->self
, hRsrc
);
383 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
385 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
386 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
387 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
393 /**********************************************************************
396 DWORD
NE_SizeofResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
398 NE_NAMEINFO
*pNameInfo
=NULL
;
401 if (!pModule
|| !pModule
->res_table
) return 0;
403 TRACE(resource
, "module=%04x res=%04x\n", pModule
->self
, hRsrc
);
405 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
406 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
407 return (DWORD
)pNameInfo
->length
<< sizeShift
;
411 /**********************************************************************
414 HGLOBAL16
NE_LoadResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
416 NE_TYPEINFO
*pTypeInfo
;
417 NE_NAMEINFO
*pNameInfo
= NULL
;
420 TRACE( resource
, "module=%04x res=%04x\n", pModule
->self
, hRsrc
);
421 if (!hRsrc
|| !pModule
|| !pModule
->res_table
) return 0;
423 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
425 d
= pModule
->res_table
+ 2;
426 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
429 if (pTypeInfo
->type_id
== 0)
430 break; /* terminal entry */
431 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
434 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
436 pNameInfo
= (NE_NAMEINFO
*)(((char *)pModule
) + hRsrc
);
440 break; /* NE_NAMEINFO boundary mismatch */
442 pTypeInfo
= (NE_TYPEINFO
*)(((char *)pModule
) + d
);
447 if (pNameInfo
->handle
448 && !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
451 TRACE(resource
, " Already loaded, new count=%d\n",
456 if (pTypeInfo
->resloader
)
457 pNameInfo
->handle
= Callbacks
->CallResourceHandlerProc(
458 pTypeInfo
->resloader
, pNameInfo
->handle
, pModule
->self
, hRsrc
);
459 else /* this is really bad */
461 ERR(resource
, "[%04x]: Missing resource handler!\n", pModule
->self
);
462 pNameInfo
->handle
= NE_DefResourceHandler(
463 pNameInfo
->handle
, pModule
->self
, hRsrc
);
466 if (pNameInfo
->handle
)
469 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
472 return pNameInfo
->handle
;
478 /**********************************************************************
481 BOOL16
NE_FreeResource( NE_MODULE
*pModule
, HGLOBAL16 handle
)
483 NE_TYPEINFO
*pTypeInfo
;
484 NE_NAMEINFO
*pNameInfo
;
487 if (!handle
|| !pModule
|| !pModule
->res_table
) return handle
;
489 TRACE(resource
, "handle=%04x\n", handle
);
491 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
492 while (pTypeInfo
->type_id
)
494 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
495 for (count
= pTypeInfo
->count
; count
> 0; count
--)
497 if (pNameInfo
->handle
== handle
)
499 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
500 if (pNameInfo
->usage
== 0)
502 GlobalFree16( pNameInfo
->handle
);
503 pNameInfo
->handle
= 0;
504 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
510 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;