Fixed bad non-client calculation.
[wine.git] / dlls / kernel / resource16.c
blob31af22f95a674aa23e76caa8605dcaa144059bc2
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 <stdlib.h>
28 #include <string.h>
29 #include <sys/types.h>
31 #include "windef.h"
32 #include "wownt32.h"
33 #include "wine/winbase16.h"
34 #include "wine/winuser16.h"
35 #include "wine/unicode.h"
36 #include "module.h"
37 #include "task.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(resource);
42 /* handle conversions */
43 #define HRSRC_32(h16) ((HRSRC)(ULONG_PTR)(h16))
44 #define HGLOBAL_32(h16) ((HGLOBAL)(ULONG_PTR)(h16))
46 static inline NE_MODULE *get_module( HMODULE16 mod )
48 if (!mod) mod = TASK_GetCurrent()->hModule;
49 return NE_GetPtr( mod );
52 #define HRSRC_MAP_BLOCKSIZE 16
54 typedef struct _HRSRC_ELEM
56 HRSRC hRsrc;
57 WORD type;
58 } HRSRC_ELEM;
60 typedef struct _HRSRC_MAP
62 int nAlloc;
63 int nUsed;
64 HRSRC_ELEM *elem;
65 } HRSRC_MAP;
68 /**********************************************************************
69 * MapHRsrc32To16
71 static HRSRC16 MapHRsrc32To16( NE_MODULE *pModule, HRSRC hRsrc32, WORD type )
73 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
74 HRSRC_ELEM *newElem;
75 int i;
77 /* On first call, initialize HRSRC map */
78 if ( !map )
80 if ( !(map = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HRSRC_MAP) ) ) )
82 ERR("Cannot allocate HRSRC map\n" );
83 return 0;
85 pModule->hRsrcMap = map;
88 /* Check whether HRSRC32 already in map */
89 for ( i = 0; i < map->nUsed; i++ )
90 if ( map->elem[i].hRsrc == hRsrc32 )
91 return (HRSRC16)(i + 1);
93 /* If no space left, grow table */
94 if ( map->nUsed == map->nAlloc )
96 if ( !(newElem = (HRSRC_ELEM *)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
97 map->elem,
98 (map->nAlloc + HRSRC_MAP_BLOCKSIZE)
99 * sizeof(HRSRC_ELEM) ) ))
101 ERR("Cannot grow HRSRC map\n" );
102 return 0;
104 map->elem = newElem;
105 map->nAlloc += HRSRC_MAP_BLOCKSIZE;
108 /* Add HRSRC32 to table */
109 map->elem[map->nUsed].hRsrc = hRsrc32;
110 map->elem[map->nUsed].type = type;
111 map->nUsed++;
113 return (HRSRC16)map->nUsed;
116 /**********************************************************************
117 * MapHRsrc16To32
119 static HRSRC MapHRsrc16To32( NE_MODULE *pModule, HRSRC16 hRsrc16 )
121 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
122 if ( !map || !hRsrc16 || hRsrc16 > map->nUsed ) return 0;
124 return map->elem[hRsrc16-1].hRsrc;
127 /**********************************************************************
128 * MapHRsrc16ToType
130 static WORD MapHRsrc16ToType( NE_MODULE *pModule, HRSRC16 hRsrc16 )
132 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
133 if ( !map || !hRsrc16 || hRsrc16 > map->nUsed ) return 0;
135 return map->elem[hRsrc16-1].type;
139 /**********************************************************************
140 * get_res_name
142 * Convert a resource name from '#xxx' form to numerical id.
144 static inline LPCSTR get_res_name( LPCSTR name )
146 if (HIWORD(name) && name[0] == '#') name = (LPCSTR)atoi( name + 1 );
147 return name;
151 /**********************************************************************
152 * next_typeinfo
154 static inline NE_TYPEINFO *next_typeinfo( NE_TYPEINFO *info )
156 return (NE_TYPEINFO *)((char*)(info + 1) + info->count * sizeof(NE_NAMEINFO));
160 /**********************************************************************
161 * get_default_res_handler
163 static inline FARPROC16 get_default_res_handler(void)
165 static FARPROC16 handler;
167 if (!handler) handler = GetProcAddress16( GetModuleHandle16("KERNEL"), "DefResourceHandler" );
168 return handler;
172 /***********************************************************************
173 * NE_FindNameTableId
175 * Find the type and resource id from their names.
176 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
178 static DWORD NE_FindNameTableId( NE_MODULE *pModule, LPCSTR typeId, LPCSTR resId )
180 NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
181 NE_NAMEINFO *pNameInfo;
182 HGLOBAL16 handle;
183 WORD *p;
184 DWORD ret = 0;
185 int count;
187 for (; pTypeInfo->type_id != 0;
188 pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
189 pTypeInfo->count * sizeof(NE_NAMEINFO)))
191 if (pTypeInfo->type_id != 0x800f) continue;
192 pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
193 for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
195 TRACE("NameTable entry: type=%04x id=%04x\n",
196 pTypeInfo->type_id, pNameInfo->id );
197 handle = LoadResource16( pModule->self,
198 (HRSRC16)((int)pNameInfo - (int)pModule) );
199 for(p = (WORD*)LockResource16(handle); p && *p; p = (WORD *)((char*)p+*p))
201 TRACE(" type=%04x '%s' id=%04x '%s'\n",
202 p[1], (char *)(p+3), p[2],
203 (char *)(p+3)+strlen((char *)(p+3))+1 );
204 /* Check for correct type */
206 if (p[1] & 0x8000)
208 if (!HIWORD(typeId)) continue;
209 if (strcasecmp( typeId, (char *)(p + 3) )) continue;
211 else if (HIWORD(typeId) || (((DWORD)typeId & ~0x8000)!= p[1]))
212 continue;
214 /* Now check for the id */
216 if (p[2] & 0x8000)
218 if (!HIWORD(resId)) continue;
219 if (strcasecmp( resId, (char*)(p+3)+strlen((char*)(p+3))+1 )) continue;
222 else if (HIWORD(resId) || (((DWORD)resId & ~0x8000) != p[2]))
223 continue;
225 /* If we get here, we've found the entry */
227 TRACE(" Found!\n" );
228 ret = MAKELONG( p[1], p[2] );
229 break;
231 FreeResource16( handle );
232 if (ret) return ret;
235 return 0;
239 /***********************************************************************
240 * NE_FindTypeSection
242 * Find header struct for a particular resource type.
244 static NE_TYPEINFO *NE_FindTypeSection( LPBYTE pResTab, NE_TYPEINFO *pTypeInfo, LPCSTR typeId )
246 /* start from pTypeInfo */
248 if (HIWORD(typeId) != 0) /* Named type */
250 LPCSTR str = typeId;
251 BYTE len = strlen( str );
252 while (pTypeInfo->type_id)
254 if (!(pTypeInfo->type_id & 0x8000))
256 BYTE *p = pResTab + pTypeInfo->type_id;
257 if ((*p == len) && !strncasecmp( p+1, str, len ))
259 TRACE(" Found type '%s'\n", str );
260 return pTypeInfo;
263 TRACE(" Skipping type %04x\n", pTypeInfo->type_id );
264 pTypeInfo = next_typeinfo(pTypeInfo);
267 else /* Numeric type id */
269 WORD id = LOWORD(typeId) | 0x8000;
270 while (pTypeInfo->type_id)
272 if (pTypeInfo->type_id == id)
274 TRACE(" Found type %04x\n", id );
275 return pTypeInfo;
277 TRACE(" Skipping type %04x\n", pTypeInfo->type_id );
278 pTypeInfo = next_typeinfo(pTypeInfo);
281 return NULL;
285 /***********************************************************************
286 * NE_FindResourceFromType
288 * Find a resource once the type info structure has been found.
290 static NE_NAMEINFO *NE_FindResourceFromType( LPBYTE pResTab, NE_TYPEINFO *pTypeInfo, LPCSTR resId )
292 BYTE *p;
293 int count;
294 NE_NAMEINFO *pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
296 if (HIWORD(resId) != 0) /* Named resource */
298 LPCSTR str = resId;
299 BYTE len = strlen( str );
300 for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
302 if (pNameInfo->id & 0x8000) continue;
303 p = pResTab + pNameInfo->id;
304 if ((*p == len) && !strncasecmp( p+1, str, len ))
305 return pNameInfo;
308 else /* Numeric resource id */
310 WORD id = LOWORD(resId) | 0x8000;
311 for (count = pTypeInfo->count; count > 0; count--, pNameInfo++)
312 if (pNameInfo->id == id) return pNameInfo;
314 return NULL;
318 /***********************************************************************
319 * DefResourceHandler (KERNEL.456)
321 * This is the default LoadProc() function.
323 HGLOBAL16 WINAPI NE_DefResourceHandler( HGLOBAL16 hMemObj, HMODULE16 hModule,
324 HRSRC16 hRsrc )
326 HANDLE fd;
327 NE_MODULE* pModule = NE_GetPtr( hModule );
328 if (pModule && (pModule->flags & NE_FFLAGS_BUILTIN))
330 HGLOBAL16 handle;
331 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
332 NE_NAMEINFO* pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
334 if ( hMemObj )
335 handle = GlobalReAlloc16( hMemObj, pNameInfo->length << sizeShift, 0 );
336 else
337 handle = AllocResource16( hModule, hRsrc, 0 );
339 if ( handle )
341 /* NOTE: hRsrcMap points to start of built-in resource data */
342 memcpy( GlobalLock16( handle ),
343 (char *)pModule->hRsrcMap + (pNameInfo->offset << sizeShift),
344 pNameInfo->length << sizeShift );
346 return handle;
348 if (pModule && (fd = NE_OpenFile( pModule )) != INVALID_HANDLE_VALUE)
350 HGLOBAL16 handle;
351 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
352 NE_NAMEINFO* pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
354 TRACE("loading, pos=%d, len=%d\n",
355 (int)pNameInfo->offset << sizeShift,
356 (int)pNameInfo->length << sizeShift );
357 if( hMemObj )
358 handle = GlobalReAlloc16( hMemObj, pNameInfo->length << sizeShift, 0 );
359 else
360 handle = AllocResource16( hModule, hRsrc, 0 );
362 if( handle )
364 DWORD res;
365 SetFilePointer( fd, (int)pNameInfo->offset << sizeShift, NULL, SEEK_SET );
366 ReadFile( fd, GlobalLock16( handle ), (int)pNameInfo->length << sizeShift,
367 &res, NULL );
369 CloseHandle(fd);
370 return handle;
372 return (HGLOBAL16)0;
376 /**********************************************************************
377 * SetResourceHandler (KERNEL.67)
379 FARPROC16 WINAPI SetResourceHandler16( HMODULE16 hModule, LPCSTR typeId, FARPROC16 resourceHandler )
381 LPBYTE pResTab;
382 NE_TYPEINFO *pTypeInfo;
383 FARPROC16 prevHandler = NULL;
384 NE_MODULE *pModule = NE_GetPtr( hModule );
386 if (!pModule || !pModule->res_table) return NULL;
388 pResTab = (LPBYTE)pModule + pModule->res_table;
389 pTypeInfo = (NE_TYPEINFO *)(pResTab + 2);
391 TRACE("module=%04x type=%s\n", hModule, debugstr_a(typeId) );
393 for (;;)
395 if (!(pTypeInfo = NE_FindTypeSection( pResTab, pTypeInfo, typeId )))
396 break;
397 memcpy_unaligned( &prevHandler, &pTypeInfo->resloader, sizeof(FARPROC16) );
398 memcpy_unaligned( &pTypeInfo->resloader, &resourceHandler, sizeof(FARPROC16) );
399 pTypeInfo = next_typeinfo(pTypeInfo);
401 if (!prevHandler) prevHandler = get_default_res_handler();
402 return prevHandler;
406 /**********************************************************************
407 * ConvertDialog32To16 (KERNEL.615)
409 VOID WINAPI ConvertDialog32To16( LPVOID dialog32, DWORD size, LPVOID dialog16 )
411 LPVOID p = dialog32;
412 WORD nbItems, data, dialogEx;
413 DWORD style;
415 style = *((DWORD *)dialog16)++ = *((DWORD *)p)++;
416 dialogEx = (style == 0xffff0001); /* DIALOGEX resource */
417 if (dialogEx)
419 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* helpID */
420 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* exStyle */
421 style = *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* style */
423 else
424 ((DWORD *)p)++; /* exStyle ignored in 16-bit standard dialog */
426 nbItems = *((BYTE *)dialog16)++ = (BYTE)*((WORD *)p)++;
427 *((WORD *)dialog16)++ = *((WORD *)p)++; /* x */
428 *((WORD *)dialog16)++ = *((WORD *)p)++; /* y */
429 *((WORD *)dialog16)++ = *((WORD *)p)++; /* cx */
430 *((WORD *)dialog16)++ = *((WORD *)p)++; /* cy */
432 /* Transfer menu name */
433 switch (*((WORD *)p))
435 case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
436 case 0xffff: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff;
437 *((WORD *)dialog16)++ = *((WORD *)p)++; break;
438 default: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL );
439 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
440 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
441 break;
444 /* Transfer class name */
445 switch (*((WORD *)p))
447 case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
448 case 0xffff: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff;
449 *((WORD *)dialog16)++ = *((WORD *)p)++; break;
450 default: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL );
451 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
452 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
453 break;
456 /* Transfer window caption */
457 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL );
458 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
459 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
461 /* Transfer font info */
462 if (style & DS_SETFONT)
464 *((WORD *)dialog16)++ = *((WORD *)p)++; /* pointSize */
465 if (dialogEx)
467 *((WORD *)dialog16)++ = *((WORD *)p)++; /* weight */
468 *((WORD *)dialog16)++ = *((WORD *)p)++; /* italic */
470 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL ); /* faceName */
471 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
472 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
475 /* Transfer dialog items */
476 while (nbItems)
478 /* align on DWORD boundary (32-bit only) */
479 p = (LPVOID)((((int)p) + 3) & ~3);
481 if (dialogEx)
483 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* helpID */
484 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* exStyle */
485 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* style */
487 else
489 style = *((DWORD *)p)++; /* save style */
490 ((DWORD *)p)++; /* ignore exStyle */
493 *((WORD *)dialog16)++ = *((WORD *)p)++; /* x */
494 *((WORD *)dialog16)++ = *((WORD *)p)++; /* y */
495 *((WORD *)dialog16)++ = *((WORD *)p)++; /* cx */
496 *((WORD *)dialog16)++ = *((WORD *)p)++; /* cy */
498 if (dialogEx)
499 *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* ID */
500 else
502 *((WORD *)dialog16)++ = *((WORD *)p)++; /* ID */
503 *((DWORD *)dialog16)++ = style; /* style from above */
506 /* Transfer class name */
507 switch (*((WORD *)p))
509 case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
510 case 0xffff: ((WORD *)p)++;
511 *((BYTE *)dialog16)++ = (BYTE)*((WORD *)p)++; break;
512 default: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL );
513 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
514 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
515 break;
518 /* Transfer window name */
519 switch (*((WORD *)p))
521 case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
522 case 0xffff: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff;
523 *((WORD *)dialog16)++ = *((WORD *)p)++; break;
524 default: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL );
525 ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
526 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
527 break;
530 /* Transfer data */
531 data = *((WORD *)p)++;
532 if (dialogEx)
533 *((WORD *)dialog16)++ = data;
534 else
535 *((BYTE *)dialog16)++ = (BYTE)data;
537 if (data)
539 memcpy( dialog16, p, data );
540 (LPSTR)dialog16 += data;
541 (LPSTR)p += data;
544 /* Next item */
545 nbItems--;
550 /**********************************************************************
551 * GetDialog32Size (KERNEL.618)
553 WORD WINAPI GetDialog32Size16( LPVOID dialog32 )
555 LPVOID p = dialog32;
556 WORD nbItems, data, dialogEx;
557 DWORD style;
559 style = *((DWORD *)p)++;
560 dialogEx = (style == 0xffff0001); /* DIALOGEX resource */
561 if (dialogEx)
563 ((DWORD *)p)++; /* helpID */
564 ((DWORD *)p)++; /* exStyle */
565 style = *((DWORD *)p)++; /* style */
567 else
568 ((DWORD *)p)++; /* exStyle */
570 nbItems = *((WORD *)p)++;
571 ((WORD *)p)++; /* x */
572 ((WORD *)p)++; /* y */
573 ((WORD *)p)++; /* cx */
574 ((WORD *)p)++; /* cy */
576 /* Skip menu name */
577 switch (*((WORD *)p))
579 case 0x0000: ((WORD *)p)++; break;
580 case 0xffff: ((WORD *)p) += 2; break;
581 default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
584 /* Skip class name */
585 switch (*((WORD *)p))
587 case 0x0000: ((WORD *)p)++; break;
588 case 0xffff: ((WORD *)p) += 2; break;
589 default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
592 /* Skip window caption */
593 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
595 /* Skip font info */
596 if (style & DS_SETFONT)
598 ((WORD *)p)++; /* pointSize */
599 if (dialogEx)
601 ((WORD *)p)++; /* weight */
602 ((WORD *)p)++; /* italic */
604 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; /* faceName */
607 /* Skip dialog items */
608 while (nbItems)
610 /* align on DWORD boundary */
611 p = (LPVOID)((((int)p) + 3) & ~3);
613 if (dialogEx)
615 ((DWORD *)p)++; /* helpID */
616 ((DWORD *)p)++; /* exStyle */
617 ((DWORD *)p)++; /* style */
619 else
621 ((DWORD *)p)++; /* style */
622 ((DWORD *)p)++; /* exStyle */
625 ((WORD *)p)++; /* x */
626 ((WORD *)p)++; /* y */
627 ((WORD *)p)++; /* cx */
628 ((WORD *)p)++; /* cy */
630 if (dialogEx)
631 ((DWORD *)p)++; /* ID */
632 else
633 ((WORD *)p)++; /* ID */
635 /* Skip class name */
636 switch (*((WORD *)p))
638 case 0x0000: ((WORD *)p)++; break;
639 case 0xffff: ((WORD *)p) += 2; break;
640 default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
643 /* Skip window name */
644 switch (*((WORD *)p))
646 case 0x0000: ((WORD *)p)++; break;
647 case 0xffff: ((WORD *)p) += 2; break;
648 default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
651 /* Skip data */
652 data = *((WORD *)p)++;
653 (LPSTR)p += data;
655 /* Next item */
656 nbItems--;
659 return (WORD)((LPSTR)p - (LPSTR)dialog32);
663 /**********************************************************************
664 * ConvertMenu32To16 (KERNEL.616)
666 VOID WINAPI ConvertMenu32To16( LPVOID menu32, DWORD size, LPVOID menu16 )
668 LPVOID p = menu32;
669 WORD version, headersize, flags, level = 1;
671 version = *((WORD *)menu16)++ = *((WORD *)p)++;
672 headersize = *((WORD *)menu16)++ = *((WORD *)p)++;
673 if ( headersize )
675 memcpy( menu16, p, headersize );
676 ((LPSTR)menu16) += headersize;
677 ((LPSTR)p) += headersize;
680 while ( level )
681 if ( version == 0 ) /* standard */
683 flags = *((WORD *)menu16)++ = *((WORD *)p)++;
684 if ( !(flags & MF_POPUP) )
685 *((WORD *)menu16)++ = *((WORD *)p)++; /* ID */
686 else
687 level++;
689 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)menu16, 0x7fffffff, NULL,NULL );
690 ((LPSTR)menu16) += strlen( (LPSTR)menu16 ) + 1;
691 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
693 if ( flags & MF_END )
694 level--;
696 else /* extended */
698 *((DWORD *)menu16)++ = *((DWORD *)p)++; /* fType */
699 *((DWORD *)menu16)++ = *((DWORD *)p)++; /* fState */
700 *((WORD *)menu16)++ = (WORD)*((DWORD *)p)++; /* ID */
701 flags = *((BYTE *)menu16)++ = (BYTE)*((WORD *)p)++;
703 WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)menu16, 0x7fffffff, NULL,NULL );
704 ((LPSTR)menu16) += strlen( (LPSTR)menu16 ) + 1;
705 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
707 /* align on DWORD boundary (32-bit only) */
708 p = (LPVOID)((((int)p) + 3) & ~3);
710 /* If popup, transfer helpid */
711 if ( flags & 1)
713 *((DWORD *)menu16)++ = *((DWORD *)p)++;
714 level++;
717 if ( flags & MF_END )
718 level--;
723 /**********************************************************************
724 * GetMenu32Size (KERNEL.617)
726 WORD WINAPI GetMenu32Size16( LPVOID menu32 )
728 LPVOID p = menu32;
729 WORD version, headersize, flags, level = 1;
731 version = *((WORD *)p)++;
732 headersize = *((WORD *)p)++;
733 ((LPSTR)p) += headersize;
735 while ( level )
736 if ( version == 0 ) /* standard */
738 flags = *((WORD *)p)++;
739 if ( !(flags & MF_POPUP) )
740 ((WORD *)p)++; /* ID */
741 else
742 level++;
744 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
746 if ( flags & MF_END )
747 level--;
749 else /* extended */
751 ((DWORD *)p)++; /* fType */
752 ((DWORD *)p)++; /* fState */
753 ((DWORD *)p)++; /* ID */
754 flags = *((WORD *)p)++;
756 ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
758 /* align on DWORD boundary (32-bit only) */
759 p = (LPVOID)((((int)p) + 3) & ~3);
761 /* If popup, skip helpid */
762 if ( flags & 1)
764 ((DWORD *)p)++;
765 level++;
768 if ( flags & MF_END )
769 level--;
772 return (WORD)((LPSTR)p - (LPSTR)menu32);
776 /**********************************************************************
777 * ConvertAccelerator32To16
779 static void ConvertAccelerator32To16( LPVOID acc32, DWORD size, LPVOID acc16 )
781 int type;
785 /* Copy type */
786 type = *((BYTE *)acc16)++ = *((BYTE *)acc32)++;
787 /* Skip padding */
788 ((BYTE *)acc32)++;
789 /* Copy event and IDval */
790 *((WORD *)acc16)++ = *((WORD *)acc32)++;
791 *((WORD *)acc16)++ = *((WORD *)acc32)++;
792 /* Skip padding */
793 ((WORD *)acc32)++;
795 } while ( !( type & 0x80 ) );
799 /**********************************************************************
800 * NE_LoadPEResource
802 static HGLOBAL16 NE_LoadPEResource( NE_MODULE *pModule, WORD type, LPVOID bits, DWORD size )
804 HGLOBAL16 handle;
806 TRACE("module=%04x type=%04x\n", pModule->self, type );
808 handle = GlobalAlloc16( 0, size );
810 switch (type)
812 case RT_MENU16:
813 ConvertMenu32To16( bits, size, GlobalLock16( handle ) );
814 break;
815 case RT_DIALOG16:
816 ConvertDialog32To16( bits, size, GlobalLock16( handle ) );
817 break;
818 case RT_ACCELERATOR16:
819 ConvertAccelerator32To16( bits, size, GlobalLock16( handle ) );
820 break;
821 case RT_STRING16:
822 FIXME("not yet implemented!\n" );
823 /* fall through */
824 default:
825 memcpy( GlobalLock16( handle ), bits, size );
826 break;
828 return handle;
832 /**********************************************************************
833 * AllocResource (KERNEL.66)
835 HGLOBAL16 WINAPI AllocResource16( HMODULE16 hModule, HRSRC16 hRsrc, DWORD size)
837 NE_NAMEINFO *pNameInfo=NULL;
838 WORD sizeShift;
839 HGLOBAL16 ret;
841 NE_MODULE *pModule = NE_GetPtr( hModule );
842 if (!pModule || !pModule->res_table || !hRsrc) return 0;
844 TRACE("module=%04x res=%04x size=%ld\n", hModule, hRsrc, size );
846 sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
847 pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
848 if (size < (DWORD)pNameInfo->length << sizeShift)
849 size = (DWORD)pNameInfo->length << sizeShift;
850 ret = GlobalAlloc16( GMEM_FIXED, size );
851 if (ret) FarSetOwner16( ret, hModule );
852 return ret;
856 /**********************************************************************
857 * DirectResAlloc (KERNEL.168)
859 * Check Schulman, p. 232 for details
861 HGLOBAL16 WINAPI DirectResAlloc16( HINSTANCE16 hInstance, WORD wType,
862 UINT16 wSize )
864 HGLOBAL16 ret;
865 TRACE("(%04x,%04x,%04x)\n", hInstance, wType, wSize );
866 if (!(hInstance = GetExePtr( hInstance ))) return 0;
867 if(wType != 0x10) /* 0x10 is the only observed value, passed from
868 CreateCursorIndirect. */
869 TRACE("(wType=%x)\n", wType);
870 ret = GlobalAlloc16( GMEM_MOVEABLE, wSize );
871 if (ret) FarSetOwner16( ret, hInstance );
872 return ret;
876 /**********************************************************************
877 * AccessResource (KERNEL.64)
879 INT16 WINAPI AccessResource16( HINSTANCE16 hModule, HRSRC16 hRsrc )
881 HFILE16 fd;
882 NE_MODULE *pModule = NE_GetPtr( hModule );
884 if (!pModule || !pModule->res_table || !hRsrc) return -1;
886 TRACE("module=%04x res=%04x\n", pModule->self, hRsrc );
888 if ((fd = _lopen16( NE_MODULE_NAME(pModule), OF_READ )) != HFILE_ERROR16)
890 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
891 NE_NAMEINFO *pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
892 _llseek16( fd, (int)pNameInfo->offset << sizeShift, SEEK_SET );
894 return fd;
898 /**********************************************************************
899 * FindResource (KERNEL.60)
901 HRSRC16 WINAPI FindResource16( HMODULE16 hModule, LPCSTR name, LPCSTR type )
903 NE_TYPEINFO *pTypeInfo;
904 NE_NAMEINFO *pNameInfo;
905 LPBYTE pResTab;
906 NE_MODULE *pModule = get_module( hModule );
908 if (!pModule) return 0;
910 if (pModule->module32)
912 /* 32-bit PE module */
913 HRSRC hRsrc32 = FindResourceA( pModule->module32, name, type );
914 return MapHRsrc32To16( pModule, hRsrc32, HIWORD(type) ? 0 : LOWORD(type) );
917 TRACE("module=%04x name=%s type=%s\n", pModule->self, debugstr_a(name), debugstr_a(type) );
919 if (!pModule->res_table) return 0;
921 type = get_res_name( type );
922 name = get_res_name( name );
924 if (HIWORD(type) || HIWORD(name))
926 DWORD id = NE_FindNameTableId( pModule, type, name );
927 if (id) /* found */
929 type = (LPCSTR)(ULONG_PTR)LOWORD(id);
930 name = (LPCSTR)(ULONG_PTR)HIWORD(id);
933 pResTab = (LPBYTE)pModule + pModule->res_table;
934 pTypeInfo = (NE_TYPEINFO *)( pResTab + 2 );
936 for (;;)
938 if (!(pTypeInfo = NE_FindTypeSection( pResTab, pTypeInfo, type ))) break;
939 if ((pNameInfo = NE_FindResourceFromType( pResTab, pTypeInfo, name )))
941 TRACE(" Found id %08lx\n", (DWORD)name );
942 return (HRSRC16)( (char *)pNameInfo - (char *)pModule );
944 pTypeInfo = next_typeinfo(pTypeInfo);
946 return 0;
950 /**********************************************************************
951 * LoadResource (KERNEL.61)
953 HGLOBAL16 WINAPI LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc )
955 NE_TYPEINFO *pTypeInfo;
956 NE_NAMEINFO *pNameInfo = NULL;
957 NE_MODULE *pModule = get_module( hModule );
958 int d;
960 if (!hRsrc || !pModule) return 0;
962 if (pModule->module32)
964 /* load 32-bit resource and convert it */
965 HRSRC hRsrc32 = MapHRsrc16To32( pModule, hRsrc );
966 WORD type = MapHRsrc16ToType( pModule, hRsrc );
967 HGLOBAL hMem = LoadResource( pModule->module32, hRsrc32 );
968 DWORD size = SizeofResource( pModule->module32, hRsrc32 );
969 if (!hMem) return 0;
970 return NE_LoadPEResource( pModule, type, LockResource( hMem ), size );
973 /* first, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
975 d = pModule->res_table + 2;
976 pTypeInfo = (NE_TYPEINFO *)((char *)pModule + d);
977 while( hRsrc > d )
979 if (pTypeInfo->type_id == 0) break; /* terminal entry */
980 d += sizeof(NE_TYPEINFO) + pTypeInfo->count * sizeof(NE_NAMEINFO);
981 if (hRsrc < d)
983 if( ((d - hRsrc)%sizeof(NE_NAMEINFO)) == 0 )
985 pNameInfo = (NE_NAMEINFO *)((char *)pModule + hRsrc);
986 break;
988 else break; /* NE_NAMEINFO boundary mismatch */
990 pTypeInfo = (NE_TYPEINFO *)((char *)pModule + d);
993 if (pNameInfo)
995 if (pNameInfo->handle && !(GlobalFlags16(pNameInfo->handle) & GMEM_DISCARDED))
997 pNameInfo->usage++;
998 TRACE(" Already loaded, new count=%d\n", pNameInfo->usage );
1000 else
1002 FARPROC16 resloader;
1003 memcpy_unaligned( &resloader, &pTypeInfo->resloader, sizeof(FARPROC16) );
1004 if (resloader && resloader != get_default_res_handler())
1006 WORD args[3];
1007 DWORD ret;
1009 args[2] = pNameInfo->handle;
1010 args[1] = pModule->self;
1011 args[0] = hRsrc;
1012 WOWCallback16Ex( (DWORD)resloader, WCB16_PASCAL, sizeof(args), args, &ret );
1013 pNameInfo->handle = LOWORD(ret);
1015 else
1016 pNameInfo->handle = NE_DefResourceHandler( pNameInfo->handle, pModule->self, hRsrc );
1018 if (pNameInfo->handle)
1020 pNameInfo->usage++;
1021 pNameInfo->flags |= NE_SEGFLAGS_LOADED;
1024 return pNameInfo->handle;
1026 return 0;
1030 /**********************************************************************
1031 * LockResource (KERNEL.62)
1033 SEGPTR WINAPI WIN16_LockResource16( HGLOBAL16 handle )
1035 TRACE("(%04x)\n", handle );
1036 /* May need to reload the resource if discarded */
1037 return K32WOWGlobalLock16( handle );
1041 /**********************************************************************
1042 * LockResource16 (KERNEL32.@)
1044 LPVOID WINAPI LockResource16( HGLOBAL16 handle )
1046 return MapSL( WIN16_LockResource16(handle) );
1050 /**********************************************************************
1051 * SizeofResource (KERNEL.65)
1053 DWORD WINAPI SizeofResource16( HMODULE16 hModule, HRSRC16 hRsrc )
1055 NE_MODULE *pModule = NE_GetPtr( hModule );
1057 TRACE("(%x, %x)\n", hModule, hRsrc );
1059 if (!hRsrc) return 0;
1060 if (!(pModule = get_module( hModule ))) return 0;
1061 if (pModule->res_table)
1063 WORD sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
1064 NE_NAMEINFO *pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
1065 return (DWORD)pNameInfo->length << sizeShift;
1067 if (pModule->module32)
1069 /* 32-bit PE module */
1070 return SizeofResource( pModule->module32, MapHRsrc16To32( pModule, hRsrc ) );
1072 return 0;
1076 typedef WORD (WINAPI *pDestroyIcon32Proc)( HGLOBAL16 handle, UINT16 flags );
1078 /**********************************************************************
1079 * FreeResource (KERNEL.63)
1081 BOOL16 WINAPI FreeResource16( HGLOBAL16 handle )
1083 pDestroyIcon32Proc proc;
1084 HMODULE user;
1085 NE_MODULE *pModule = NE_GetPtr( FarGetOwner16( handle ) );
1087 TRACE("(%04x)\n", handle );
1089 /* Try NE resource first */
1091 if (pModule && pModule->res_table)
1093 NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
1094 while (pTypeInfo->type_id)
1096 WORD count;
1097 NE_NAMEINFO *pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1);
1098 for (count = pTypeInfo->count; count > 0; count--)
1100 if (pNameInfo->handle == handle)
1102 if (pNameInfo->usage > 0) pNameInfo->usage--;
1103 if (pNameInfo->usage == 0)
1105 GlobalFree16( pNameInfo->handle );
1106 pNameInfo->handle = 0;
1107 pNameInfo->flags &= ~NE_SEGFLAGS_LOADED;
1109 return 0;
1111 pNameInfo++;
1113 pTypeInfo = (NE_TYPEINFO *)pNameInfo;
1117 /* If this failed, call USER.DestroyIcon32; this will check
1118 whether it is a shared cursor/icon; if not it will call
1119 GlobalFree16() */
1120 user = GetModuleHandleA( "user32.dll" );
1121 if (user && (proc = (pDestroyIcon32Proc)GetProcAddress( user, "DestroyIcon32" )))
1122 return proc( handle, 1 /*CID_RESOURCE*/ );
1123 else
1124 return GlobalFree16( handle );