Added tmschema.h and some other theme defines.
[wine.git] / dlls / kernel / resource16.c
bloba00a89aa87bd42e69ee8dea5f35f8b59c0c009cb
1 /*
2 * 16-bit resource functions
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1997 Alex Korobka
6 * Copyright 1998 Ulrich Weigand
7 * Copyright 1995, 2003 Alexandre Julliard
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "config.h"
25 #include "wine/port.h"
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/types.h>
32 #include "windef.h"
33 #include "winbase.h"
34 #include "wownt32.h"
35 #include "wine/winbase16.h"
36 #include "wine/winuser16.h"
37 #include "wine/unicode.h"
38 #include "module.h"
39 #include "task.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(resource);
44 /* handle conversions */
45 #define HRSRC_32(h16) ((HRSRC)(ULONG_PTR)(h16))
46 #define HGLOBAL_32(h16) ((HGLOBAL)(ULONG_PTR)(h16))
48 static inline NE_MODULE *get_module( HMODULE16 mod )
50 if (!mod) mod = TASK_GetCurrent()->hModule;
51 return NE_GetPtr( mod );
54 #define HRSRC_MAP_BLOCKSIZE 16
56 typedef struct _HRSRC_ELEM
58 HRSRC hRsrc;
59 WORD type;
60 } HRSRC_ELEM;
62 typedef struct _HRSRC_MAP
64 int nAlloc;
65 int nUsed;
66 HRSRC_ELEM *elem;
67 } HRSRC_MAP;
70 /**********************************************************************
71 * MapHRsrc32To16
73 static HRSRC16 MapHRsrc32To16( NE_MODULE *pModule, HRSRC hRsrc32, WORD type )
75 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
76 HRSRC_ELEM *newElem;
77 int i;
79 /* On first call, initialize HRSRC map */
80 if ( !map )
82 if ( !(map = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HRSRC_MAP) ) ) )
84 ERR("Cannot allocate HRSRC map\n" );
85 return 0;
87 pModule->hRsrcMap = map;
90 /* Check whether HRSRC32 already in map */
91 for ( i = 0; i < map->nUsed; i++ )
92 if ( map->elem[i].hRsrc == hRsrc32 )
93 return (HRSRC16)(i + 1);
95 /* If no space left, grow table */
96 if ( map->nUsed == map->nAlloc )
98 if ( !(newElem = (HRSRC_ELEM *)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
99 map->elem,
100 (map->nAlloc + HRSRC_MAP_BLOCKSIZE)
101 * sizeof(HRSRC_ELEM) ) ))
103 ERR("Cannot grow HRSRC map\n" );
104 return 0;
106 map->elem = newElem;
107 map->nAlloc += HRSRC_MAP_BLOCKSIZE;
110 /* Add HRSRC32 to table */
111 map->elem[map->nUsed].hRsrc = hRsrc32;
112 map->elem[map->nUsed].type = type;
113 map->nUsed++;
115 return (HRSRC16)map->nUsed;
118 /**********************************************************************
119 * MapHRsrc16To32
121 static HRSRC MapHRsrc16To32( NE_MODULE *pModule, HRSRC16 hRsrc16 )
123 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
124 if ( !map || !hRsrc16 || hRsrc16 > map->nUsed ) return 0;
126 return map->elem[hRsrc16-1].hRsrc;
129 /**********************************************************************
130 * MapHRsrc16ToType
132 static WORD MapHRsrc16ToType( NE_MODULE *pModule, HRSRC16 hRsrc16 )
134 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
135 if ( !map || !hRsrc16 || hRsrc16 > map->nUsed ) return 0;
137 return map->elem[hRsrc16-1].type;
141 /**********************************************************************
142 * get_res_name
144 * Convert a resource name from '#xxx' form to numerical id.
146 static inline LPCSTR get_res_name( LPCSTR name )
148 if (HIWORD(name) && name[0] == '#') name = (LPCSTR)atoi( name + 1 );
149 return name;
153 /**********************************************************************
154 * next_typeinfo
156 static inline NE_TYPEINFO *next_typeinfo( NE_TYPEINFO *info )
158 return (NE_TYPEINFO *)((char*)(info + 1) + info->count * sizeof(NE_NAMEINFO));
162 /**********************************************************************
163 * get_default_res_handler
165 static inline FARPROC16 get_default_res_handler(void)
167 static FARPROC16 handler;
169 if (!handler) handler = GetProcAddress16( GetModuleHandle16("KERNEL"), "DefResourceHandler" );
170 return handler;
174 /***********************************************************************
175 * NE_FindNameTableId
177 * Find the type and resource id from their names.
178 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
180 static DWORD NE_FindNameTableId( NE_MODULE *pModule, LPCSTR typeId, LPCSTR resId )
182 NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
183 NE_NAMEINFO *pNameInfo;
184 HGLOBAL16 handle;
185 WORD *p;
186 DWORD ret = 0;
187 int count;
189 for (; pTypeInfo->type_id != 0;
190 pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
191 pTypeInfo->count * sizeof(NE_NAMEINFO)))
193 if (pTypeInfo->type_id != 0x800f) continue;
194 pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
195 for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
197 TRACE("NameTable entry: type=%04x id=%04x\n",
198 pTypeInfo->type_id, pNameInfo->id );
199 handle = LoadResource16( pModule->self,
200 (HRSRC16)((int)pNameInfo - (int)pModule) );
201 for(p = (WORD*)LockResource16(handle); p && *p; p = (WORD *)((char*)p+*p))
203 TRACE(" type=%04x '%s' id=%04x '%s'\n",
204 p[1], (char *)(p+3), p[2],
205 (char *)(p+3)+strlen((char *)(p+3))+1 );
206 /* Check for correct type */
208 if (p[1] & 0x8000)
210 if (!HIWORD(typeId)) continue;
211 if (strcasecmp( typeId, (char *)(p + 3) )) continue;
213 else if (HIWORD(typeId) || (((DWORD)typeId & ~0x8000)!= p[1]))
214 continue;
216 /* Now check for the id */
218 if (p[2] & 0x8000)
220 if (!HIWORD(resId)) continue;
221 if (strcasecmp( resId, (char*)(p+3)+strlen((char*)(p+3))+1 )) continue;
224 else if (HIWORD(resId) || (((DWORD)resId & ~0x8000) != p[2]))
225 continue;
227 /* If we get here, we've found the entry */
229 TRACE(" Found!\n" );
230 ret = MAKELONG( p[1], p[2] );
231 break;
233 FreeResource16( handle );
234 if (ret) return ret;
237 return 0;
241 /***********************************************************************
242 * NE_FindTypeSection
244 * Find header struct for a particular resource type.
246 static NE_TYPEINFO *NE_FindTypeSection( LPBYTE pResTab, NE_TYPEINFO *pTypeInfo, LPCSTR typeId )
248 /* start from pTypeInfo */
250 if (HIWORD(typeId) != 0) /* Named type */
252 LPCSTR str = typeId;
253 BYTE len = strlen( str );
254 while (pTypeInfo->type_id)
256 if (!(pTypeInfo->type_id & 0x8000))
258 BYTE *p = pResTab + pTypeInfo->type_id;
259 if ((*p == len) && !strncasecmp( p+1, str, len ))
261 TRACE(" Found type '%s'\n", str );
262 return pTypeInfo;
265 TRACE(" Skipping type %04x\n", pTypeInfo->type_id );
266 pTypeInfo = next_typeinfo(pTypeInfo);
269 else /* Numeric type id */
271 WORD id = LOWORD(typeId) | 0x8000;
272 while (pTypeInfo->type_id)
274 if (pTypeInfo->type_id == id)
276 TRACE(" Found type %04x\n", id );
277 return pTypeInfo;
279 TRACE(" Skipping type %04x\n", pTypeInfo->type_id );
280 pTypeInfo = next_typeinfo(pTypeInfo);
283 return NULL;
287 /***********************************************************************
288 * NE_FindResourceFromType
290 * Find a resource once the type info structure has been found.
292 static NE_NAMEINFO *NE_FindResourceFromType( LPBYTE pResTab, NE_TYPEINFO *pTypeInfo, LPCSTR resId )
294 BYTE *p;
295 int count;
296 NE_NAMEINFO *pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
298 if (HIWORD(resId) != 0) /* Named resource */
300 LPCSTR str = resId;
301 BYTE len = strlen( str );
302 for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
304 if (pNameInfo->id & 0x8000) continue;
305 p = pResTab + pNameInfo->id;
306 if ((*p == len) && !strncasecmp( p+1, str, len ))
307 return pNameInfo;
310 else /* Numeric resource id */
312 WORD id = LOWORD(resId) | 0x8000;
313 for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
314 if (pNameInfo->id == id) return pNameInfo;
316 return NULL;
320 /***********************************************************************
321 * DefResourceHandler (KERNEL.456)
323 * This is the default LoadProc() function.
325 HGLOBAL16 WINAPI NE_DefResourceHandler( HGLOBAL16 hMemObj, HMODULE16 hModule,
326 HRSRC16 hRsrc )
328 HANDLE fd;
329 NE_MODULE* pModule = NE_GetPtr( hModule );
330 if (pModule && (pModule->flags & NE_FFLAGS_BUILTIN))
332 HGLOBAL16 handle;
333 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
334 NE_NAMEINFO* pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
336 if ( hMemObj )
337 handle = GlobalReAlloc16( hMemObj, pNameInfo->length << sizeShift, 0 );
338 else
339 handle = AllocResource16( hModule, hRsrc, 0 );
341 if ( handle )
343 /* NOTE: hRsrcMap points to start of built-in resource data */
344 memcpy( GlobalLock16( handle ),
345 (char *)pModule->hRsrcMap + (pNameInfo->offset << sizeShift),
346 pNameInfo->length << sizeShift );
348 return handle;
350 if (pModule && (fd = NE_OpenFile( pModule )) != INVALID_HANDLE_VALUE)
352 HGLOBAL16 handle;
353 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
354 NE_NAMEINFO* pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
356 TRACE("loading, pos=%d, len=%d\n",
357 (int)pNameInfo->offset << sizeShift,
358 (int)pNameInfo->length << sizeShift );
359 if( hMemObj )
360 handle = GlobalReAlloc16( hMemObj, pNameInfo->length << sizeShift, 0 );
361 else
362 handle = AllocResource16( hModule, hRsrc, 0 );
364 if( handle )
366 DWORD res;
367 SetFilePointer( fd, (int)pNameInfo->offset << sizeShift, NULL, SEEK_SET );
368 ReadFile( fd, GlobalLock16( handle ), (int)pNameInfo->length << sizeShift,
369 &res, NULL );
371 CloseHandle(fd);
372 return handle;
374 return (HGLOBAL16)0;
378 /**********************************************************************
379 * SetResourceHandler (KERNEL.67)
381 FARPROC16 WINAPI SetResourceHandler16( HMODULE16 hModule, LPCSTR typeId, FARPROC16 resourceHandler )
383 LPBYTE pResTab;
384 NE_TYPEINFO *pTypeInfo;
385 FARPROC16 prevHandler = NULL;
386 NE_MODULE *pModule = NE_GetPtr( hModule );
388 if (!pModule || !pModule->res_table) return NULL;
390 pResTab = (LPBYTE)pModule + pModule->res_table;
391 pTypeInfo = (NE_TYPEINFO *)(pResTab + 2);
393 TRACE("module=%04x type=%s\n", hModule, debugstr_a(typeId) );
395 for (;;)
397 if (!(pTypeInfo = NE_FindTypeSection( pResTab, pTypeInfo, typeId )))
398 break;
399 memcpy_unaligned( &prevHandler, &pTypeInfo->resloader, sizeof(FARPROC16) );
400 memcpy_unaligned( &pTypeInfo->resloader, &resourceHandler, sizeof(FARPROC16) );
401 pTypeInfo = next_typeinfo(pTypeInfo);
403 if (!prevHandler) prevHandler = get_default_res_handler();
404 return prevHandler;
408 /**********************************************************************
409 * ConvertDialog32To16 (KERNEL.615)
411 VOID WINAPI ConvertDialog32To16( LPVOID dialog32, DWORD size, LPVOID dialog16 )
413 LPVOID p = dialog32;
414 WORD nbItems, data, dialogEx;
415 DWORD style;
417 style = *((DWORD *)dialog16)++ = *((DWORD *)p)++;
418 dialogEx = (style == 0xffff0001); /* DIALOGEX resource */
419 if (dialogEx)
421 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* helpID */
422 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* exStyle */
423 style = *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* style */
425 else
426 ((DWORD *)p)++; /* exStyle ignored in 16-bit standard dialog */
428 nbItems = *((BYTE *)dialog16)++ = (BYTE)*((WORD *)p)++;
429 *((WORD *)dialog16)++ = *((WORD *)p)++; /* x */
430 *((WORD *)dialog16)++ = *((WORD *)p)++; /* y */
431 *((WORD *)dialog16)++ = *((WORD *)p)++; /* cx */
432 *((WORD *)dialog16)++ = *((WORD *)p)++; /* cy */
434 /* Transfer menu name */
435 switch (*((WORD *)p))
437 case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
438 case 0xffff: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff;
439 *((WORD *)dialog16)++ = *((WORD *)p)++; break;
440 default: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL );
441 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
442 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
443 break;
446 /* Transfer class name */
447 switch (*((WORD *)p))
449 case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
450 case 0xffff: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff;
451 *((WORD *)dialog16)++ = *((WORD *)p)++; break;
452 default: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL );
453 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
454 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
455 break;
458 /* Transfer window caption */
459 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL );
460 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
461 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
463 /* Transfer font info */
464 if (style & DS_SETFONT)
466 *((WORD *)dialog16)++ = *((WORD *)p)++; /* pointSize */
467 if (dialogEx)
469 *((WORD *)dialog16)++ = *((WORD *)p)++; /* weight */
470 *((WORD *)dialog16)++ = *((WORD *)p)++; /* italic */
472 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL ); /* faceName */
473 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
474 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
477 /* Transfer dialog items */
478 while (nbItems)
480 /* align on DWORD boundary (32-bit only) */
481 p = (LPVOID)((((int)p) + 3) & ~3);
483 if (dialogEx)
485 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* helpID */
486 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* exStyle */
487 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* style */
489 else
491 style = *((DWORD *)p)++; /* save style */
492 ((DWORD *)p)++; /* ignore exStyle */
495 *((WORD *)dialog16)++ = *((WORD *)p)++; /* x */
496 *((WORD *)dialog16)++ = *((WORD *)p)++; /* y */
497 *((WORD *)dialog16)++ = *((WORD *)p)++; /* cx */
498 *((WORD *)dialog16)++ = *((WORD *)p)++; /* cy */
500 if (dialogEx)
501 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* ID */
502 else
504 *((WORD *)dialog16)++ = *((WORD *)p)++; /* ID */
505 *((DWORD *)dialog16)++ = style; /* style from above */
508 /* Transfer class name */
509 switch (*((WORD *)p))
511 case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
512 case 0xffff: ((WORD *)p)++;
513 *((BYTE *)dialog16)++ = (BYTE)*((WORD *)p)++; break;
514 default: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL );
515 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
516 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
517 break;
520 /* Transfer window name */
521 switch (*((WORD *)p))
523 case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
524 case 0xffff: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff;
525 *((WORD *)dialog16)++ = *((WORD *)p)++; break;
526 default: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL );
527 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
528 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
529 break;
532 /* Transfer data */
533 data = *((WORD *)p)++;
534 if (dialogEx)
535 *((WORD *)dialog16)++ = data;
536 else
537 *((BYTE *)dialog16)++ = (BYTE)data;
539 if (data)
541 memcpy( dialog16, p, data );
542 (LPSTR)dialog16 += data;
543 (LPSTR)p += data;
546 /* Next item */
547 nbItems--;
552 /**********************************************************************
553 * GetDialog32Size (KERNEL.618)
555 WORD WINAPI GetDialog32Size16( LPVOID dialog32 )
557 LPVOID p = dialog32;
558 WORD nbItems, data, dialogEx;
559 DWORD style;
561 style = *((DWORD *)p)++;
562 dialogEx = (style == 0xffff0001); /* DIALOGEX resource */
563 if (dialogEx)
565 ((DWORD *)p)++; /* helpID */
566 ((DWORD *)p)++; /* exStyle */
567 style = *((DWORD *)p)++; /* style */
569 else
570 ((DWORD *)p)++; /* exStyle */
572 nbItems = *((WORD *)p)++;
573 ((WORD *)p)++; /* x */
574 ((WORD *)p)++; /* y */
575 ((WORD *)p)++; /* cx */
576 ((WORD *)p)++; /* cy */
578 /* Skip menu name */
579 switch (*((WORD *)p))
581 case 0x0000: ((WORD *)p)++; break;
582 case 0xffff: ((WORD *)p) += 2; break;
583 default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
586 /* Skip class name */
587 switch (*((WORD *)p))
589 case 0x0000: ((WORD *)p)++; break;
590 case 0xffff: ((WORD *)p) += 2; break;
591 default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
594 /* Skip window caption */
595 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
597 /* Skip font info */
598 if (style & DS_SETFONT)
600 ((WORD *)p)++; /* pointSize */
601 if (dialogEx)
603 ((WORD *)p)++; /* weight */
604 ((WORD *)p)++; /* italic */
606 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; /* faceName */
609 /* Skip dialog items */
610 while (nbItems)
612 /* align on DWORD boundary */
613 p = (LPVOID)((((int)p) + 3) & ~3);
615 if (dialogEx)
617 ((DWORD *)p)++; /* helpID */
618 ((DWORD *)p)++; /* exStyle */
619 ((DWORD *)p)++; /* style */
621 else
623 ((DWORD *)p)++; /* style */
624 ((DWORD *)p)++; /* exStyle */
627 ((WORD *)p)++; /* x */
628 ((WORD *)p)++; /* y */
629 ((WORD *)p)++; /* cx */
630 ((WORD *)p)++; /* cy */
632 if (dialogEx)
633 ((DWORD *)p)++; /* ID */
634 else
635 ((WORD *)p)++; /* ID */
637 /* Skip class name */
638 switch (*((WORD *)p))
640 case 0x0000: ((WORD *)p)++; break;
641 case 0xffff: ((WORD *)p) += 2; break;
642 default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
645 /* Skip window name */
646 switch (*((WORD *)p))
648 case 0x0000: ((WORD *)p)++; break;
649 case 0xffff: ((WORD *)p) += 2; break;
650 default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
653 /* Skip data */
654 data = *((WORD *)p)++;
655 (LPSTR)p += data;
657 /* Next item */
658 nbItems--;
661 return (WORD)((LPSTR)p - (LPSTR)dialog32);
665 /**********************************************************************
666 * ConvertMenu32To16 (KERNEL.616)
668 VOID WINAPI ConvertMenu32To16( LPVOID menu32, DWORD size, LPVOID menu16 )
670 LPVOID p = menu32;
671 WORD version, headersize, flags, level = 1;
673 version = *((WORD *)menu16)++ = *((WORD *)p)++;
674 headersize = *((WORD *)menu16)++ = *((WORD *)p)++;
675 if ( headersize )
677 memcpy( menu16, p, headersize );
678 ((LPSTR)menu16) += headersize;
679 ((LPSTR)p) += headersize;
682 while ( level )
683 if ( version == 0 ) /* standard */
685 flags = *((WORD *)menu16)++ = *((WORD *)p)++;
686 if ( !(flags & MF_POPUP) )
687 *((WORD *)menu16)++ = *((WORD *)p)++; /* ID */
688 else
689 level++;
691 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)menu16, 0x7fffffff, NULL,NULL );
692 ((LPSTR)menu16) += strlen( (LPSTR)menu16 ) + 1;
693 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
695 if ( flags & MF_END )
696 level--;
698 else /* extended */
700 *((DWORD *)menu16)++ = *((DWORD *)p)++; /* fType */
701 *((DWORD *)menu16)++ = *((DWORD *)p)++; /* fState */
702 *((WORD *)menu16)++ = (WORD)*((DWORD *)p)++; /* ID */
703 flags = *((BYTE *)menu16)++ = (BYTE)*((WORD *)p)++;
705 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)menu16, 0x7fffffff, NULL,NULL );
706 ((LPSTR)menu16) += strlen( (LPSTR)menu16 ) + 1;
707 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
709 /* align on DWORD boundary (32-bit only) */
710 p = (LPVOID)((((int)p) + 3) & ~3);
712 /* If popup, transfer helpid */
713 if ( flags & 1)
715 *((DWORD *)menu16)++ = *((DWORD *)p)++;
716 level++;
719 if ( flags & MF_END )
720 level--;
725 /**********************************************************************
726 * GetMenu32Size (KERNEL.617)
728 WORD WINAPI GetMenu32Size16( LPVOID menu32 )
730 LPVOID p = menu32;
731 WORD version, headersize, flags, level = 1;
733 version = *((WORD *)p)++;
734 headersize = *((WORD *)p)++;
735 ((LPSTR)p) += headersize;
737 while ( level )
738 if ( version == 0 ) /* standard */
740 flags = *((WORD *)p)++;
741 if ( !(flags & MF_POPUP) )
742 ((WORD *)p)++; /* ID */
743 else
744 level++;
746 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
748 if ( flags & MF_END )
749 level--;
751 else /* extended */
753 ((DWORD *)p)++; /* fType */
754 ((DWORD *)p)++; /* fState */
755 ((DWORD *)p)++; /* ID */
756 flags = *((WORD *)p)++;
758 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
760 /* align on DWORD boundary (32-bit only) */
761 p = (LPVOID)((((int)p) + 3) & ~3);
763 /* If popup, skip helpid */
764 if ( flags & 1)
766 ((DWORD *)p)++;
767 level++;
770 if ( flags & MF_END )
771 level--;
774 return (WORD)((LPSTR)p - (LPSTR)menu32);
778 /**********************************************************************
779 * ConvertAccelerator32To16
781 static void ConvertAccelerator32To16( LPVOID acc32, DWORD size, LPVOID acc16 )
783 int type;
787 /* Copy type */
788 type = *((BYTE *)acc16)++ = *((BYTE *)acc32)++;
789 /* Skip padding */
790 ((BYTE *)acc32)++;
791 /* Copy event and IDval */
792 *((WORD *)acc16)++ = *((WORD *)acc32)++;
793 *((WORD *)acc16)++ = *((WORD *)acc32)++;
794 /* Skip padding */
795 ((WORD *)acc32)++;
797 } while ( !( type & 0x80 ) );
801 /**********************************************************************
802 * NE_LoadPEResource
804 static HGLOBAL16 NE_LoadPEResource( NE_MODULE *pModule, WORD type, LPVOID bits, DWORD size )
806 HGLOBAL16 handle;
808 TRACE("module=%04x type=%04x\n", pModule->self, type );
810 handle = GlobalAlloc16( 0, size );
812 switch (type)
814 case RT_MENU:
815 ConvertMenu32To16( bits, size, GlobalLock16( handle ) );
816 break;
817 case RT_DIALOG:
818 ConvertDialog32To16( bits, size, GlobalLock16( handle ) );
819 break;
820 case RT_ACCELERATOR:
821 ConvertAccelerator32To16( bits, size, GlobalLock16( handle ) );
822 break;
823 case RT_STRING:
824 FIXME("not yet implemented!\n" );
825 /* fall through */
826 default:
827 memcpy( GlobalLock16( handle ), bits, size );
828 break;
830 return handle;
834 /**********************************************************************
835 * AllocResource (KERNEL.66)
837 HGLOBAL16 WINAPI AllocResource16( HMODULE16 hModule, HRSRC16 hRsrc, DWORD size)
839 NE_NAMEINFO *pNameInfo=NULL;
840 WORD sizeShift;
841 HGLOBAL16 ret;
843 NE_MODULE *pModule = NE_GetPtr( hModule );
844 if (!pModule || !pModule->res_table || !hRsrc) return 0;
846 TRACE("module=%04x res=%04x size=%ld\n", hModule, hRsrc, size );
848 sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
849 pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
850 if (size < (DWORD)pNameInfo->length << sizeShift)
851 size = (DWORD)pNameInfo->length << sizeShift;
852 ret = GlobalAlloc16( GMEM_FIXED, size );
853 if (ret) FarSetOwner16( ret, hModule );
854 return ret;
858 /**********************************************************************
859 * DirectResAlloc (KERNEL.168)
861 * Check Schulman, p. 232 for details
863 HGLOBAL16 WINAPI DirectResAlloc16( HINSTANCE16 hInstance, WORD wType,
864 UINT16 wSize )
866 HGLOBAL16 ret;
867 TRACE("(%04x,%04x,%04x)\n", hInstance, wType, wSize );
868 if (!(hInstance = GetExePtr( hInstance ))) return 0;
869 if(wType != 0x10) /* 0x10 is the only observed value, passed from
870 CreateCursorIndirect. */
871 TRACE("(wType=%x)\n", wType);
872 ret = GlobalAlloc16( GMEM_MOVEABLE, wSize );
873 if (ret) FarSetOwner16( ret, hInstance );
874 return ret;
878 /**********************************************************************
879 * AccessResource (KERNEL.64)
881 INT16 WINAPI AccessResource16( HINSTANCE16 hModule, HRSRC16 hRsrc )
883 HFILE16 fd;
884 NE_MODULE *pModule = NE_GetPtr( hModule );
886 if (!pModule || !pModule->res_table || !hRsrc) return -1;
888 TRACE("module=%04x res=%04x\n", pModule->self, hRsrc );
890 if ((fd = _lopen16( NE_MODULE_NAME(pModule), OF_READ )) != HFILE_ERROR16)
892 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
893 NE_NAMEINFO *pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
894 _llseek16( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
896 return fd;
900 /**********************************************************************
901 * FindResource (KERNEL.60)
903 HRSRC16 WINAPI FindResource16( HMODULE16 hModule, LPCSTR name, LPCSTR type )
905 NE_TYPEINFO *pTypeInfo;
906 NE_NAMEINFO *pNameInfo;
907 LPBYTE pResTab;
908 NE_MODULE *pModule = get_module( hModule );
910 if (!pModule) return 0;
912 if (pModule->module32)
914 /* 32-bit PE module */
915 HRSRC hRsrc32 = FindResourceA( pModule->module32, name, type );
916 return MapHRsrc32To16( pModule, hRsrc32, HIWORD(type) ? 0 : LOWORD(type) );
919 TRACE("module=%04x name=%s type=%s\n", pModule->self, debugstr_a(name), debugstr_a(type) );
921 if (!pModule->res_table) return 0;
923 type = get_res_name( type );
924 name = get_res_name( name );
926 if (HIWORD(type) || HIWORD(name))
928 DWORD id = NE_FindNameTableId( pModule, type, name );
929 if (id) /* found */
931 type = (LPCSTR)(ULONG_PTR)LOWORD(id);
932 name = (LPCSTR)(ULONG_PTR)HIWORD(id);
935 pResTab = (LPBYTE)pModule + pModule->res_table;
936 pTypeInfo = (NE_TYPEINFO *)( pResTab + 2 );
938 for (;;)
940 if (!(pTypeInfo = NE_FindTypeSection( pResTab, pTypeInfo, type ))) break;
941 if ((pNameInfo = NE_FindResourceFromType( pResTab, pTypeInfo, name )))
943 TRACE(" Found id %08lx\n", (DWORD)name );
944 return (HRSRC16)( (char *)pNameInfo - (char *)pModule );
946 pTypeInfo = next_typeinfo(pTypeInfo);
948 return 0;
952 /**********************************************************************
953 * LoadResource (KERNEL.61)
955 HGLOBAL16 WINAPI LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc )
957 NE_TYPEINFO *pTypeInfo;
958 NE_NAMEINFO *pNameInfo = NULL;
959 NE_MODULE *pModule = get_module( hModule );
960 int d;
962 if (!hRsrc || !pModule) return 0;
964 if (pModule->module32)
966 /* load 32-bit resource and convert it */
967 HRSRC hRsrc32 = MapHRsrc16To32( pModule, hRsrc );
968 WORD type = MapHRsrc16ToType( pModule, hRsrc );
969 HGLOBAL hMem = LoadResource( pModule->module32, hRsrc32 );
970 DWORD size = SizeofResource( pModule->module32, hRsrc32 );
971 if (!hMem) return 0;
972 return NE_LoadPEResource( pModule, type, LockResource( hMem ), size );
975 /* first, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
977 d = pModule->res_table + 2;
978 pTypeInfo = (NE_TYPEINFO *)((char *)pModule + d);
979 while( hRsrc > d )
981 if (pTypeInfo->type_id == 0) break; /* terminal entry */
982 d += sizeof(NE_TYPEINFO) + pTypeInfo->count * sizeof(NE_NAMEINFO);
983 if (hRsrc < d)
985 if( ((d - hRsrc)%sizeof(NE_NAMEINFO)) == 0 )
987 pNameInfo = (NE_NAMEINFO *)((char *)pModule + hRsrc);
988 break;
990 else break; /* NE_NAMEINFO boundary mismatch */
992 pTypeInfo = (NE_TYPEINFO *)((char *)pModule + d);
995 if (pNameInfo)
997 if (pNameInfo->handle && !(GlobalFlags16(pNameInfo->handle) & GMEM_DISCARDED))
999 pNameInfo->usage++;
1000 TRACE(" Already loaded, new count=%d\n", pNameInfo->usage );
1002 else
1004 FARPROC16 resloader;
1005 memcpy_unaligned( &resloader, &pTypeInfo->resloader, sizeof(FARPROC16) );
1006 if (resloader && resloader != get_default_res_handler())
1008 WORD args[3];
1009 DWORD ret;
1011 args[2] = pNameInfo->handle;
1012 args[1] = pModule->self;
1013 args[0] = hRsrc;
1014 WOWCallback16Ex( (DWORD)resloader, WCB16_PASCAL, sizeof(args), args, &ret );
1015 pNameInfo->handle = LOWORD(ret);
1017 else
1018 pNameInfo->handle = NE_DefResourceHandler( pNameInfo->handle, pModule->self, hRsrc );
1020 if (pNameInfo->handle)
1022 pNameInfo->usage++;
1023 pNameInfo->flags |= NE_SEGFLAGS_LOADED;
1026 return pNameInfo->handle;
1028 return 0;
1032 /**********************************************************************
1033 * LockResource (KERNEL.62)
1035 SEGPTR WINAPI WIN16_LockResource16( HGLOBAL16 handle )
1037 TRACE("(%04x)\n", handle );
1038 /* May need to reload the resource if discarded */
1039 return K32WOWGlobalLock16( handle );
1043 /**********************************************************************
1044 * LockResource16 (KERNEL32.@)
1046 LPVOID WINAPI LockResource16( HGLOBAL16 handle )
1048 return MapSL( WIN16_LockResource16(handle) );
1052 /**********************************************************************
1053 * SizeofResource (KERNEL.65)
1055 DWORD WINAPI SizeofResource16( HMODULE16 hModule, HRSRC16 hRsrc )
1057 NE_MODULE *pModule = NE_GetPtr( hModule );
1059 TRACE("(%x, %x)\n", hModule, hRsrc );
1061 if (!hRsrc) return 0;
1062 if (!(pModule = get_module( hModule ))) return 0;
1063 if (pModule->res_table)
1065 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
1066 NE_NAMEINFO *pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
1067 return (DWORD)pNameInfo->length << sizeShift;
1069 if (pModule->module32)
1071 /* 32-bit PE module */
1072 return SizeofResource( pModule->module32, MapHRsrc16To32( pModule, hRsrc ) );
1074 return 0;
1078 typedef WORD (WINAPI *pDestroyIcon32Proc)( HGLOBAL16 handle, UINT16 flags );
1080 /**********************************************************************
1081 * FreeResource (KERNEL.63)
1083 BOOL16 WINAPI FreeResource16( HGLOBAL16 handle )
1085 pDestroyIcon32Proc proc;
1086 HMODULE user;
1087 NE_MODULE *pModule = NE_GetPtr( FarGetOwner16( handle ) );
1089 TRACE("(%04x)\n", handle );
1091 /* Try NE resource first */
1093 if (pModule && pModule->res_table)
1095 NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
1096 while (pTypeInfo->type_id)
1098 WORD count;
1099 NE_NAMEINFO *pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
1100 for (count = pTypeInfo->count; count > 0; count--)
1102 if (pNameInfo->handle == handle)
1104 if (pNameInfo->usage > 0) pNameInfo->usage--;
1105 if (pNameInfo->usage == 0)
1107 GlobalFree16( pNameInfo->handle );
1108 pNameInfo->handle = 0;
1109 pNameInfo->flags &= ~NE_SEGFLAGS_LOADED;
1111 return 0;
1113 pNameInfo++;
1115 pTypeInfo = (NE_TYPEINFO *)pNameInfo;
1119 /* If this failed, call USER.DestroyIcon32; this will check
1120 whether it is a shared cursor/icon; if not it will call
1121 GlobalFree16() */
1122 user = GetModuleHandleA( "user32.dll" );
1123 if (user && (proc = (pDestroyIcon32Proc)GetProcAddress( user, "DestroyIcon32" )))
1124 return proc( handle, 1 /*CID_RESOURCE*/ );
1125 else
1126 return GlobalFree16( handle );