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"
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
= (HRSRC_MAP
*)pModule
->hRsrcMap
;
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
->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
)
100 newElem
= (HRSRC_ELEM
*)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
101 map
->elem
, (map
->nAlloc
+ HRSRC_MAP_BLOCKSIZE
) * sizeof(HRSRC_ELEM
) );
103 newElem
= (HRSRC_ELEM
*)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
= (HRSRC_MAP
*)pModule
->hRsrcMap
;
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
= (HRSRC_MAP
*)pModule
->hRsrcMap
;
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
->res_table
+ 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
,
334 NE_MODULE
* pModule
= NE_GetPtr( hModule
);
335 if (pModule
&& (pModule
->flags
& NE_FFLAGS_BUILTIN
))
338 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
339 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
342 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
344 handle
= AllocResource16( hModule
, hRsrc
, 0 );
348 /* NOTE: hRsrcMap points to start of built-in resource data */
349 memcpy( GlobalLock16( handle
),
350 (char *)pModule
->hRsrcMap
+ (pNameInfo
->offset
<< sizeShift
),
351 pNameInfo
->length
<< sizeShift
);
355 if (pModule
&& (fd
= NE_OpenFile( pModule
)) != INVALID_HANDLE_VALUE
)
358 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
359 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
361 TRACE("loading, pos=%d, len=%d\n",
362 (int)pNameInfo
->offset
<< sizeShift
,
363 (int)pNameInfo
->length
<< sizeShift
);
365 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
367 handle
= AllocResource16( hModule
, hRsrc
, 0 );
372 SetFilePointer( fd
, (int)pNameInfo
->offset
<< sizeShift
, NULL
, SEEK_SET
);
373 ReadFile( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
,
383 /**********************************************************************
384 * SetResourceHandler (KERNEL.67)
386 FARPROC16 WINAPI
SetResourceHandler16( HMODULE16 hModule
, LPCSTR typeId
, FARPROC16 resourceHandler
)
389 NE_TYPEINFO
*pTypeInfo
;
390 FARPROC16 prevHandler
= NULL
;
391 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
393 if (!pModule
|| !pModule
->res_table
) return NULL
;
395 pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
396 pTypeInfo
= (NE_TYPEINFO
*)(pResTab
+ 2);
398 TRACE("module=%04x type=%s\n", hModule
, debugstr_a(typeId
) );
402 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, typeId
)))
404 memcpy_unaligned( &prevHandler
, &pTypeInfo
->resloader
, sizeof(FARPROC16
) );
405 memcpy_unaligned( &pTypeInfo
->resloader
, &resourceHandler
, sizeof(FARPROC16
) );
406 pTypeInfo
= next_typeinfo(pTypeInfo
);
408 if (!prevHandler
) prevHandler
= get_default_res_handler();
412 static inline DWORD
get_dword(LPVOID
*p
)
414 DWORD ret
= *(DWORD
*)*p
;
415 *p
= (DWORD
*)*p
+ 1;
419 static inline void put_dword(LPVOID
*p
, DWORD d
)
422 *p
= (DWORD
*)*p
+ 1;
425 static inline WORD
get_word(LPVOID
*p
)
427 WORD ret
= *(WORD
*)*p
;
432 static inline void put_word(LPVOID
*p
, WORD w
)
438 static inline BYTE
get_byte(LPVOID
*p
)
440 BYTE ret
= *(BYTE
*)*p
;
445 static inline void put_byte(LPVOID
*p
, BYTE b
)
451 /* convert a resource name */
452 static void convert_name( LPVOID
*dst
, LPVOID
*src
)
455 switch (*((WORD
*)*src
))
463 put_byte( dst
, 0xff );
464 put_word( dst
, get_word(src
) );
467 len
= WideCharToMultiByte( CP_ACP
, 0, *src
, -1, *dst
, 0x7fffffff, NULL
,NULL
);
468 *dst
= (char *)*dst
+ len
;
469 *src
= (WCHAR
*)*src
+ strlenW( (WCHAR
*)*src
) + 1;
474 /**********************************************************************
475 * ConvertDialog32To16 (KERNEL.615)
477 VOID WINAPI
ConvertDialog32To16( LPVOID dialog32
, DWORD size
, LPVOID dialog16
)
479 WORD nbItems
, data
, dialogEx
;
482 style
= get_dword( &dialog32
);
483 put_dword( &dialog16
, style
);
484 dialogEx
= (style
== 0xffff0001); /* DIALOGEX resource */
487 put_dword( &dialog16
, get_dword( &dialog32
) ); /* helpID */
488 put_dword( &dialog16
, get_dword( &dialog32
) ); /* exStyle */
489 style
= get_dword( &dialog32
);
490 put_dword( &dialog16
, style
); /* style */
493 dialog32
= (DWORD
*)dialog32
+ 1; /* exStyle ignored in 16-bit standard dialog */
495 nbItems
= get_word( &dialog32
);
496 put_byte( &dialog16
, nbItems
);
497 put_word( &dialog16
, get_word( &dialog32
) ); /* x */
498 put_word( &dialog16
, get_word( &dialog32
) ); /* y */
499 put_word( &dialog16
, get_word( &dialog32
) ); /* cx */
500 put_word( &dialog16
, get_word( &dialog32
) ); /* cy */
502 /* Transfer menu name */
503 convert_name( &dialog16
, &dialog32
);
505 /* Transfer class name */
506 convert_name( &dialog16
, &dialog32
);
508 /* Transfer window caption */
509 WideCharToMultiByte( CP_ACP
, 0, dialog32
, -1, dialog16
, 0x7fffffff, NULL
, NULL
);
510 dialog16
= (LPSTR
)dialog16
+ strlen( (LPSTR
)dialog16
) + 1;
511 dialog32
= (LPWSTR
)dialog32
+ strlenW( (LPWSTR
)dialog32
) + 1;
513 /* Transfer font info */
514 if (style
& DS_SETFONT
)
516 put_word( &dialog16
, get_word( &dialog32
) ); /* pointSize */
519 put_word( &dialog16
, get_word( &dialog32
) ); /* weight */
520 put_word( &dialog16
, get_word( &dialog32
) ); /* italic */
522 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)dialog32
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
, NULL
); /* faceName */
523 dialog16
= (LPSTR
)dialog16
+ strlen( (LPSTR
)dialog16
) + 1;
524 dialog32
= (LPWSTR
)dialog32
+ strlenW( (LPWSTR
)dialog32
) + 1;
527 /* Transfer dialog items */
530 /* align on DWORD boundary (32-bit only) */
531 dialog32
= (LPVOID
)((((int)dialog32
) + 3) & ~3);
535 put_dword( &dialog16
, get_dword( &dialog32
) ); /* helpID */
536 put_dword( &dialog16
, get_dword( &dialog32
) ); /* exStyle */
537 put_dword( &dialog16
, get_dword( &dialog32
) ); /* style */
541 style
= get_dword( &dialog32
); /* save style */
542 dialog32
= (DWORD
*)dialog32
+ 1; /* ignore exStyle */
545 put_word( &dialog16
, get_word( &dialog32
) ); /* x */
546 put_word( &dialog16
, get_word( &dialog32
) ); /* y */
547 put_word( &dialog16
, get_word( &dialog32
) ); /* cx */
548 put_word( &dialog16
, get_word( &dialog32
) ); /* cy */
551 put_dword( &dialog16
, get_dword( &dialog32
) ); /* ID */
554 put_word( &dialog16
, get_word( &dialog32
) ); /* ID */
555 put_dword( &dialog16
, style
); /* style from above */
558 /* Transfer class name */
559 switch (*(WORD
*)dialog32
)
562 get_word( &dialog32
);
563 put_byte( &dialog16
, 0 );
566 get_word( &dialog32
);
567 put_byte( &dialog16
, get_word( &dialog32
) );
570 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)dialog32
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
, NULL
);
571 dialog16
= (LPSTR
)dialog16
+ strlen( (LPSTR
)dialog16
) + 1;
572 dialog32
= (LPWSTR
)dialog32
+ strlenW( (LPWSTR
)dialog32
) + 1;
576 /* Transfer window name */
577 convert_name( &dialog16
, &dialog32
);
580 data
= get_word( &dialog32
);
582 put_word(&dialog16
, data
);
584 put_byte(&dialog16
,(BYTE
)data
);
588 memcpy( dialog16
, dialog32
, data
);
589 dialog16
= (BYTE
*)dialog16
+ data
;
590 dialog32
= (BYTE
*)dialog32
+ data
;
599 /**********************************************************************
600 * GetDialog32Size (KERNEL.618)
602 WORD WINAPI
GetDialog32Size16( LPVOID dialog32
)
605 WORD nbItems
, data
, dialogEx
;
608 style
= get_dword(&p
);
609 dialogEx
= (style
== 0xffff0001); /* DIALOGEX resource */
612 p
= (DWORD
*)p
+ 1; /* helpID */
613 p
= (DWORD
*)p
+ 1; /* exStyle */
614 style
= get_dword(&p
); /* style */
617 p
= (DWORD
*)p
+ 1; /* exStyle */
619 nbItems
= get_word(&p
);
620 p
= (WORD
*)p
+ 1; /* x */
621 p
= (WORD
*)p
+ 1; /* y */
622 p
= (WORD
*)p
+ 1; /* cx */
623 p
= (WORD
*)p
+ 1; /* cy */
626 switch (*((WORD
*)p
))
628 case 0x0000: p
= (WORD
*)p
+ 1; break;
629 case 0xffff: p
= (WORD
*)p
+ 2; break;
630 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
633 /* Skip class name */
634 switch (*((WORD
*)p
))
636 case 0x0000: p
= (WORD
*)p
+ 1; break;
637 case 0xffff: p
= (WORD
*)p
+ 2; break;
638 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
641 /* Skip window caption */
642 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1;
645 if (style
& DS_SETFONT
)
647 p
= (WORD
*)p
+ 1; /* pointSize */
650 p
= (WORD
*)p
+ 1; /* weight */
651 p
= (WORD
*)p
+ 1; /* italic */
653 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; /* faceName */
656 /* Skip dialog items */
659 /* align on DWORD boundary */
660 p
= (LPVOID
)((((int)p
) + 3) & ~3);
664 p
= (DWORD
*)p
+ 1; /* helpID */
665 p
= (DWORD
*)p
+ 1; /* exStyle */
666 p
= (DWORD
*)p
+ 1; /* style */
670 p
= (DWORD
*)p
+ 1; /* style */
671 p
= (DWORD
*)p
+ 1; /* exStyle */
674 p
= (WORD
*)p
+ 1; /* x */
675 p
= (WORD
*)p
+ 1; /* y */
676 p
= (WORD
*)p
+ 1; /* cx */
677 p
= (WORD
*)p
+ 1; /* cy */
680 p
= (DWORD
*)p
+ 1; /* ID */
682 p
= (WORD
*)p
+ 1; /* ID */
684 /* Skip class name */
685 switch (*((WORD
*)p
))
687 case 0x0000: p
= (WORD
*)p
+ 1; break;
688 case 0xffff: p
= (WORD
*)p
+ 2; break;
689 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
692 /* Skip window name */
693 switch (*((WORD
*)p
))
695 case 0x0000: p
= (WORD
*)p
+ 1; break;
696 case 0xffff: p
= (WORD
*)p
+ 2; break;
697 default: p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1; break;
702 p
= (BYTE
*)p
+ data
;
708 return (WORD
)((LPSTR
)p
- (LPSTR
)dialog32
);
712 /**********************************************************************
713 * ConvertMenu32To16 (KERNEL.616)
715 VOID WINAPI
ConvertMenu32To16( LPVOID menu32
, DWORD size
, LPVOID menu16
)
717 WORD version
, headersize
, flags
, level
= 1;
719 version
= get_word( &menu32
);
720 headersize
= get_word( &menu32
);
721 put_word( &menu16
, version
);
722 put_word( &menu16
, headersize
);
725 memcpy( menu16
, menu32
, headersize
);
726 menu16
= (BYTE
*)menu16
+ headersize
;
727 menu32
= (BYTE
*)menu32
+ headersize
;
731 if ( version
== 0 ) /* standard */
733 flags
= get_word( &menu32
);
734 put_word( &menu16
, flags
);
735 if ( !(flags
& MF_POPUP
) )
736 put_word( &menu16
, get_word( &menu32
) ); /* ID */
740 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)menu32
, -1, (LPSTR
)menu16
, 0x7fffffff, NULL
, NULL
);
741 menu16
= (LPSTR
)menu16
+ strlen( (LPSTR
)menu16
) + 1;
742 menu32
= (LPWSTR
)menu32
+ strlenW( (LPWSTR
)menu32
) + 1;
744 if ( flags
& MF_END
)
749 put_dword( &menu16
, get_dword( &menu32
) ); /* fType */
750 put_dword( &menu16
, get_dword( &menu32
) ); /* fState */
751 put_word( &menu16
, get_dword( &menu32
) ); /* ID */
752 flags
= get_word( &menu32
);
753 put_byte(&menu16
,flags
);
755 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)menu32
, -1, (LPSTR
)menu16
, 0x7fffffff, NULL
, NULL
);
756 menu16
= (LPSTR
)menu16
+ strlen( (LPSTR
)menu16
) + 1;
757 menu32
= (LPWSTR
)menu32
+ strlenW( (LPWSTR
)menu32
) + 1;
759 /* align on DWORD boundary (32-bit only) */
760 menu32
= (LPVOID
)((((int)menu32
) + 3) & ~3);
762 /* If popup, transfer helpid */
765 put_dword( &menu16
, get_dword( &menu32
) );
769 if ( flags
& MF_END
)
775 /**********************************************************************
776 * GetMenu32Size (KERNEL.617)
778 WORD WINAPI
GetMenu32Size16( LPVOID menu32
)
781 WORD version
, headersize
, flags
, level
= 1;
783 version
= get_word(&p
);
784 headersize
= get_word(&p
);
785 p
= (BYTE
*)p
+ headersize
;
788 if ( version
== 0 ) /* standard */
790 flags
= get_word(&p
);
791 if ( !(flags
& MF_POPUP
) )
792 p
= (WORD
*)p
+ 1; /* ID */
796 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1;
798 if ( flags
& MF_END
)
803 p
= (DWORD
*)p
+ 1; /* fType */
804 p
= (DWORD
*)p
+ 1; /* fState */
805 p
= (DWORD
*)p
+ 1; /* ID */
806 flags
= get_word(&p
);
808 p
= (LPWSTR
)p
+ strlenW( (LPWSTR
)p
) + 1;
810 /* align on DWORD boundary (32-bit only) */
811 p
= (LPVOID
)((((int)p
) + 3) & ~3);
813 /* If popup, skip helpid */
820 if ( flags
& MF_END
)
824 return (WORD
)((LPSTR
)p
- (LPSTR
)menu32
);
828 /**********************************************************************
829 * ConvertAccelerator32To16
831 static void ConvertAccelerator32To16( LPVOID acc32
, DWORD size
, LPVOID acc16
)
838 type
= get_byte(&acc32
);
839 put_byte(&acc16
, type
);
842 /* Copy event and IDval */
843 put_word(&acc16
, get_word(&acc32
));
844 put_word(&acc16
, get_word(&acc32
));
848 } while ( !( type
& 0x80 ) );
852 /**********************************************************************
855 static HGLOBAL16
NE_LoadPEResource( NE_MODULE
*pModule
, WORD type
, LPVOID bits
, DWORD size
)
859 TRACE("module=%04x type=%04x\n", pModule
->self
, type
);
861 handle
= GlobalAlloc16( 0, size
);
866 ConvertMenu32To16( bits
, size
, GlobalLock16( handle
) );
869 ConvertDialog32To16( bits
, size
, GlobalLock16( handle
) );
872 ConvertAccelerator32To16( bits
, size
, GlobalLock16( handle
) );
875 FIXME("not yet implemented!\n" );
878 memcpy( GlobalLock16( handle
), bits
, size
);
885 /**********************************************************************
886 * AllocResource (KERNEL.66)
888 HGLOBAL16 WINAPI
AllocResource16( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
890 NE_NAMEINFO
*pNameInfo
=NULL
;
894 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
895 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return 0;
897 TRACE("module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
899 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
900 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
901 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
902 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
903 ret
= GlobalAlloc16( GMEM_FIXED
, size
);
904 if (ret
) FarSetOwner16( ret
, hModule
);
909 /**********************************************************************
910 * DirectResAlloc (KERNEL.168)
912 * Check Schulman, p. 232 for details
914 HGLOBAL16 WINAPI
DirectResAlloc16( HINSTANCE16 hInstance
, WORD wType
,
918 TRACE("(%04x,%04x,%04x)\n", hInstance
, wType
, wSize
);
919 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
920 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
921 CreateCursorIndirect. */
922 TRACE("(wType=%x)\n", wType
);
923 ret
= GlobalAlloc16( GMEM_MOVEABLE
, wSize
);
924 if (ret
) FarSetOwner16( ret
, hInstance
);
929 /**********************************************************************
930 * AccessResource (KERNEL.64)
932 INT16 WINAPI
AccessResource16( HINSTANCE16 hModule
, HRSRC16 hRsrc
)
935 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
937 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return -1;
939 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
941 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
943 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
944 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
945 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
951 /**********************************************************************
952 * FindResource (KERNEL.60)
954 HRSRC16 WINAPI
FindResource16( HMODULE16 hModule
, LPCSTR name
, LPCSTR type
)
956 NE_TYPEINFO
*pTypeInfo
;
957 NE_NAMEINFO
*pNameInfo
;
959 NE_MODULE
*pModule
= get_module( hModule
);
961 if (!pModule
) return 0;
963 if (pModule
->module32
)
965 /* 32-bit PE module */
966 HRSRC hRsrc32
= FindResourceA( pModule
->module32
, name
, type
);
967 return MapHRsrc32To16( pModule
, hRsrc32
, HIWORD(type
) ? 0 : LOWORD(type
) );
970 TRACE("module=%04x name=%s type=%s\n", pModule
->self
, debugstr_a(name
), debugstr_a(type
) );
972 if (!pModule
->res_table
) return 0;
974 type
= get_res_name( type
);
975 name
= get_res_name( name
);
977 if (HIWORD(type
) || HIWORD(name
))
979 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
982 type
= (LPCSTR
)(ULONG_PTR
)LOWORD(id
);
983 name
= (LPCSTR
)(ULONG_PTR
)HIWORD(id
);
986 pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
987 pTypeInfo
= (NE_TYPEINFO
*)( pResTab
+ 2 );
991 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, type
))) break;
992 if ((pNameInfo
= NE_FindResourceFromType( pResTab
, pTypeInfo
, name
)))
994 TRACE(" Found id %08lx\n", (DWORD
)name
);
995 return (HRSRC16
)( (char *)pNameInfo
- (char *)pModule
);
997 pTypeInfo
= next_typeinfo(pTypeInfo
);
1003 /**********************************************************************
1004 * LoadResource (KERNEL.61)
1006 HGLOBAL16 WINAPI
LoadResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
1008 NE_TYPEINFO
*pTypeInfo
;
1009 NE_NAMEINFO
*pNameInfo
= NULL
;
1010 NE_MODULE
*pModule
= get_module( hModule
);
1013 if (!hRsrc
|| !pModule
) return 0;
1015 if (pModule
->module32
)
1017 /* load 32-bit resource and convert it */
1018 HRSRC hRsrc32
= MapHRsrc16To32( pModule
, hRsrc
);
1019 WORD type
= MapHRsrc16ToType( pModule
, hRsrc
);
1020 HGLOBAL hMem
= LoadResource( pModule
->module32
, hRsrc32
);
1021 DWORD size
= SizeofResource( pModule
->module32
, hRsrc32
);
1022 if (!hMem
) return 0;
1023 return NE_LoadPEResource( pModule
, type
, LockResource( hMem
), size
);
1026 /* first, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
1028 d
= pModule
->res_table
+ 2;
1029 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
1032 if (pTypeInfo
->type_id
== 0) break; /* terminal entry */
1033 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
1036 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
1038 pNameInfo
= (NE_NAMEINFO
*)((char *)pModule
+ hRsrc
);
1041 else break; /* NE_NAMEINFO boundary mismatch */
1043 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
1048 if (pNameInfo
->handle
&& !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
1051 TRACE(" Already loaded, new count=%d\n", pNameInfo
->usage
);
1055 FARPROC16 resloader
;
1056 memcpy_unaligned( &resloader
, &pTypeInfo
->resloader
, sizeof(FARPROC16
) );
1057 if (resloader
&& resloader
!= get_default_res_handler())
1062 args
[2] = pNameInfo
->handle
;
1063 args
[1] = pModule
->self
;
1065 WOWCallback16Ex( (DWORD
)resloader
, WCB16_PASCAL
, sizeof(args
), args
, &ret
);
1066 pNameInfo
->handle
= LOWORD(ret
);
1069 pNameInfo
->handle
= NE_DefResourceHandler( pNameInfo
->handle
, pModule
->self
, hRsrc
);
1071 if (pNameInfo
->handle
)
1074 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
1077 return pNameInfo
->handle
;
1083 /**********************************************************************
1084 * LockResource (KERNEL.62)
1086 SEGPTR WINAPI
WIN16_LockResource16( HGLOBAL16 handle
)
1088 TRACE("(%04x)\n", handle
);
1089 /* May need to reload the resource if discarded */
1090 return K32WOWGlobalLock16( handle
);
1094 /**********************************************************************
1095 * LockResource16 (KERNEL32.@)
1097 LPVOID WINAPI
LockResource16( HGLOBAL16 handle
)
1099 return MapSL( WIN16_LockResource16(handle
) );
1103 /**********************************************************************
1104 * SizeofResource (KERNEL.65)
1106 DWORD WINAPI
SizeofResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
1108 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
1110 TRACE("(%x, %x)\n", hModule
, hRsrc
);
1112 if (!hRsrc
) return 0;
1113 if (!(pModule
= get_module( hModule
))) return 0;
1114 if (pModule
->res_table
)
1116 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
1117 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
1118 return (DWORD
)pNameInfo
->length
<< sizeShift
;
1120 if (pModule
->module32
)
1122 /* 32-bit PE module */
1123 return SizeofResource( pModule
->module32
, MapHRsrc16To32( pModule
, hRsrc
) );
1129 typedef WORD (WINAPI
*pDestroyIcon32Proc
)( HGLOBAL16 handle
, UINT16 flags
);
1131 /**********************************************************************
1132 * FreeResource (KERNEL.63)
1134 BOOL16 WINAPI
FreeResource16( HGLOBAL16 handle
)
1136 pDestroyIcon32Proc proc
;
1138 NE_MODULE
*pModule
= NE_GetPtr( FarGetOwner16( handle
) );
1140 TRACE("(%04x)\n", handle
);
1142 /* Try NE resource first */
1144 if (pModule
&& pModule
->res_table
)
1146 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
1147 while (pTypeInfo
->type_id
)
1150 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
1151 for (count
= pTypeInfo
->count
; count
> 0; count
--)
1153 if (pNameInfo
->handle
== handle
)
1155 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
1156 if (pNameInfo
->usage
== 0)
1158 GlobalFree16( pNameInfo
->handle
);
1159 pNameInfo
->handle
= 0;
1160 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
1166 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;
1170 /* If this failed, call USER.DestroyIcon32; this will check
1171 whether it is a shared cursor/icon; if not it will call
1173 user
= GetModuleHandleA( "user32.dll" );
1174 if (user
&& (proc
= (pDestroyIcon32Proc
)GetProcAddress( user
, "DestroyIcon32" )))
1175 return proc( handle
, 1 /*CID_RESOURCE*/ );
1177 return GlobalFree16( handle
);