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
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
= (LPCSTR
)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
)((int)pNameInfo
- (int)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
) || (((DWORD
)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( 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( 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 (pModule
->ne_flags
& NE_FFLAGS_BUILTIN
)
352 /* NOTE: hRsrcMap points to start of built-in resource data */
353 memcpy( GlobalLock16( handle
),
354 (char *)pModule
->rsrc32_map
+ (pNameInfo
->offset
<< sizeShift
),
355 pNameInfo
->length
<< sizeShift
);
359 if (!NE_READ_DATA( pModule
, GlobalLock16( handle
),
360 (int)pNameInfo
->offset
<< sizeShift
,
361 (int)pNameInfo
->length
<< sizeShift
))
363 GlobalFree16( handle
);
372 /**********************************************************************
373 * SetResourceHandler (KERNEL.67)
375 FARPROC16 WINAPI
SetResourceHandler16( HMODULE16 hModule
, LPCSTR typeId
, FARPROC16 resourceHandler
)
378 NE_TYPEINFO
*pTypeInfo
;
379 FARPROC16 prevHandler
= NULL
;
380 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
382 if (!pModule
|| !pModule
->ne_rsrctab
) return NULL
;
384 pResTab
= (LPBYTE
)pModule
+ pModule
->ne_rsrctab
;
385 pTypeInfo
= (NE_TYPEINFO
*)(pResTab
+ 2);
387 TRACE("module=%04x type=%s\n", hModule
, debugstr_a(typeId
) );
391 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, typeId
)))
393 memcpy_unaligned( &prevHandler
, &pTypeInfo
->resloader
, sizeof(FARPROC16
) );
394 memcpy_unaligned( &pTypeInfo
->resloader
, &resourceHandler
, sizeof(FARPROC16
) );
395 pTypeInfo
= next_typeinfo(pTypeInfo
);
397 if (!prevHandler
) prevHandler
= get_default_res_handler();
401 static inline DWORD
get_dword(LPVOID
*p
)
403 DWORD ret
= *(DWORD
*)*p
;
404 *p
= (DWORD
*)*p
+ 1;
408 static inline void put_dword(LPVOID
*p
, DWORD d
)
411 *p
= (DWORD
*)*p
+ 1;
414 static inline WORD
get_word(LPVOID
*p
)
416 WORD ret
= *(WORD
*)*p
;
421 static inline void put_word(LPVOID
*p
, WORD w
)
427 static inline BYTE
get_byte(LPVOID
*p
)
429 BYTE ret
= *(BYTE
*)*p
;
434 static inline void put_byte(LPVOID
*p
, BYTE b
)
440 /* convert a resource name */
441 static void convert_name( LPVOID
*dst
, LPVOID
*src
)
444 switch (*((WORD
*)*src
))
452 put_byte( dst
, 0xff );
453 put_word( dst
, get_word(src
) );
456 len
= WideCharToMultiByte( CP_ACP
, 0, *src
, -1, *dst
, 0x7fffffff, NULL
,NULL
);
457 *dst
= (char *)*dst
+ len
;
458 *src
= (WCHAR
*)*src
+ strlenW( (WCHAR
*)*src
) + 1;
463 /**********************************************************************
464 * ConvertDialog32To16 (KERNEL.615)
466 VOID WINAPI
ConvertDialog32To16( LPVOID dialog32
, DWORD size
, LPVOID dialog16
)
468 WORD nbItems
, data
, dialogEx
;
471 style
= get_dword( &dialog32
);
472 put_dword( &dialog16
, style
);
473 dialogEx
= (style
== 0xffff0001); /* DIALOGEX resource */
476 put_dword( &dialog16
, get_dword( &dialog32
) ); /* helpID */
477 put_dword( &dialog16
, get_dword( &dialog32
) ); /* exStyle */
478 style
= get_dword( &dialog32
);
479 put_dword( &dialog16
, style
); /* style */
482 dialog32
= (DWORD
*)dialog32
+ 1; /* exStyle ignored in 16-bit standard dialog */
484 nbItems
= get_word( &dialog32
);
485 put_byte( &dialog16
, nbItems
);
486 put_word( &dialog16
, get_word( &dialog32
) ); /* x */
487 put_word( &dialog16
, get_word( &dialog32
) ); /* y */
488 put_word( &dialog16
, get_word( &dialog32
) ); /* cx */
489 put_word( &dialog16
, get_word( &dialog32
) ); /* cy */
491 /* Transfer menu name */
492 convert_name( &dialog16
, &dialog32
);
494 /* Transfer class name */
495 convert_name( &dialog16
, &dialog32
);
497 /* Transfer window caption */
498 WideCharToMultiByte( CP_ACP
, 0, dialog32
, -1, dialog16
, 0x7fffffff, NULL
, NULL
);
499 dialog16
= (LPSTR
)dialog16
+ strlen( (LPSTR
)dialog16
) + 1;
500 dialog32
= (LPWSTR
)dialog32
+ strlenW( (LPWSTR
)dialog32
) + 1;
502 /* Transfer font info */
503 if (style
& DS_SETFONT
)
505 put_word( &dialog16
, get_word( &dialog32
) ); /* pointSize */
508 put_word( &dialog16
, get_word( &dialog32
) ); /* weight */
509 put_word( &dialog16
, get_word( &dialog32
) ); /* italic */
511 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)dialog32
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
, NULL
); /* faceName */
512 dialog16
= (LPSTR
)dialog16
+ strlen( (LPSTR
)dialog16
) + 1;
513 dialog32
= (LPWSTR
)dialog32
+ strlenW( (LPWSTR
)dialog32
) + 1;
516 /* Transfer dialog items */
519 /* align on DWORD boundary (32-bit only) */
520 dialog32
= (LPVOID
)((((int)dialog32
) + 3) & ~3);
524 put_dword( &dialog16
, get_dword( &dialog32
) ); /* helpID */
525 put_dword( &dialog16
, get_dword( &dialog32
) ); /* exStyle */
526 put_dword( &dialog16
, get_dword( &dialog32
) ); /* style */
530 style
= get_dword( &dialog32
); /* save style */
531 dialog32
= (DWORD
*)dialog32
+ 1; /* ignore exStyle */
534 put_word( &dialog16
, get_word( &dialog32
) ); /* x */
535 put_word( &dialog16
, get_word( &dialog32
) ); /* y */
536 put_word( &dialog16
, get_word( &dialog32
) ); /* cx */
537 put_word( &dialog16
, get_word( &dialog32
) ); /* cy */
540 put_dword( &dialog16
, get_dword( &dialog32
) ); /* ID */
543 put_word( &dialog16
, get_word( &dialog32
) ); /* ID */
544 put_dword( &dialog16
, style
); /* style from above */
547 /* Transfer class name */
548 switch (*(WORD
*)dialog32
)
551 get_word( &dialog32
);
552 put_byte( &dialog16
, 0 );
555 get_word( &dialog32
);
556 put_byte( &dialog16
, get_word( &dialog32
) );
559 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)dialog32
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
, NULL
);
560 dialog16
= (LPSTR
)dialog16
+ strlen( (LPSTR
)dialog16
) + 1;
561 dialog32
= (LPWSTR
)dialog32
+ strlenW( (LPWSTR
)dialog32
) + 1;
565 /* Transfer window name */
566 convert_name( &dialog16
, &dialog32
);
569 data
= get_word( &dialog32
);
571 put_word(&dialog16
, data
);
573 put_byte(&dialog16
,(BYTE
)data
);
577 memcpy( dialog16
, dialog32
, data
);
578 dialog16
= (BYTE
*)dialog16
+ data
;
579 dialog32
= (BYTE
*)dialog32
+ data
;
588 /**********************************************************************
589 * GetDialog32Size (KERNEL.618)
591 WORD WINAPI
GetDialog32Size16( LPVOID dialog32
)
594 WORD nbItems
, data
, dialogEx
;
597 style
= get_dword(&p
);
598 dialogEx
= (style
== 0xffff0001); /* DIALOGEX resource */
601 p
= (DWORD
*)p
+ 1; /* helpID */
602 p
= (DWORD
*)p
+ 1; /* exStyle */
603 style
= get_dword(&p
); /* style */
606 p
= (DWORD
*)p
+ 1; /* exStyle */
608 nbItems
= get_word(&p
);
609 p
= (WORD
*)p
+ 1; /* x */
610 p
= (WORD
*)p
+ 1; /* y */
611 p
= (WORD
*)p
+ 1; /* cx */
612 p
= (WORD
*)p
+ 1; /* cy */
615 switch (*((WORD
*)p
))
617 case 0x0000: p
= (WORD
*)p
+ 1; break;
618 case 0xffff: p
= (WORD
*)p
+ 2; break;
619 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
622 /* Skip class name */
623 switch (*((WORD
*)p
))
625 case 0x0000: p
= (WORD
*)p
+ 1; break;
626 case 0xffff: p
= (WORD
*)p
+ 2; break;
627 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
630 /* Skip window caption */
631 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1;
634 if (style
& DS_SETFONT
)
636 p
= (WORD
*)p
+ 1; /* pointSize */
639 p
= (WORD
*)p
+ 1; /* weight */
640 p
= (WORD
*)p
+ 1; /* italic */
642 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; /* faceName */
645 /* Skip dialog items */
648 /* align on DWORD boundary */
649 p
= (LPVOID
)((((int)p
) + 3) & ~3);
653 p
= (DWORD
*)p
+ 1; /* helpID */
654 p
= (DWORD
*)p
+ 1; /* exStyle */
655 p
= (DWORD
*)p
+ 1; /* style */
659 p
= (DWORD
*)p
+ 1; /* style */
660 p
= (DWORD
*)p
+ 1; /* exStyle */
663 p
= (WORD
*)p
+ 1; /* x */
664 p
= (WORD
*)p
+ 1; /* y */
665 p
= (WORD
*)p
+ 1; /* cx */
666 p
= (WORD
*)p
+ 1; /* cy */
669 p
= (DWORD
*)p
+ 1; /* ID */
671 p
= (WORD
*)p
+ 1; /* ID */
673 /* Skip class name */
674 switch (*((WORD
*)p
))
676 case 0x0000: p
= (WORD
*)p
+ 1; break;
677 case 0xffff: p
= (WORD
*)p
+ 2; break;
678 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
681 /* Skip window name */
682 switch (*((WORD
*)p
))
684 case 0x0000: p
= (WORD
*)p
+ 1; break;
685 case 0xffff: p
= (WORD
*)p
+ 2; break;
686 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
691 p
= (BYTE
*)p
+ data
;
697 return (WORD
)((LPSTR
)p
- (LPSTR
)dialog32
);
701 /**********************************************************************
702 * ConvertMenu32To16 (KERNEL.616)
704 VOID WINAPI
ConvertMenu32To16( LPVOID menu32
, DWORD size
, LPVOID menu16
)
706 WORD version
, headersize
, flags
, level
= 1;
708 version
= get_word( &menu32
);
709 headersize
= get_word( &menu32
);
710 put_word( &menu16
, version
);
711 put_word( &menu16
, headersize
);
714 memcpy( menu16
, menu32
, headersize
);
715 menu16
= (BYTE
*)menu16
+ headersize
;
716 menu32
= (BYTE
*)menu32
+ headersize
;
720 if ( version
== 0 ) /* standard */
722 flags
= get_word( &menu32
);
723 put_word( &menu16
, flags
);
724 if ( !(flags
& MF_POPUP
) )
725 put_word( &menu16
, get_word( &menu32
) ); /* ID */
729 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)menu32
, -1, (LPSTR
)menu16
, 0x7fffffff, NULL
, NULL
);
730 menu16
= (LPSTR
)menu16
+ strlen( (LPSTR
)menu16
) + 1;
731 menu32
= (LPWSTR
)menu32
+ strlenW( (LPWSTR
)menu32
) + 1;
733 if ( flags
& MF_END
)
738 put_dword( &menu16
, get_dword( &menu32
) ); /* fType */
739 put_dword( &menu16
, get_dword( &menu32
) ); /* fState */
740 put_word( &menu16
, get_dword( &menu32
) ); /* ID */
741 flags
= get_word( &menu32
);
742 put_byte(&menu16
,flags
);
744 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)menu32
, -1, (LPSTR
)menu16
, 0x7fffffff, NULL
, NULL
);
745 menu16
= (LPSTR
)menu16
+ strlen( (LPSTR
)menu16
) + 1;
746 menu32
= (LPWSTR
)menu32
+ strlenW( (LPWSTR
)menu32
) + 1;
748 /* align on DWORD boundary (32-bit only) */
749 menu32
= (LPVOID
)((((int)menu32
) + 3) & ~3);
751 /* If popup, transfer helpid */
754 put_dword( &menu16
, get_dword( &menu32
) );
758 if ( flags
& MF_END
)
764 /**********************************************************************
765 * GetMenu32Size (KERNEL.617)
767 WORD WINAPI
GetMenu32Size16( LPVOID menu32
)
770 WORD version
, headersize
, flags
, level
= 1;
772 version
= get_word(&p
);
773 headersize
= get_word(&p
);
774 p
= (BYTE
*)p
+ headersize
;
777 if ( version
== 0 ) /* standard */
779 flags
= get_word(&p
);
780 if ( !(flags
& MF_POPUP
) )
781 p
= (WORD
*)p
+ 1; /* ID */
785 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1;
787 if ( flags
& MF_END
)
792 p
= (DWORD
*)p
+ 1; /* fType */
793 p
= (DWORD
*)p
+ 1; /* fState */
794 p
= (DWORD
*)p
+ 1; /* ID */
795 flags
= get_word(&p
);
797 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1;
799 /* align on DWORD boundary (32-bit only) */
800 p
= (LPVOID
)((((int)p
) + 3) & ~3);
802 /* If popup, skip helpid */
809 if ( flags
& MF_END
)
813 return (WORD
)((LPSTR
)p
- (LPSTR
)menu32
);
817 /**********************************************************************
818 * ConvertAccelerator32To16
820 static void ConvertAccelerator32To16( LPVOID acc32
, DWORD size
, LPVOID acc16
)
827 type
= get_byte(&acc32
);
828 put_byte(&acc16
, type
);
831 /* Copy event and IDval */
832 put_word(&acc16
, get_word(&acc32
));
833 put_word(&acc16
, get_word(&acc32
));
837 } while ( !( type
& 0x80 ) );
841 /**********************************************************************
844 static HGLOBAL16
NE_LoadPEResource( NE_MODULE
*pModule
, WORD type
, LPVOID bits
, DWORD size
)
848 TRACE("module=%04x type=%04x\n", pModule
->self
, type
);
850 handle
= GlobalAlloc16( 0, size
);
855 ConvertMenu32To16( bits
, size
, GlobalLock16( handle
) );
858 ConvertDialog32To16( bits
, size
, GlobalLock16( handle
) );
861 ConvertAccelerator32To16( bits
, size
, GlobalLock16( handle
) );
864 FIXME("not yet implemented!\n" );
867 memcpy( GlobalLock16( handle
), bits
, size
);
874 /**********************************************************************
875 * AllocResource (KERNEL.66)
877 HGLOBAL16 WINAPI
AllocResource16( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
879 NE_NAMEINFO
*pNameInfo
=NULL
;
883 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
884 if (!pModule
|| !pModule
->ne_rsrctab
|| !hRsrc
) return 0;
886 TRACE("module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
888 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
889 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
890 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
891 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
892 ret
= GlobalAlloc16( GMEM_FIXED
, size
);
893 if (ret
) FarSetOwner16( ret
, hModule
);
898 /**********************************************************************
899 * DirectResAlloc (KERNEL.168)
901 * Check Schulman, p. 232 for details
903 HGLOBAL16 WINAPI
DirectResAlloc16( HINSTANCE16 hInstance
, WORD wType
,
907 TRACE("(%04x,%04x,%04x)\n", hInstance
, wType
, wSize
);
908 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
909 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
910 CreateCursorIndirect. */
911 TRACE("(wType=%x)\n", wType
);
912 ret
= GlobalAlloc16( GMEM_MOVEABLE
, wSize
);
913 if (ret
) FarSetOwner16( ret
, hInstance
);
918 /**********************************************************************
919 * AccessResource (KERNEL.64)
921 INT16 WINAPI
AccessResource16( HINSTANCE16 hModule
, HRSRC16 hRsrc
)
924 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
926 if (!pModule
|| !pModule
->ne_rsrctab
|| !hRsrc
) return -1;
928 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
930 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
932 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
933 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
934 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
940 /**********************************************************************
941 * FindResource (KERNEL.60)
943 HRSRC16 WINAPI
FindResource16( HMODULE16 hModule
, LPCSTR name
, LPCSTR type
)
945 NE_TYPEINFO
*pTypeInfo
;
946 NE_NAMEINFO
*pNameInfo
;
948 NE_MODULE
*pModule
= get_module( hModule
);
950 if (!pModule
) return 0;
952 if (pModule
->module32
)
954 /* 32-bit PE module */
955 HRSRC hRsrc32
= FindResourceA( pModule
->module32
, name
, type
);
956 return MapHRsrc32To16( pModule
, hRsrc32
, HIWORD(type
) ? 0 : LOWORD(type
) );
959 TRACE("module=%04x name=%s type=%s\n", pModule
->self
, debugstr_a(name
), debugstr_a(type
) );
961 if (!pModule
->ne_rsrctab
) return 0;
963 type
= get_res_name( type
);
964 name
= get_res_name( name
);
966 if (HIWORD(type
) || HIWORD(name
))
968 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
971 type
= (LPCSTR
)(ULONG_PTR
)LOWORD(id
);
972 name
= (LPCSTR
)(ULONG_PTR
)HIWORD(id
);
975 pResTab
= (LPBYTE
)pModule
+ pModule
->ne_rsrctab
;
976 pTypeInfo
= (NE_TYPEINFO
*)( pResTab
+ 2 );
980 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, type
))) break;
981 if ((pNameInfo
= NE_FindResourceFromType( pResTab
, pTypeInfo
, name
)))
983 TRACE(" Found id %08lx\n", (DWORD
)name
);
984 return (HRSRC16
)( (char *)pNameInfo
- (char *)pModule
);
986 pTypeInfo
= next_typeinfo(pTypeInfo
);
992 /**********************************************************************
993 * LoadResource (KERNEL.61)
995 HGLOBAL16 WINAPI
LoadResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
997 NE_TYPEINFO
*pTypeInfo
;
998 NE_NAMEINFO
*pNameInfo
= NULL
;
999 NE_MODULE
*pModule
= get_module( hModule
);
1002 if (!hRsrc
|| !pModule
) return 0;
1004 if (pModule
->module32
)
1006 /* load 32-bit resource and convert it */
1007 HRSRC hRsrc32
= MapHRsrc16To32( pModule
, hRsrc
);
1008 WORD type
= MapHRsrc16ToType( pModule
, hRsrc
);
1009 HGLOBAL hMem
= LoadResource( pModule
->module32
, hRsrc32
);
1010 DWORD size
= SizeofResource( pModule
->module32
, hRsrc32
);
1011 if (!hMem
) return 0;
1012 return NE_LoadPEResource( pModule
, type
, LockResource( hMem
), size
);
1015 /* first, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
1017 d
= pModule
->ne_rsrctab
+ 2;
1018 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
1021 if (pTypeInfo
->type_id
== 0) break; /* terminal entry */
1022 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
1025 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
1027 pNameInfo
= (NE_NAMEINFO
*)((char *)pModule
+ hRsrc
);
1030 else break; /* NE_NAMEINFO boundary mismatch */
1032 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
1037 if (pNameInfo
->handle
&& !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
1040 TRACE(" Already loaded, new count=%d\n", pNameInfo
->usage
);
1044 FARPROC16 resloader
;
1045 memcpy_unaligned( &resloader
, &pTypeInfo
->resloader
, sizeof(FARPROC16
) );
1046 if (resloader
&& resloader
!= get_default_res_handler())
1051 args
[2] = pNameInfo
->handle
;
1052 args
[1] = pModule
->self
;
1054 WOWCallback16Ex( (DWORD
)resloader
, WCB16_PASCAL
, sizeof(args
), args
, &ret
);
1055 pNameInfo
->handle
= LOWORD(ret
);
1058 pNameInfo
->handle
= NE_DefResourceHandler( pNameInfo
->handle
, pModule
->self
, hRsrc
);
1060 if (pNameInfo
->handle
)
1063 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
1066 return pNameInfo
->handle
;
1072 /**********************************************************************
1073 * LockResource (KERNEL.62)
1075 SEGPTR WINAPI
WIN16_LockResource16( HGLOBAL16 handle
)
1077 TRACE("(%04x)\n", handle
);
1078 /* May need to reload the resource if discarded */
1079 return K32WOWGlobalLock16( handle
);
1083 /**********************************************************************
1084 * LockResource16 (KERNEL32.@)
1086 LPVOID WINAPI
LockResource16( HGLOBAL16 handle
)
1088 return MapSL( WIN16_LockResource16(handle
) );
1092 /**********************************************************************
1093 * SizeofResource (KERNEL.65)
1095 DWORD WINAPI
SizeofResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
1097 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
1099 TRACE("(%x, %x)\n", hModule
, hRsrc
);
1101 if (!hRsrc
) return 0;
1102 if (!(pModule
= get_module( hModule
))) return 0;
1103 if (pModule
->ne_rsrctab
)
1105 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
1106 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
1107 return (DWORD
)pNameInfo
->length
<< sizeShift
;
1109 if (pModule
->module32
)
1111 /* 32-bit PE module */
1112 return SizeofResource( pModule
->module32
, MapHRsrc16To32( pModule
, hRsrc
) );
1118 typedef WORD (WINAPI
*pDestroyIcon32Proc
)( HGLOBAL16 handle
, UINT16 flags
);
1120 /**********************************************************************
1121 * FreeResource (KERNEL.63)
1123 BOOL16 WINAPI
FreeResource16( HGLOBAL16 handle
)
1125 pDestroyIcon32Proc proc
;
1127 NE_MODULE
*pModule
= NE_GetPtr( FarGetOwner16( handle
) );
1129 TRACE("(%04x)\n", handle
);
1131 /* Try NE resource first */
1133 if (pModule
&& pModule
->ne_rsrctab
)
1135 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->ne_rsrctab
+ 2);
1136 while (pTypeInfo
->type_id
)
1139 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
1140 for (count
= pTypeInfo
->count
; count
> 0; count
--)
1142 if (pNameInfo
->handle
== handle
)
1144 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
1145 if (pNameInfo
->usage
== 0)
1147 GlobalFree16( pNameInfo
->handle
);
1148 pNameInfo
->handle
= 0;
1149 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
1155 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;
1159 /* If this failed, call USER.DestroyIcon32; this will check
1160 whether it is a shared cursor/icon; if not it will call
1162 user
= GetModuleHandleA( "user32.dll" );
1163 if (user
&& (proc
= (pDestroyIcon32Proc
)GetProcAddress( user
, "DestroyIcon32" )))
1164 return proc( handle
, 1 /*CID_RESOURCE*/ );
1166 return GlobalFree16( handle
);