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>
34 #include "wine/winbase16.h"
35 #include "wine/library.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(resource
);
41 #define NEXT_TYPEINFO(pTypeInfo) ((NE_TYPEINFO *)((char*)((pTypeInfo) + 1) + \
42 (pTypeInfo)->count * sizeof(NE_NAMEINFO)))
44 static FARPROC16 DefResourceHandlerProc
= (FARPROC16
)0xffffffff;
46 /* already defined in segment.c glue code */
47 extern WORD CALLBACK
NE_CallTo16_word_www(FARPROC16
,WORD
,WORD
,WORD
);
49 /***********************************************************************
52 * Find the type and resource id from their names.
53 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
55 static DWORD
NE_FindNameTableId( NE_MODULE
*pModule
, LPCSTR typeId
, LPCSTR resId
)
57 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
58 NE_NAMEINFO
*pNameInfo
;
64 for (; pTypeInfo
->type_id
!= 0;
65 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+1) +
66 pTypeInfo
->count
* sizeof(NE_NAMEINFO
)))
68 if (pTypeInfo
->type_id
!= 0x800f) continue;
69 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
70 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
72 TRACE("NameTable entry: type=%04x id=%04x\n",
73 pTypeInfo
->type_id
, pNameInfo
->id
);
74 handle
= LoadResource16( pModule
->self
,
75 (HRSRC16
)((int)pNameInfo
- (int)pModule
) );
76 for(p
= (WORD
*)LockResource16(handle
); p
&& *p
; p
= (WORD
*)((char*)p
+*p
))
78 TRACE(" type=%04x '%s' id=%04x '%s'\n",
79 p
[1], (char *)(p
+3), p
[2],
80 (char *)(p
+3)+strlen((char *)(p
+3))+1 );
81 /* Check for correct type */
85 if (!HIWORD(typeId
)) continue;
86 if (strcasecmp( typeId
, (char *)(p
+ 3) )) continue;
88 else if (HIWORD(typeId
) || (((DWORD
)typeId
& ~0x8000)!= p
[1]))
91 /* Now check for the id */
95 if (!HIWORD(resId
)) continue;
96 if (strcasecmp( resId
, (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
99 else if (HIWORD(resId
) || (((DWORD
)resId
& ~0x8000) != p
[2]))
102 /* If we get here, we've found the entry */
105 ret
= MAKELONG( p
[1], p
[2] );
108 FreeResource16( handle
);
115 /***********************************************************************
118 * Find header struct for a particular resource type.
120 NE_TYPEINFO
*NE_FindTypeSection( LPBYTE pResTab
,
121 NE_TYPEINFO
*pTypeInfo
, LPCSTR typeId
)
123 /* start from pTypeInfo */
125 if (HIWORD(typeId
) != 0) /* Named type */
128 BYTE len
= strlen( str
);
129 while (pTypeInfo
->type_id
)
131 if (!(pTypeInfo
->type_id
& 0x8000))
133 BYTE
*p
= pResTab
+ pTypeInfo
->type_id
;
134 if ((*p
== len
) && !strncasecmp( p
+1, str
, len
))
136 TRACE(" Found type '%s'\n", str
);
140 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
141 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
144 else /* Numeric type id */
146 WORD id
= LOWORD(typeId
) | 0x8000;
147 while (pTypeInfo
->type_id
)
149 if (pTypeInfo
->type_id
== id
)
151 TRACE(" Found type %04x\n", id
);
154 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
155 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
161 /***********************************************************************
162 * NE_FindResourceFromType
164 * Find a resource once the type info structure has been found.
166 NE_NAMEINFO
*NE_FindResourceFromType( LPBYTE pResTab
,
167 NE_TYPEINFO
*pTypeInfo
, LPCSTR resId
)
171 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
173 if (HIWORD(resId
) != 0) /* Named resource */
176 BYTE len
= strlen( str
);
177 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
179 if (pNameInfo
->id
& 0x8000) continue;
180 p
= pResTab
+ pNameInfo
->id
;
181 if ((*p
== len
) && !strncasecmp( p
+1, str
, len
))
185 else /* Numeric resource id */
187 WORD id
= LOWORD(resId
) | 0x8000;
188 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
189 if (pNameInfo
->id
== id
)
196 /***********************************************************************
197 * DefResourceHandler (KERNEL.456)
199 * This is the default LoadProc() function.
201 HGLOBAL16 WINAPI
NE_DefResourceHandler( HGLOBAL16 hMemObj
, HMODULE16 hModule
,
205 NE_MODULE
* pModule
= NE_GetPtr( hModule
);
206 if (pModule
&& (pModule
->flags
& NE_FFLAGS_BUILTIN
))
209 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
210 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
213 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
215 handle
= AllocResource16( hModule
, hRsrc
, 0 );
219 /* NOTE: hRsrcMap points to start of built-in resource data */
220 memcpy( GlobalLock16( handle
),
221 (char *)pModule
->hRsrcMap
+ (pNameInfo
->offset
<< sizeShift
),
222 pNameInfo
->length
<< sizeShift
);
226 if (pModule
&& (fd
= NE_OpenFile( pModule
)) != INVALID_HANDLE_VALUE
)
229 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
230 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
232 TRACE("loading, pos=%d, len=%d\n",
233 (int)pNameInfo
->offset
<< sizeShift
,
234 (int)pNameInfo
->length
<< sizeShift
);
236 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
238 handle
= AllocResource16( hModule
, hRsrc
, 0 );
243 SetFilePointer( fd
, (int)pNameInfo
->offset
<< sizeShift
, NULL
, SEEK_SET
);
244 ReadFile( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
,
252 /***********************************************************************
253 * NE_InitResourceHandler
255 * Fill in 'resloader' fields in the resource table.
257 BOOL
NE_InitResourceHandler( HMODULE16 hModule
)
259 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
260 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
262 if ( DefResourceHandlerProc
== (FARPROC16
)0xffffffff )
264 HMODULE16 hModule
= GetModuleHandle16( "KERNEL" );
265 int ordinal
= hModule
? NE_GetOrdinal( hModule
, "DefResourceHandler" ) : 0;
268 DefResourceHandlerProc
= NE_GetEntryPointEx( hModule
, ordinal
, FALSE
);
270 DefResourceHandlerProc
= NULL
;
273 TRACE("InitResourceHandler[%04x]\n", hModule
);
275 while(pTypeInfo
->type_id
)
277 PUT_UA_DWORD( &pTypeInfo
->resloader
, (DWORD
)DefResourceHandlerProc
);
278 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
284 /**********************************************************************
285 * SetResourceHandler (KERNEL.67)
287 FARPROC16 WINAPI
SetResourceHandler16( HMODULE16 hModule
, LPCSTR typeId
,
288 FARPROC16 resourceHandler
)
290 FARPROC16 prevHandler
= NULL
;
291 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
292 LPBYTE pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
293 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)(pResTab
+ 2);
295 if (!pModule
|| !pModule
->res_table
) return NULL
;
297 TRACE("module=%04x type=%s\n", hModule
, debugres_a(typeId
) );
301 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, typeId
)))
303 prevHandler
= (FARPROC16
)GET_UA_DWORD( &pTypeInfo
->resloader
);
304 PUT_UA_DWORD( &pTypeInfo
->resloader
, (DWORD
)resourceHandler
);
305 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
311 /**********************************************************************
314 HRSRC16
NE_FindResource( NE_MODULE
*pModule
, LPCSTR name
, LPCSTR type
)
316 NE_TYPEINFO
*pTypeInfo
;
317 NE_NAMEINFO
*pNameInfo
;
320 if (!pModule
|| !pModule
->res_table
) return 0;
322 TRACE("module=%04x name=%s type=%s\n", pModule
->self
, debugres_a(name
), debugres_a(type
) );
324 if (HIWORD(name
)) /* Check for '#xxx' name */
328 if (!(name
= (LPCSTR
)atoi( ptr
+ 1 )))
330 WARN("Incorrect resource name: %s\n", ptr
);
335 if (HIWORD(type
)) /* Check for '#xxx' type */
339 if (!(type
= (LPCSTR
)atoi( ptr
+ 1 )))
341 WARN("Incorrect resource type: %s\n", ptr
);
346 if (HIWORD(type
) || HIWORD(name
))
348 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
351 type
= (LPCSTR
)(int)LOWORD(id
);
352 name
= (LPCSTR
)(int)HIWORD(id
);
356 pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
357 pTypeInfo
= (NE_TYPEINFO
*)( pResTab
+ 2 );
361 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, type
)))
363 if ((pNameInfo
= NE_FindResourceFromType( pResTab
, pTypeInfo
, name
)))
365 TRACE(" Found id %08lx\n", (DWORD
)name
);
366 return (HRSRC16
)( (int)pNameInfo
- (int)pModule
);
368 TRACE(" Not found, going on\n" );
369 pTypeInfo
= NEXT_TYPEINFO(pTypeInfo
);
377 /**********************************************************************
378 * AllocResource (KERNEL.66)
380 HGLOBAL16 WINAPI
AllocResource16( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
382 NE_NAMEINFO
*pNameInfo
=NULL
;
386 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
387 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return 0;
389 TRACE("module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
391 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
392 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
393 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
394 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
395 ret
= GlobalAlloc16( GMEM_FIXED
, size
);
396 if (ret
) FarSetOwner16( ret
, hModule
);
401 /**********************************************************************
402 * DirectResAlloc (KERNEL.168)
404 * Check Schulman, p. 232 for details
406 HGLOBAL16 WINAPI
DirectResAlloc16( HINSTANCE16 hInstance
, WORD wType
,
410 TRACE("(%04x,%04x,%04x)\n", hInstance
, wType
, wSize
);
411 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
412 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
413 CreateCursorIndirect. */
414 TRACE("(wType=%x)\n", wType
);
415 ret
= GlobalAlloc16( GMEM_MOVEABLE
, wSize
);
416 if (ret
) FarSetOwner16( ret
, hInstance
);
421 /**********************************************************************
422 * AccessResource (KERNEL.64)
424 INT16 WINAPI
AccessResource16( HINSTANCE16 hModule
, HRSRC16 hRsrc
)
427 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
429 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return -1;
431 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
433 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
435 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
436 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
437 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
443 /**********************************************************************
446 DWORD
NE_SizeofResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
448 NE_NAMEINFO
*pNameInfo
=NULL
;
451 if (!pModule
|| !pModule
->res_table
) return 0;
453 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
455 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
456 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
457 return (DWORD
)pNameInfo
->length
<< sizeShift
;
461 /**********************************************************************
464 HGLOBAL16
NE_LoadResource( NE_MODULE
*pModule
, HRSRC16 hRsrc
)
466 NE_TYPEINFO
*pTypeInfo
;
467 NE_NAMEINFO
*pNameInfo
= NULL
;
470 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
471 if (!hRsrc
|| !pModule
|| !pModule
->res_table
) return 0;
473 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
475 d
= pModule
->res_table
+ 2;
476 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
479 if (pTypeInfo
->type_id
== 0)
480 break; /* terminal entry */
481 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
484 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
486 pNameInfo
= (NE_NAMEINFO
*)(((char *)pModule
) + hRsrc
);
490 break; /* NE_NAMEINFO boundary mismatch */
492 pTypeInfo
= (NE_TYPEINFO
*)(((char *)pModule
) + d
);
497 if (pNameInfo
->handle
498 && !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
501 TRACE(" Already loaded, new count=%d\n",
506 FARPROC16 resloader
= (FARPROC16
)GET_UA_DWORD( &pTypeInfo
->resloader
);
507 if ( resloader
&& resloader
!= DefResourceHandlerProc
)
508 pNameInfo
->handle
= NE_CallTo16_word_www(
509 resloader
, pNameInfo
->handle
, pModule
->self
, hRsrc
);
511 pNameInfo
->handle
= NE_DefResourceHandler(
512 pNameInfo
->handle
, pModule
->self
, hRsrc
);
514 if (pNameInfo
->handle
)
517 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
520 return pNameInfo
->handle
;
526 /**********************************************************************
529 BOOL16
NE_FreeResource( NE_MODULE
*pModule
, HGLOBAL16 handle
)
531 NE_TYPEINFO
*pTypeInfo
;
532 NE_NAMEINFO
*pNameInfo
;
535 if (!handle
|| !pModule
|| !pModule
->res_table
) return handle
;
537 TRACE("handle=%04x\n", handle
);
539 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
540 while (pTypeInfo
->type_id
)
542 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
543 for (count
= pTypeInfo
->count
; count
> 0; count
--)
545 if (pNameInfo
->handle
== handle
)
547 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
548 if (pNameInfo
->usage
== 0)
550 GlobalFree16( pNameInfo
->handle
);
551 pNameInfo
->handle
= 0;
552 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
558 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;