2 * NE resource functions
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
6 * Copyright 1997 Alex Korobka
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
29 #include <sys/types.h>
36 #include "wine/winbase16.h"
37 #include "wine/library.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(resource
);
43 #define NEXT_TYPEINFO(pTypeInfo) ((NE_TYPEINFO *)((char*)((pTypeInfo) + 1) + \
44 (pTypeInfo)->count * sizeof(NE_NAMEINFO)))
46 static FARPROC16 DefResourceHandlerProc
= (FARPROC16
)0xffffffff;
48 /* already defined in segment.c glue code */
49 extern WORD CALLBACK
NE_CallTo16_word_www(FARPROC16
,WORD
,WORD
,WORD
);
51 /***********************************************************************
54 * Find the type and resource id from their names.
55 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
57 static DWORD
NE_FindNameTableId( NE_MODULE
*pModule
, LPCSTR typeId
, LPCSTR resId
)
59 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
60 NE_NAMEINFO
*pNameInfo
;
66 for (; pTypeInfo
->type_id
!= 0;
67 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+1) +
68 pTypeInfo
->count
* sizeof(NE_NAMEINFO
)))
70 if (pTypeInfo
->type_id
!= 0x800f) continue;
71 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
72 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
74 TRACE("NameTable entry: type=%04x id=%04x\n",
75 pTypeInfo
->type_id
, pNameInfo
->id
);
76 handle
= LoadResource16( pModule
->self
,
77 (HRSRC16
)((int)pNameInfo
- (int)pModule
) );
78 for(p
= (WORD
*)LockResource16(handle
); p
&& *p
; p
= (WORD
*)((char*)p
+*p
))
80 TRACE(" type=%04x '%s' id=%04x '%s'\n",
81 p
[1], (char *)(p
+3), p
[2],
82 (char *)(p
+3)+strlen((char *)(p
+3))+1 );
83 /* Check for correct type */
87 if (!HIWORD(typeId
)) continue;
88 if (strcasecmp( typeId
, (char *)(p
+ 3) )) continue;
90 else if (HIWORD(typeId
) || (((DWORD
)typeId
& ~0x8000)!= p
[1]))
93 /* Now check for the id */
97 if (!HIWORD(resId
)) continue;
98 if (strcasecmp( resId
, (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
101 else if (HIWORD(resId
) || (((DWORD
)resId
& ~0x8000) != p
[2]))
104 /* If we get here, we've found the entry */
107 ret
= MAKELONG( p
[1], p
[2] );
110 FreeResource16( handle
);
117 /***********************************************************************
120 * Find header struct for a particular resource type.
122 NE_TYPEINFO
*NE_FindTypeSection( LPBYTE pResTab
,
123 NE_TYPEINFO
*pTypeInfo
, LPCSTR typeId
)
125 /* start from pTypeInfo */
127 if (HIWORD(typeId
) != 0) /* Named type */
130 BYTE len
= strlen( str
);
131 while (pTypeInfo
->type_id
)
133 if (!(pTypeInfo
->type_id
& 0x8000))
135 BYTE
*p
= pResTab
+ pTypeInfo
->type_id
;
136 if ((*p
== len
) && !strncasecmp( p
+1, str
, len
))
138 TRACE(" Found type '%s'\n", str
);
142 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
143 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
146 else /* Numeric type id */
148 WORD id
= LOWORD(typeId
) | 0x8000;
149 while (pTypeInfo
->type_id
)
151 if (pTypeInfo
->type_id
== id
)
153 TRACE(" Found type %04x\n", id
);
156 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
157 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
163 /***********************************************************************
164 * NE_FindResourceFromType
166 * Find a resource once the type info structure has been found.
168 NE_NAMEINFO
*NE_FindResourceFromType( LPBYTE pResTab
,
169 NE_TYPEINFO
*pTypeInfo
, LPCSTR resId
)
173 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
175 if (HIWORD(resId
) != 0) /* Named resource */
178 BYTE len
= strlen( str
);
179 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
181 if (pNameInfo
->id
& 0x8000) continue;
182 p
= pResTab
+ pNameInfo
->id
;
183 if ((*p
== len
) && !strncasecmp( p
+1, str
, len
))
187 else /* Numeric resource id */
189 WORD id
= LOWORD(resId
) | 0x8000;
190 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
191 if (pNameInfo
->id
== id
)
198 /***********************************************************************
199 * DefResourceHandler (KERNEL.456)
201 * This is the default LoadProc() function.
203 HGLOBAL16 WINAPI
NE_DefResourceHandler( HGLOBAL16 hMemObj
, HMODULE16 hModule
,
207 NE_MODULE
* pModule
= NE_GetPtr( hModule
);
208 if (pModule
&& (pModule
->flags
& NE_FFLAGS_BUILTIN
))
211 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
212 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
215 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
217 handle
= AllocResource16( hModule
, hRsrc
, 0 );
221 /* NOTE: hRsrcMap points to start of built-in resource data */
222 memcpy( GlobalLock16( handle
),
223 (char *)pModule
->hRsrcMap
+ (pNameInfo
->offset
<< sizeShift
),
224 pNameInfo
->length
<< sizeShift
);
228 if (pModule
&& (fd
= NE_OpenFile( pModule
)) != INVALID_HANDLE_VALUE
)
231 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
232 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
234 TRACE("loading, pos=%d, len=%d\n",
235 (int)pNameInfo
->offset
<< sizeShift
,
236 (int)pNameInfo
->length
<< sizeShift
);
238 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
240 handle
= AllocResource16( hModule
, hRsrc
, 0 );
245 SetFilePointer( fd
, (int)pNameInfo
->offset
<< sizeShift
, NULL
, SEEK_SET
);
246 ReadFile( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
,
255 /***********************************************************************
256 * NE_InitResourceHandler
258 * Fill in 'resloader' fields in the resource table.
260 BOOL
NE_InitResourceHandler( HMODULE16 hModule
)
262 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
263 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
265 if ( DefResourceHandlerProc
== (FARPROC16
)0xffffffff )
267 HMODULE16 hModule
= GetModuleHandle16( "KERNEL" );
268 int ordinal
= hModule
? NE_GetOrdinal( hModule
, "DefResourceHandler" ) : 0;
271 DefResourceHandlerProc
= NE_GetEntryPointEx( hModule
, ordinal
, FALSE
);
273 DefResourceHandlerProc
= NULL
;
276 TRACE("InitResourceHandler[%04x]\n", hModule
);
278 while(pTypeInfo
->type_id
)
280 wine_memcpy_unaligned( &pTypeInfo
->resloader
, &DefResourceHandlerProc
, sizeof(FARPROC16
) );
281 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
287 /**********************************************************************
288 * SetResourceHandler (KERNEL.67)
290 FARPROC16 WINAPI
SetResourceHandler16( HMODULE16 hModule
, LPCSTR typeId
,
291 FARPROC16 resourceHandler
)
293 FARPROC16 prevHandler
= NULL
;
294 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
295 LPBYTE pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
296 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)(pResTab
+ 2);
298 if (!pModule
|| !pModule
->res_table
) return NULL
;
300 TRACE("module=%04x type=%s\n", hModule
, debugstr_a(typeId
) );
304 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, typeId
)))
306 wine_memcpy_unaligned( &prevHandler
, &pTypeInfo
->resloader
, sizeof(FARPROC16
) );
307 wine_memcpy_unaligned( &pTypeInfo
->resloader
, &resourceHandler
, sizeof(FARPROC16
) );
308 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
314 /**********************************************************************
317 HRSRC
NE_FindResource( NE_MODULE
*pModule
, LPCSTR name
, LPCSTR type
)
319 NE_TYPEINFO
*pTypeInfo
;
320 NE_NAMEINFO
*pNameInfo
;
323 if (!pModule
|| !pModule
->res_table
) return 0;
325 TRACE("module=%04x name=%s type=%s\n", pModule
->self
, debugstr_a(name
), debugstr_a(type
) );
327 if (HIWORD(name
)) /* Check for '#xxx' name */
331 if (!(name
= (LPCSTR
)atoi( ptr
+ 1 )))
333 WARN("Incorrect resource name: %s\n", ptr
);
338 if (HIWORD(type
)) /* Check for '#xxx' type */
342 if (!(type
= (LPCSTR
)atoi( ptr
+ 1 )))
344 WARN("Incorrect resource type: %s\n", ptr
);
349 if (HIWORD(type
) || HIWORD(name
))
351 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
354 type
= (LPCSTR
)(int)LOWORD(id
);
355 name
= (LPCSTR
)(int)HIWORD(id
);
359 pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
360 pTypeInfo
= (NE_TYPEINFO
*)( pResTab
+ 2 );
364 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, type
)))
366 if ((pNameInfo
= NE_FindResourceFromType( pResTab
, pTypeInfo
, name
)))
368 TRACE(" Found id %08lx\n", (DWORD
)name
);
369 return (HRSRC
)( (char *)pNameInfo
- (char *)pModule
);
371 TRACE(" Not found, going on\n" );
372 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
380 /**********************************************************************
381 * AllocResource (KERNEL.66)
383 HGLOBAL16 WINAPI
AllocResource16( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
385 NE_NAMEINFO
*pNameInfo
=NULL
;
389 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
390 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return 0;
392 TRACE("module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
394 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
395 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
396 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
397 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
398 ret
= GlobalAlloc16( GMEM_FIXED
, size
);
399 if (ret
) FarSetOwner16( ret
, hModule
);
404 /**********************************************************************
405 * DirectResAlloc (KERNEL.168)
407 * Check Schulman, p. 232 for details
409 HGLOBAL16 WINAPI
DirectResAlloc16( HINSTANCE16 hInstance
, WORD wType
,
413 TRACE("(%04x,%04x,%04x)\n", hInstance
, wType
, wSize
);
414 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
415 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
416 CreateCursorIndirect. */
417 TRACE("(wType=%x)\n", wType
);
418 ret
= GlobalAlloc16( GMEM_MOVEABLE
, wSize
);
419 if (ret
) FarSetOwner16( ret
, hInstance
);
424 /**********************************************************************
425 * AccessResource (KERNEL.64)
427 INT16 WINAPI
AccessResource16( HINSTANCE16 hModule
, HRSRC16 hRsrc
)
430 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
432 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return -1;
434 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
436 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
438 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
439 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
440 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
446 /**********************************************************************
449 DWORD
NE_SizeofResource( NE_MODULE
*pModule
, HRSRC hRsrc
)
451 NE_NAMEINFO
*pNameInfo
=NULL
;
454 if (!pModule
|| !pModule
->res_table
) return 0;
456 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
458 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
459 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ LOWORD(hRsrc
));
460 return (DWORD
)pNameInfo
->length
<< sizeShift
;
464 /**********************************************************************
467 HGLOBAL16
NE_LoadResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
469 NE_TYPEINFO
*pTypeInfo
;
470 NE_NAMEINFO
*pNameInfo
= NULL
;
473 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
474 if (!hRsrc
|| !pModule
|| !pModule
->res_table
) return 0;
476 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
478 d
= pModule
->res_table
+ 2;
479 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
482 if (pTypeInfo
->type_id
== 0)
483 break; /* terminal entry */
484 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
487 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
489 pNameInfo
= (NE_NAMEINFO
*)(((char *)pModule
) + hRsrc
);
493 break; /* NE_NAMEINFO boundary mismatch */
495 pTypeInfo
= (NE_TYPEINFO
*)(((char *)pModule
) + d
);
500 if (pNameInfo
->handle
501 && !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
504 TRACE(" Already loaded, new count=%d\n",
510 wine_memcpy_unaligned( &resloader
, &pTypeInfo
->resloader
, sizeof(FARPROC16
) );
511 if ( resloader
&& resloader
!= DefResourceHandlerProc
)
512 pNameInfo
->handle
= NE_CallTo16_word_www(
513 resloader
, pNameInfo
->handle
, pModule
->self
, hRsrc
);
515 pNameInfo
->handle
= NE_DefResourceHandler(
516 pNameInfo
->handle
, pModule
->self
, hRsrc
);
518 if (pNameInfo
->handle
)
521 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
524 return pNameInfo
->handle
;
530 /**********************************************************************
533 BOOL16
NE_FreeResource( NE_MODULE
*pModule
, HGLOBAL16 handle
)
535 NE_TYPEINFO
*pTypeInfo
;
536 NE_NAMEINFO
*pNameInfo
;
539 if (!handle
|| !pModule
|| !pModule
->res_table
) return handle
;
541 TRACE("handle=%04x\n", handle
);
543 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
544 while (pTypeInfo
->type_id
)
546 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
547 for (count
= pTypeInfo
->count
; count
> 0; count
--)
549 if (pNameInfo
->handle
== handle
)
551 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
552 if (pNameInfo
->usage
== 0)
554 GlobalFree16( pNameInfo
->handle
);
555 pNameInfo
->handle
= 0;
556 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
562 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;