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>
16 #include "wine/port.h"
17 #include "wine/winbase16.h"
18 #include "wine/library.h"
21 #include "debugtools.h"
23 DEFAULT_DEBUG_CHANNEL(resource);
25 #define NEXT_TYPEINFO(pTypeInfo) ((NE_TYPEINFO *)((char*)((pTypeInfo) + 1) + \
26 (pTypeInfo)->count * sizeof(NE_NAMEINFO)))
28 static FARPROC16 DefResourceHandlerProc = (FARPROC16)0xffffffff;
30 /* already defined in segment.c glue code */
31 extern WORD CALLBACK NE_CallTo16_word_www(FARPROC16,WORD,WORD,WORD);
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 (strcasecmp( typeId, (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;
80 if (strcasecmp( resId, (char*)(p+3)+strlen((char*)(p+3))+1 )) continue;
83 else if (HIWORD(resId) || (((DWORD)resId & ~0x8000) != p[2]))
86 /* If we get here, we've found the entry */
89 ret = MAKELONG( p[1], p[2] );
92 FreeResource16( handle );
99 /***********************************************************************
102 * Find header struct for a particular resource type.
104 NE_TYPEINFO *NE_FindTypeSection( LPBYTE pResTab,
105 NE_TYPEINFO *pTypeInfo, LPCSTR typeId )
107 /* start from pTypeInfo */
109 if (HIWORD(typeId) != 0) /* Named type */
112 BYTE len = strlen( str );
113 while (pTypeInfo->type_id)
115 if (!(pTypeInfo->type_id & 0x8000))
117 BYTE *p = pResTab + pTypeInfo->type_id;
118 if ((*p == len) && !strncasecmp( p+1, str, len ))
120 TRACE(" Found type '%s'\n", str );
124 TRACE(" Skipping type %04x\n", pTypeInfo->type_id );
125 pTypeInfo = NEXT_TYPEINFO(pTypeInfo);
128 else /* Numeric type id */
130 WORD id = LOWORD(typeId) | 0x8000;
131 while (pTypeInfo->type_id)
133 if (pTypeInfo->type_id == id)
135 TRACE(" Found type %04x\n", id );
138 TRACE(" Skipping type %04x\n", pTypeInfo->type_id );
139 pTypeInfo = NEXT_TYPEINFO(pTypeInfo);
145 /***********************************************************************
146 * NE_FindResourceFromType
148 * Find a resource once the type info structure has been found.
150 NE_NAMEINFO *NE_FindResourceFromType( LPBYTE pResTab,
151 NE_TYPEINFO *pTypeInfo, LPCSTR resId )
155 NE_NAMEINFO *pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
157 if (HIWORD(resId) != 0) /* Named resource */
160 BYTE len = strlen( str );
161 for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
163 if (pNameInfo->id & 0x8000) continue;
164 p = pResTab + pNameInfo->id;
165 if ((*p == len) && !strncasecmp( p+1, str, len ))
169 else /* Numeric resource id */
171 WORD id = LOWORD(resId) | 0x8000;
172 for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
173 if (pNameInfo->id == id)
180 /***********************************************************************
181 * NE_DefResourceHandler
183 * This is the default LoadProc() function.
185 HGLOBAL16 WINAPI NE_DefResourceHandler( HGLOBAL16 hMemObj, HMODULE16 hModule,
189 NE_MODULE* pModule = NE_GetPtr( hModule );
190 if (pModule && (pModule->flags & NE_FFLAGS_BUILTIN))
193 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
194 NE_NAMEINFO* pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
197 handle = GlobalReAlloc16( hMemObj, pNameInfo->length << sizeShift, 0 );
199 handle = AllocResource16( hModule, hRsrc, 0 );
203 /* NOTE: hRsrcMap points to start of built-in resource data */
204 memcpy( GlobalLock16( handle ),
205 (char *)pModule->hRsrcMap + (pNameInfo->offset << sizeShift),
206 pNameInfo->length << sizeShift );
210 if (pModule && (fd = NE_OpenFile( pModule )) >= 0)
213 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
214 NE_NAMEINFO* pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
216 TRACE("loading, pos=%d, len=%d\n",
217 (int)pNameInfo->offset << sizeShift,
218 (int)pNameInfo->length << sizeShift );
220 handle = GlobalReAlloc16( hMemObj, pNameInfo->length << sizeShift, 0 );
222 handle = AllocResource16( hModule, hRsrc, 0 );
227 SetFilePointer( fd, (int)pNameInfo->offset << sizeShift, NULL, SEEK_SET );
228 ReadFile( fd, GlobalLock16( handle ), (int)pNameInfo->length << sizeShift,
236 /***********************************************************************
237 * NE_InitResourceHandler
239 * Fill in 'resloader' fields in the resource table.
241 BOOL NE_InitResourceHandler( HMODULE16 hModule )
243 NE_MODULE *pModule = NE_GetPtr( hModule );
244 NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
246 if ( DefResourceHandlerProc == (FARPROC16)0xffffffff )
248 HMODULE16 hModule = GetModuleHandle16( "KERNEL" );
249 int ordinal = hModule? NE_GetOrdinal( hModule, "DefResourceHandler" ) : 0;
252 DefResourceHandlerProc = NE_GetEntryPointEx( hModule, ordinal, FALSE );
254 DefResourceHandlerProc = NULL;
257 TRACE("InitResourceHandler[%04x]\n", hModule );
259 while(pTypeInfo->type_id)
261 PUT_UA_DWORD( &pTypeInfo->resloader, (DWORD)DefResourceHandlerProc );
262 pTypeInfo = NEXT_TYPEINFO(pTypeInfo);
268 /**********************************************************************
269 * SetResourceHandler (KERNEL.43)
271 FARPROC16 WINAPI SetResourceHandler16( HMODULE16 hModule, LPCSTR typeId,
272 FARPROC16 resourceHandler )
274 FARPROC16 prevHandler = NULL;
275 NE_MODULE *pModule = NE_GetPtr( hModule );
276 LPBYTE pResTab = (LPBYTE)pModule + pModule->res_table;
277 NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)(pResTab + 2);
279 if (!pModule || !pModule->res_table) return NULL;
281 TRACE("module=%04x type=%s\n", hModule, debugres_a(typeId) );
285 if (!(pTypeInfo = NE_FindTypeSection( pResTab, pTypeInfo, typeId )))
287 prevHandler = (FARPROC16)GET_UA_DWORD( &pTypeInfo->resloader );
288 PUT_UA_DWORD( &pTypeInfo->resloader, (DWORD)resourceHandler );
289 pTypeInfo = NEXT_TYPEINFO(pTypeInfo);
295 /**********************************************************************
298 HRSRC16 NE_FindResource( NE_MODULE *pModule, LPCSTR name, LPCSTR type )
300 NE_TYPEINFO *pTypeInfo;
301 NE_NAMEINFO *pNameInfo;
304 if (!pModule || !pModule->res_table) return 0;
306 TRACE("module=%04x name=%s type=%s\n", pModule->self, debugres_a(name), debugres_a(type) );
308 if (HIWORD(name)) /* Check for '#xxx' name */
312 if (!(name = (LPCSTR)atoi( ptr + 1 )))
314 WARN("Incorrect resource name: %s\n", ptr);
319 if (HIWORD(type)) /* Check for '#xxx' type */
323 if (!(type = (LPCSTR)atoi( ptr + 1 )))
325 WARN("Incorrect resource type: %s\n", ptr);
330 if (HIWORD(type) || HIWORD(name))
332 DWORD id = NE_FindNameTableId( pModule, type, name );
335 type = (LPCSTR)(int)LOWORD(id);
336 name = (LPCSTR)(int)HIWORD(id);
340 pResTab = (LPBYTE)pModule + pModule->res_table;
341 pTypeInfo = (NE_TYPEINFO *)( pResTab + 2 );
345 if (!(pTypeInfo = NE_FindTypeSection( pResTab, pTypeInfo, type )))
347 if ((pNameInfo = NE_FindResourceFromType( pResTab, pTypeInfo, name )))
349 TRACE(" Found id %08lx\n", (DWORD)name );
350 return (HRSRC16)( (int)pNameInfo - (int)pModule );
352 TRACE(" Not found, going on\n" );
353 pTypeInfo = NEXT_TYPEINFO(pTypeInfo);
361 /**********************************************************************
362 * AllocResource (KERNEL.66)
364 HGLOBAL16 WINAPI AllocResource16( HMODULE16 hModule, HRSRC16 hRsrc, DWORD size)
366 NE_NAMEINFO *pNameInfo=NULL;
370 NE_MODULE *pModule = NE_GetPtr( hModule );
371 if (!pModule || !pModule->res_table || !hRsrc) return 0;
373 TRACE("module=%04x res=%04x size=%ld\n", hModule, hRsrc, size );
375 sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
376 pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
377 if (size < (DWORD)pNameInfo->length << sizeShift)
378 size = (DWORD)pNameInfo->length << sizeShift;
379 ret = GlobalAlloc16( GMEM_FIXED, size );
380 if (ret) FarSetOwner16( ret, hModule );
385 /**********************************************************************
386 * DirectResAlloc (KERNEL.168)
388 * Check Schulman, p. 232 for details
390 HGLOBAL16 WINAPI DirectResAlloc16( HINSTANCE16 hInstance, WORD wType,
394 TRACE("(%04x,%04x,%04x)\n", hInstance, wType, wSize );
395 if (!(hInstance = GetExePtr( hInstance ))) return 0;
396 if(wType != 0x10) /* 0x10 is the only observed value, passed from
397 CreateCursorIndirect. */
398 TRACE("(wType=%x)\n", wType);
399 ret = GlobalAlloc16( GMEM_MOVEABLE, wSize );
400 if (ret) FarSetOwner16( ret, hInstance );
405 /**********************************************************************
406 * AccessResource16 (KERNEL.64)
408 INT16 WINAPI AccessResource16( HINSTANCE16 hModule, HRSRC16 hRsrc )
411 NE_MODULE *pModule = NE_GetPtr( hModule );
413 if (!pModule || !pModule->res_table || !hRsrc) return -1;
415 TRACE("module=%04x res=%04x\n", pModule->self, hRsrc );
417 if ((fd = _lopen16( NE_MODULE_NAME(pModule), OF_READ )) != HFILE_ERROR16)
419 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
420 NE_NAMEINFO *pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
421 _llseek16( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
427 /**********************************************************************
430 DWORD NE_SizeofResource( NE_MODULE *pModule, HRSRC16 hRsrc )
432 NE_NAMEINFO *pNameInfo=NULL;
435 if (!pModule || !pModule->res_table) return 0;
437 TRACE("module=%04x res=%04x\n", pModule->self, hRsrc );
439 sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
440 pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
441 return (DWORD)pNameInfo->length << sizeShift;
445 /**********************************************************************
448 HGLOBAL16 NE_LoadResource( NE_MODULE *pModule, HRSRC16 hRsrc )
450 NE_TYPEINFO *pTypeInfo;
451 NE_NAMEINFO *pNameInfo = NULL;
454 TRACE("module=%04x res=%04x\n", pModule->self, hRsrc );
455 if (!hRsrc || !pModule || !pModule->res_table) return 0;
457 /* First, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
459 d = pModule->res_table + 2;
460 pTypeInfo = (NE_TYPEINFO *)((char *)pModule + d);
463 if (pTypeInfo->type_id == 0)
464 break; /* terminal entry */
465 d += sizeof(NE_TYPEINFO) + pTypeInfo->count * sizeof(NE_NAMEINFO);
468 if( ((d - hRsrc)%sizeof(NE_NAMEINFO)) == 0 )
470 pNameInfo = (NE_NAMEINFO *)(((char *)pModule) + hRsrc);
474 break; /* NE_NAMEINFO boundary mismatch */
476 pTypeInfo = (NE_TYPEINFO *)(((char *)pModule) + d);
481 if (pNameInfo->handle
482 && !(GlobalFlags16(pNameInfo->handle) & GMEM_DISCARDED))
485 TRACE(" Already loaded, new count=%d\n",
490 FARPROC16 resloader = (FARPROC16)GET_UA_DWORD( &pTypeInfo->resloader );
491 if ( resloader && resloader != DefResourceHandlerProc )
492 pNameInfo->handle = NE_CallTo16_word_www(
493 resloader, pNameInfo->handle, pModule->self, hRsrc );
495 pNameInfo->handle = NE_DefResourceHandler(
496 pNameInfo->handle, pModule->self, hRsrc );
498 if (pNameInfo->handle)
501 pNameInfo->flags |= NE_SEGFLAGS_LOADED;
504 return pNameInfo->handle;
510 /**********************************************************************
513 BOOL16 NE_FreeResource( NE_MODULE *pModule, HGLOBAL16 handle )
515 NE_TYPEINFO *pTypeInfo;
516 NE_NAMEINFO *pNameInfo;
519 if (!handle || !pModule || !pModule->res_table) return handle;
521 TRACE("handle=%04x\n", handle );
523 pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
524 while (pTypeInfo->type_id)
526 pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
527 for (count = pTypeInfo->count; count > 0; count--)
529 if (pNameInfo->handle == handle)
531 if (pNameInfo->usage > 0) pNameInfo->usage--;
532 if (pNameInfo->usage == 0)
534 GlobalFree16( pNameInfo->handle );
535 pNameInfo->handle = 0;
536 pNameInfo->flags &= ~NE_SEGFLAGS_LOADED;
542 pTypeInfo = (NE_TYPEINFO *)pNameInfo;