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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/port.h"
31 #include <sys/types.h>
36 #include "wine/winbase16.h"
37 #include "wine/winuser16.h"
38 #include "wine/unicode.h"
39 #include "kernel16_private.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
62 typedef struct _HRSRC_MAP
70 /**********************************************************************
73 static HRSRC16
MapHRsrc32To16( NE_MODULE
*pModule
, HRSRC hRsrc32
, WORD type
)
75 HRSRC_MAP
*map
= pModule
->rsrc32_map
;
79 /* On first call, initialize HRSRC map */
82 if ( !(map
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(HRSRC_MAP
) ) ) )
84 ERR("Cannot allocate HRSRC map\n" );
87 pModule
->rsrc32_map
= 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
)
100 newElem
= HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
101 map
->elem
, (map
->nAlloc
+ HRSRC_MAP_BLOCKSIZE
) * sizeof(HRSRC_ELEM
) );
103 newElem
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
104 (map
->nAlloc
+ HRSRC_MAP_BLOCKSIZE
) * sizeof(HRSRC_ELEM
) );
108 ERR("Cannot grow HRSRC map\n" );
112 map
->nAlloc
+= HRSRC_MAP_BLOCKSIZE
;
115 /* Add HRSRC32 to table */
116 map
->elem
[map
->nUsed
].hRsrc
= hRsrc32
;
117 map
->elem
[map
->nUsed
].type
= type
;
120 return (HRSRC16
)map
->nUsed
;
123 /**********************************************************************
126 static HRSRC
MapHRsrc16To32( NE_MODULE
*pModule
, HRSRC16 hRsrc16
)
128 HRSRC_MAP
*map
= pModule
->rsrc32_map
;
129 if ( !map
|| !hRsrc16
|| hRsrc16
> map
->nUsed
) return 0;
131 return map
->elem
[hRsrc16
-1].hRsrc
;
134 /**********************************************************************
137 static WORD
MapHRsrc16ToType( NE_MODULE
*pModule
, HRSRC16 hRsrc16
)
139 HRSRC_MAP
*map
= pModule
->rsrc32_map
;
140 if ( !map
|| !hRsrc16
|| hRsrc16
> map
->nUsed
) return 0;
142 return map
->elem
[hRsrc16
-1].type
;
146 /**********************************************************************
149 * Convert a resource name from '#xxx' form to numerical id.
151 static inline LPCSTR
get_res_name( LPCSTR name
)
153 if (HIWORD(name
) && name
[0] == '#') name
= MAKEINTRESOURCEA( atoi( name
+ 1 ) );
158 /**********************************************************************
161 static inline NE_TYPEINFO
*next_typeinfo( NE_TYPEINFO
*info
)
163 return (NE_TYPEINFO
*)((char*)(info
+ 1) + info
->count
* sizeof(NE_NAMEINFO
));
167 /**********************************************************************
168 * get_default_res_handler
170 static inline FARPROC16
get_default_res_handler(void)
172 static FARPROC16 handler
;
174 if (!handler
) handler
= GetProcAddress16( GetModuleHandle16("KERNEL"), "DefResourceHandler" );
179 /***********************************************************************
182 * Find the type and resource id from their names.
183 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
185 static DWORD
NE_FindNameTableId( NE_MODULE
*pModule
, LPCSTR typeId
, LPCSTR resId
)
187 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->ne_rsrctab
+ 2);
188 NE_NAMEINFO
*pNameInfo
;
194 for (; pTypeInfo
->type_id
!= 0;
195 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+1) +
196 pTypeInfo
->count
* sizeof(NE_NAMEINFO
)))
198 if (pTypeInfo
->type_id
!= 0x800f) continue;
199 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
200 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
202 TRACE("NameTable entry: type=%04x id=%04x\n",
203 pTypeInfo
->type_id
, pNameInfo
->id
);
204 handle
= LoadResource16( pModule
->self
,
205 (HRSRC16
)((char *)pNameInfo
- (char *)pModule
) );
206 for(p
= (WORD
*)LockResource16(handle
); p
&& *p
; p
= (WORD
*)((char*)p
+*p
))
208 TRACE(" type=%04x '%s' id=%04x '%s'\n",
209 p
[1], (char *)(p
+3), p
[2],
210 (char *)(p
+3)+strlen((char *)(p
+3))+1 );
211 /* Check for correct type */
215 if (!HIWORD(typeId
)) continue;
216 if (strcasecmp( typeId
, (char *)(p
+ 3) )) continue;
218 else if (HIWORD(typeId
) || (((DWORD
)typeId
& ~0x8000)!= p
[1]))
221 /* Now check for the id */
225 if (!HIWORD(resId
)) continue;
226 if (strcasecmp( resId
, (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
229 else if (HIWORD(resId
) || ((LOWORD(resId
) & ~0x8000) != p
[2]))
232 /* If we get here, we've found the entry */
235 ret
= MAKELONG( p
[1], p
[2] );
238 FreeResource16( handle
);
246 /***********************************************************************
249 * Find header struct for a particular resource type.
251 static NE_TYPEINFO
*NE_FindTypeSection( LPBYTE pResTab
, NE_TYPEINFO
*pTypeInfo
, LPCSTR typeId
)
253 /* start from pTypeInfo */
255 if (HIWORD(typeId
) != 0) /* Named type */
258 BYTE len
= strlen( str
);
259 while (pTypeInfo
->type_id
)
261 if (!(pTypeInfo
->type_id
& 0x8000))
263 BYTE
*p
= pResTab
+ pTypeInfo
->type_id
;
264 if ((*p
== len
) && !strncasecmp( (char*)p
+1, str
, len
))
266 TRACE(" Found type '%s'\n", str
);
270 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
271 pTypeInfo
= next_typeinfo(pTypeInfo
);
274 else /* Numeric type id */
276 WORD id
= LOWORD(typeId
) | 0x8000;
277 while (pTypeInfo
->type_id
)
279 if (pTypeInfo
->type_id
== id
)
281 TRACE(" Found type %04x\n", id
);
284 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
285 pTypeInfo
= next_typeinfo(pTypeInfo
);
292 /***********************************************************************
293 * NE_FindResourceFromType
295 * Find a resource once the type info structure has been found.
297 static NE_NAMEINFO
*NE_FindResourceFromType( LPBYTE pResTab
, NE_TYPEINFO
*pTypeInfo
, LPCSTR resId
)
301 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
303 if (HIWORD(resId
) != 0) /* Named resource */
306 BYTE len
= strlen( str
);
307 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
309 if (pNameInfo
->id
& 0x8000) continue;
310 p
= pResTab
+ pNameInfo
->id
;
311 if ((*p
== len
) && !strncasecmp( (char*)p
+1, str
, len
))
315 else /* Numeric resource id */
317 WORD id
= LOWORD(resId
) | 0x8000;
318 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
319 if (pNameInfo
->id
== id
) return pNameInfo
;
325 /***********************************************************************
326 * DefResourceHandler (KERNEL.456)
328 * This is the default LoadProc() function.
330 HGLOBAL16 WINAPI
NE_DefResourceHandler( HGLOBAL16 hMemObj
, HMODULE16 hModule
,
335 NE_NAMEINFO
* pNameInfo
;
336 NE_MODULE
* pModule
= NE_GetPtr( hModule
);
338 if (!pModule
) return 0;
340 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
341 pNameInfo
= (NE_NAMEINFO
*)((char *)pModule
+ hRsrc
);
344 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
346 handle
= AllocResource16( hModule
, hRsrc
, 0 );
350 if (!NE_READ_DATA( pModule
, GlobalLock16( handle
),
351 (int)pNameInfo
->offset
<< sizeShift
,
352 (int)pNameInfo
->length
<< sizeShift
))
354 GlobalFree16( handle
);
362 /**********************************************************************
363 * SetResourceHandler (KERNEL.67)
365 FARPROC16 WINAPI
SetResourceHandler16( HMODULE16 hModule
, LPCSTR typeId
, FARPROC16 resourceHandler
)
368 NE_TYPEINFO
*pTypeInfo
;
369 FARPROC16 prevHandler
= NULL
;
370 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
372 if (!pModule
|| !pModule
->ne_rsrctab
) return NULL
;
374 pResTab
= (LPBYTE
)pModule
+ pModule
->ne_rsrctab
;
375 pTypeInfo
= (NE_TYPEINFO
*)(pResTab
+ 2);
377 TRACE("module=%04x type=%s\n", hModule
, debugstr_a(typeId
) );
381 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, typeId
)))
383 memcpy_unaligned( &prevHandler
, &pTypeInfo
->resloader
, sizeof(FARPROC16
) );
384 memcpy_unaligned( &pTypeInfo
->resloader
, &resourceHandler
, sizeof(FARPROC16
) );
385 pTypeInfo
= next_typeinfo(pTypeInfo
);
387 if (!prevHandler
) prevHandler
= get_default_res_handler();
391 static inline DWORD
get_dword(LPVOID
*p
)
393 DWORD ret
= *(DWORD
*)*p
;
394 *p
= (DWORD
*)*p
+ 1;
398 static inline void put_dword(LPVOID
*p
, DWORD d
)
401 *p
= (DWORD
*)*p
+ 1;
404 static inline WORD
get_word(LPVOID
*p
)
406 WORD ret
= *(WORD
*)*p
;
411 static inline void put_word(LPVOID
*p
, WORD w
)
417 static inline BYTE
get_byte(LPVOID
*p
)
419 BYTE ret
= *(BYTE
*)*p
;
424 static inline void put_byte(LPVOID
*p
, BYTE b
)
430 /* convert a resource name */
431 static void convert_name( LPVOID
*dst
, LPVOID
*src
)
434 switch (*((WORD
*)*src
))
442 put_byte( dst
, 0xff );
443 put_word( dst
, get_word(src
) );
446 len
= WideCharToMultiByte( CP_ACP
, 0, *src
, -1, *dst
, 0x7fffffff, NULL
,NULL
);
447 *dst
= (char *)*dst
+ len
;
448 *src
= (WCHAR
*)*src
+ strlenW( (WCHAR
*)*src
) + 1;
453 /**********************************************************************
454 * ConvertDialog32To16 (KERNEL.615)
456 VOID WINAPI
ConvertDialog32To16( LPVOID dialog32
, DWORD size
, LPVOID dialog16
)
458 WORD nbItems
, data
, dialogEx
;
461 style
= get_dword( &dialog32
);
462 put_dword( &dialog16
, style
);
463 dialogEx
= (style
== 0xffff0001); /* DIALOGEX resource */
466 put_dword( &dialog16
, get_dword( &dialog32
) ); /* helpID */
467 put_dword( &dialog16
, get_dword( &dialog32
) ); /* exStyle */
468 style
= get_dword( &dialog32
);
469 put_dword( &dialog16
, style
); /* style */
472 dialog32
= (DWORD
*)dialog32
+ 1; /* exStyle ignored in 16-bit standard dialog */
474 nbItems
= get_word( &dialog32
);
475 put_byte( &dialog16
, nbItems
);
476 put_word( &dialog16
, get_word( &dialog32
) ); /* x */
477 put_word( &dialog16
, get_word( &dialog32
) ); /* y */
478 put_word( &dialog16
, get_word( &dialog32
) ); /* cx */
479 put_word( &dialog16
, get_word( &dialog32
) ); /* cy */
481 /* Transfer menu name */
482 convert_name( &dialog16
, &dialog32
);
484 /* Transfer class name */
485 convert_name( &dialog16
, &dialog32
);
487 /* Transfer window caption */
488 WideCharToMultiByte( CP_ACP
, 0, dialog32
, -1, dialog16
, 0x7fffffff, NULL
, NULL
);
489 dialog16
= (LPSTR
)dialog16
+ strlen( (LPSTR
)dialog16
) + 1;
490 dialog32
= (LPWSTR
)dialog32
+ strlenW( (LPWSTR
)dialog32
) + 1;
492 /* Transfer font info */
493 if (style
& DS_SETFONT
)
495 put_word( &dialog16
, get_word( &dialog32
) ); /* pointSize */
498 put_word( &dialog16
, get_word( &dialog32
) ); /* weight */
499 put_word( &dialog16
, get_word( &dialog32
) ); /* italic */
501 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)dialog32
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
, NULL
); /* faceName */
502 dialog16
= (LPSTR
)dialog16
+ strlen( (LPSTR
)dialog16
) + 1;
503 dialog32
= (LPWSTR
)dialog32
+ strlenW( (LPWSTR
)dialog32
) + 1;
506 /* Transfer dialog items */
509 /* align on DWORD boundary (32-bit only) */
510 dialog32
= (LPVOID
)(((UINT_PTR
)dialog32
+ 3) & ~3);
514 put_dword( &dialog16
, get_dword( &dialog32
) ); /* helpID */
515 put_dword( &dialog16
, get_dword( &dialog32
) ); /* exStyle */
516 put_dword( &dialog16
, get_dword( &dialog32
) ); /* style */
520 style
= get_dword( &dialog32
); /* save style */
521 dialog32
= (DWORD
*)dialog32
+ 1; /* ignore exStyle */
524 put_word( &dialog16
, get_word( &dialog32
) ); /* x */
525 put_word( &dialog16
, get_word( &dialog32
) ); /* y */
526 put_word( &dialog16
, get_word( &dialog32
) ); /* cx */
527 put_word( &dialog16
, get_word( &dialog32
) ); /* cy */
530 put_dword( &dialog16
, get_dword( &dialog32
) ); /* ID */
533 put_word( &dialog16
, get_word( &dialog32
) ); /* ID */
534 put_dword( &dialog16
, style
); /* style from above */
537 /* Transfer class name */
538 switch (*(WORD
*)dialog32
)
541 get_word( &dialog32
);
542 put_byte( &dialog16
, 0 );
545 get_word( &dialog32
);
546 put_byte( &dialog16
, get_word( &dialog32
) );
549 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)dialog32
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
, NULL
);
550 dialog16
= (LPSTR
)dialog16
+ strlen( (LPSTR
)dialog16
) + 1;
551 dialog32
= (LPWSTR
)dialog32
+ strlenW( (LPWSTR
)dialog32
) + 1;
555 /* Transfer window name */
556 convert_name( &dialog16
, &dialog32
);
559 data
= get_word( &dialog32
);
561 put_word(&dialog16
, data
);
563 put_byte(&dialog16
,(BYTE
)data
);
567 memcpy( dialog16
, dialog32
, data
);
568 dialog16
= (BYTE
*)dialog16
+ data
;
569 dialog32
= (BYTE
*)dialog32
+ data
;
578 /**********************************************************************
579 * GetDialog32Size (KERNEL.618)
581 WORD WINAPI
GetDialog32Size16( LPVOID dialog32
)
584 WORD nbItems
, data
, dialogEx
;
587 style
= get_dword(&p
);
588 dialogEx
= (style
== 0xffff0001); /* DIALOGEX resource */
591 p
= (DWORD
*)p
+ 1; /* helpID */
592 p
= (DWORD
*)p
+ 1; /* exStyle */
593 style
= get_dword(&p
); /* style */
596 p
= (DWORD
*)p
+ 1; /* exStyle */
598 nbItems
= get_word(&p
);
599 p
= (WORD
*)p
+ 1; /* x */
600 p
= (WORD
*)p
+ 1; /* y */
601 p
= (WORD
*)p
+ 1; /* cx */
602 p
= (WORD
*)p
+ 1; /* cy */
605 switch (*((WORD
*)p
))
607 case 0x0000: p
= (WORD
*)p
+ 1; break;
608 case 0xffff: p
= (WORD
*)p
+ 2; break;
609 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
612 /* Skip class name */
613 switch (*((WORD
*)p
))
615 case 0x0000: p
= (WORD
*)p
+ 1; break;
616 case 0xffff: p
= (WORD
*)p
+ 2; break;
617 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
620 /* Skip window caption */
621 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1;
624 if (style
& DS_SETFONT
)
626 p
= (WORD
*)p
+ 1; /* pointSize */
629 p
= (WORD
*)p
+ 1; /* weight */
630 p
= (WORD
*)p
+ 1; /* italic */
632 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; /* faceName */
635 /* Skip dialog items */
638 /* align on DWORD boundary */
639 p
= (LPVOID
)(((UINT_PTR
)p
+ 3) & ~3);
643 p
= (DWORD
*)p
+ 1; /* helpID */
644 p
= (DWORD
*)p
+ 1; /* exStyle */
645 p
= (DWORD
*)p
+ 1; /* style */
649 p
= (DWORD
*)p
+ 1; /* style */
650 p
= (DWORD
*)p
+ 1; /* exStyle */
653 p
= (WORD
*)p
+ 1; /* x */
654 p
= (WORD
*)p
+ 1; /* y */
655 p
= (WORD
*)p
+ 1; /* cx */
656 p
= (WORD
*)p
+ 1; /* cy */
659 p
= (DWORD
*)p
+ 1; /* ID */
661 p
= (WORD
*)p
+ 1; /* ID */
663 /* Skip class name */
664 switch (*((WORD
*)p
))
666 case 0x0000: p
= (WORD
*)p
+ 1; break;
667 case 0xffff: p
= (WORD
*)p
+ 2; break;
668 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
671 /* Skip window name */
672 switch (*((WORD
*)p
))
674 case 0x0000: p
= (WORD
*)p
+ 1; break;
675 case 0xffff: p
= (WORD
*)p
+ 2; break;
676 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
681 p
= (BYTE
*)p
+ data
;
687 return (WORD
)((LPSTR
)p
- (LPSTR
)dialog32
);
691 /**********************************************************************
692 * ConvertMenu32To16 (KERNEL.616)
694 VOID WINAPI
ConvertMenu32To16( LPVOID menu32
, DWORD size
, LPVOID menu16
)
696 WORD version
, headersize
, flags
, level
= 1;
698 version
= get_word( &menu32
);
699 headersize
= get_word( &menu32
);
700 put_word( &menu16
, version
);
701 put_word( &menu16
, headersize
);
704 memcpy( menu16
, menu32
, headersize
);
705 menu16
= (BYTE
*)menu16
+ headersize
;
706 menu32
= (BYTE
*)menu32
+ headersize
;
710 if ( version
== 0 ) /* standard */
712 flags
= get_word( &menu32
);
713 put_word( &menu16
, flags
);
714 if ( !(flags
& MF_POPUP
) )
715 put_word( &menu16
, get_word( &menu32
) ); /* ID */
719 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)menu32
, -1, (LPSTR
)menu16
, 0x7fffffff, NULL
, NULL
);
720 menu16
= (LPSTR
)menu16
+ strlen( (LPSTR
)menu16
) + 1;
721 menu32
= (LPWSTR
)menu32
+ strlenW( (LPWSTR
)menu32
) + 1;
723 if ( flags
& MF_END
)
728 put_dword( &menu16
, get_dword( &menu32
) ); /* fType */
729 put_dword( &menu16
, get_dword( &menu32
) ); /* fState */
730 put_word( &menu16
, get_dword( &menu32
) ); /* ID */
731 flags
= get_word( &menu32
);
732 put_byte(&menu16
,flags
);
734 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)menu32
, -1, (LPSTR
)menu16
, 0x7fffffff, NULL
, NULL
);
735 menu16
= (LPSTR
)menu16
+ strlen( (LPSTR
)menu16
) + 1;
736 menu32
= (LPWSTR
)menu32
+ strlenW( (LPWSTR
)menu32
) + 1;
738 /* align on DWORD boundary (32-bit only) */
739 menu32
= (LPVOID
)(((UINT_PTR
)menu32
+ 3) & ~3);
741 /* If popup, transfer helpid */
744 put_dword( &menu16
, get_dword( &menu32
) );
748 if ( flags
& MF_END
)
754 /**********************************************************************
755 * GetMenu32Size (KERNEL.617)
757 WORD WINAPI
GetMenu32Size16( LPVOID menu32
)
760 WORD version
, headersize
, flags
, level
= 1;
762 version
= get_word(&p
);
763 headersize
= get_word(&p
);
764 p
= (BYTE
*)p
+ headersize
;
767 if ( version
== 0 ) /* standard */
769 flags
= get_word(&p
);
770 if ( !(flags
& MF_POPUP
) )
771 p
= (WORD
*)p
+ 1; /* ID */
775 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1;
777 if ( flags
& MF_END
)
782 p
= (DWORD
*)p
+ 1; /* fType */
783 p
= (DWORD
*)p
+ 1; /* fState */
784 p
= (DWORD
*)p
+ 1; /* ID */
785 flags
= get_word(&p
);
787 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1;
789 /* align on DWORD boundary (32-bit only) */
790 p
= (LPVOID
)(((UINT_PTR
)p
+ 3) & ~3);
792 /* If popup, skip helpid */
799 if ( flags
& MF_END
)
803 return (WORD
)((LPSTR
)p
- (LPSTR
)menu32
);
807 /**********************************************************************
808 * ConvertAccelerator32To16
810 static void ConvertAccelerator32To16( LPVOID acc32
, DWORD size
, LPVOID acc16
)
817 type
= get_byte(&acc32
);
818 put_byte(&acc16
, type
);
821 /* Copy event and IDval */
822 put_word(&acc16
, get_word(&acc32
));
823 put_word(&acc16
, get_word(&acc32
));
827 } while ( !( type
& 0x80 ) );
831 /**********************************************************************
834 static HGLOBAL16
NE_LoadPEResource( NE_MODULE
*pModule
, WORD type
, LPVOID bits
, DWORD size
)
838 TRACE("module=%04x type=%04x\n", pModule
->self
, type
);
840 handle
= GlobalAlloc16( 0, size
);
845 ConvertMenu32To16( bits
, size
, GlobalLock16( handle
) );
848 ConvertDialog32To16( bits
, size
, GlobalLock16( handle
) );
851 ConvertAccelerator32To16( bits
, size
, GlobalLock16( handle
) );
854 FIXME("not yet implemented!\n" );
857 memcpy( GlobalLock16( handle
), bits
, size
);
864 /**********************************************************************
865 * AllocResource (KERNEL.66)
867 HGLOBAL16 WINAPI
AllocResource16( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
869 NE_NAMEINFO
*pNameInfo
=NULL
;
873 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
874 if (!pModule
|| !pModule
->ne_rsrctab
|| !hRsrc
) return 0;
876 TRACE("module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
878 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
879 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
880 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
881 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
882 ret
= GlobalAlloc16( GMEM_FIXED
, size
);
883 if (ret
) FarSetOwner16( ret
, hModule
);
888 /**********************************************************************
889 * DirectResAlloc (KERNEL.168)
891 * Check Schulman, p. 232 for details
893 HGLOBAL16 WINAPI
DirectResAlloc16( HINSTANCE16 hInstance
, WORD wType
,
897 TRACE("(%04x,%04x,%04x)\n", hInstance
, wType
, wSize
);
898 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
899 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
900 CreateCursorIndirect. */
901 TRACE("(wType=%x)\n", wType
);
902 ret
= GlobalAlloc16( GMEM_MOVEABLE
, wSize
);
903 if (ret
) FarSetOwner16( ret
, hInstance
);
908 /**********************************************************************
909 * AccessResource (KERNEL.64)
911 INT16 WINAPI
AccessResource16( HINSTANCE16 hModule
, HRSRC16 hRsrc
)
914 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
916 if (!pModule
|| !pModule
->ne_rsrctab
|| !hRsrc
) return -1;
918 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
920 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
922 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
923 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
924 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
930 /**********************************************************************
931 * FindResource (KERNEL.60)
933 HRSRC16 WINAPI
FindResource16( HMODULE16 hModule
, LPCSTR name
, LPCSTR type
)
935 NE_TYPEINFO
*pTypeInfo
;
936 NE_NAMEINFO
*pNameInfo
;
938 NE_MODULE
*pModule
= get_module( hModule
);
940 if (!pModule
) return 0;
942 if (pModule
->module32
)
944 /* 32-bit PE module */
945 HRSRC hRsrc32
= FindResourceA( pModule
->module32
, name
, type
);
946 return MapHRsrc32To16( pModule
, hRsrc32
, HIWORD(type
) ? 0 : LOWORD(type
) );
949 TRACE("module=%04x name=%s type=%s\n", pModule
->self
, debugstr_a(name
), debugstr_a(type
) );
951 if (!pModule
->ne_rsrctab
) return 0;
953 type
= get_res_name( type
);
954 name
= get_res_name( name
);
956 if (HIWORD(type
) || HIWORD(name
))
958 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
961 type
= (LPCSTR
)(ULONG_PTR
)LOWORD(id
);
962 name
= (LPCSTR
)(ULONG_PTR
)HIWORD(id
);
965 pResTab
= (LPBYTE
)pModule
+ pModule
->ne_rsrctab
;
966 pTypeInfo
= (NE_TYPEINFO
*)( pResTab
+ 2 );
970 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, type
))) break;
971 if ((pNameInfo
= NE_FindResourceFromType( pResTab
, pTypeInfo
, name
)))
973 TRACE(" Found id %p\n", name
);
974 return (HRSRC16
)( (char *)pNameInfo
- (char *)pModule
);
976 pTypeInfo
= next_typeinfo(pTypeInfo
);
982 /**********************************************************************
983 * LoadResource (KERNEL.61)
985 HGLOBAL16 WINAPI
LoadResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
987 NE_TYPEINFO
*pTypeInfo
;
988 NE_NAMEINFO
*pNameInfo
= NULL
;
989 NE_MODULE
*pModule
= get_module( hModule
);
992 if (!hRsrc
|| !pModule
) return 0;
994 if (pModule
->module32
)
996 /* load 32-bit resource and convert it */
997 HRSRC hRsrc32
= MapHRsrc16To32( pModule
, hRsrc
);
998 WORD type
= MapHRsrc16ToType( pModule
, hRsrc
);
999 HGLOBAL hMem
= LoadResource( pModule
->module32
, hRsrc32
);
1000 DWORD size
= SizeofResource( pModule
->module32
, hRsrc32
);
1001 if (!hMem
) return 0;
1002 return NE_LoadPEResource( pModule
, type
, LockResource( hMem
), size
);
1005 /* first, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
1007 d
= pModule
->ne_rsrctab
+ 2;
1008 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
1011 if (pTypeInfo
->type_id
== 0) break; /* terminal entry */
1012 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
1015 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
1017 pNameInfo
= (NE_NAMEINFO
*)((char *)pModule
+ hRsrc
);
1020 else break; /* NE_NAMEINFO boundary mismatch */
1022 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
1027 if (pNameInfo
->handle
&& !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
1030 TRACE(" Already loaded, new count=%d\n", pNameInfo
->usage
);
1034 FARPROC16 resloader
;
1035 memcpy_unaligned( &resloader
, &pTypeInfo
->resloader
, sizeof(FARPROC16
) );
1036 if (resloader
&& resloader
!= get_default_res_handler())
1041 args
[2] = pNameInfo
->handle
;
1042 args
[1] = pModule
->self
;
1044 WOWCallback16Ex( (DWORD
)resloader
, WCB16_PASCAL
, sizeof(args
), args
, &ret
);
1045 pNameInfo
->handle
= LOWORD(ret
);
1048 pNameInfo
->handle
= NE_DefResourceHandler( pNameInfo
->handle
, pModule
->self
, hRsrc
);
1050 if (pNameInfo
->handle
)
1053 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
1056 return pNameInfo
->handle
;
1062 /**********************************************************************
1063 * LockResource (KERNEL.62)
1065 SEGPTR WINAPI
WIN16_LockResource16( HGLOBAL16 handle
)
1067 TRACE("(%04x)\n", handle
);
1068 /* May need to reload the resource if discarded */
1069 return WOWGlobalLock16( handle
);
1073 /**********************************************************************
1074 * LockResource16 (KERNEL32.@)
1076 LPVOID WINAPI
LockResource16( HGLOBAL16 handle
)
1078 return MapSL( WIN16_LockResource16(handle
) );
1082 /**********************************************************************
1083 * SizeofResource (KERNEL.65)
1085 DWORD WINAPI
SizeofResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
1087 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
1089 TRACE("(%x, %x)\n", hModule
, hRsrc
);
1091 if (!hRsrc
) return 0;
1092 if (!(pModule
= get_module( hModule
))) return 0;
1093 if (pModule
->ne_rsrctab
)
1095 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
1096 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
1097 return (DWORD
)pNameInfo
->length
<< sizeShift
;
1099 if (pModule
->module32
)
1101 /* 32-bit PE module */
1102 return SizeofResource( pModule
->module32
, MapHRsrc16To32( pModule
, hRsrc
) );
1108 typedef WORD (WINAPI
*pDestroyIcon32Proc
)( HGLOBAL16 handle
, UINT16 flags
);
1110 /**********************************************************************
1111 * FreeResource (KERNEL.63)
1113 BOOL16 WINAPI
FreeResource16( HGLOBAL16 handle
)
1115 pDestroyIcon32Proc proc
;
1117 NE_MODULE
*pModule
= NE_GetPtr( FarGetOwner16( handle
) );
1119 TRACE("(%04x)\n", handle
);
1121 /* Try NE resource first */
1123 if (pModule
&& pModule
->ne_rsrctab
)
1125 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->ne_rsrctab
+ 2);
1126 while (pTypeInfo
->type_id
)
1129 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
1130 for (count
= pTypeInfo
->count
; count
> 0; count
--)
1132 if (pNameInfo
->handle
== handle
)
1134 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
1135 if (pNameInfo
->usage
== 0)
1137 GlobalFree16( pNameInfo
->handle
);
1138 pNameInfo
->handle
= 0;
1139 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
1145 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;
1149 /* If this failed, call USER.DestroyIcon32; this will check
1150 whether it is a shared cursor/icon; if not it will call
1152 user
= GetModuleHandleA( "user32.dll" );
1153 if (user
&& (proc
= (pDestroyIcon32Proc
)GetProcAddress( user
, "DestroyIcon32" )))
1154 return proc( handle
, 1 /*CID_RESOURCE*/ );
1156 return GlobalFree16( handle
);