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
28 #include <sys/types.h>
33 #include "wine/winbase16.h"
34 #include "wine/winuser16.h"
35 #include "kernel16_private.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(resource
);
40 /* handle conversions */
41 #define HRSRC_32(h16) ((HRSRC)(ULONG_PTR)(h16))
42 #define HGLOBAL_32(h16) ((HGLOBAL)(ULONG_PTR)(h16))
44 static inline NE_MODULE
*get_module( HMODULE16 mod
)
46 if (!mod
) mod
= TASK_GetCurrent()->hModule
;
47 return NE_GetPtr( mod
);
50 #define HRSRC_MAP_BLOCKSIZE 16
52 typedef struct _HRSRC_ELEM
58 typedef struct _HRSRC_MAP
66 /**********************************************************************
69 static HRSRC16
MapHRsrc32To16( NE_MODULE
*pModule
, HRSRC hRsrc32
, WORD type
)
71 HRSRC_MAP
*map
= pModule
->rsrc32_map
;
75 /* On first call, initialize HRSRC map */
78 if ( !(map
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(HRSRC_MAP
) ) ) )
80 ERR("Cannot allocate HRSRC map\n" );
83 pModule
->rsrc32_map
= map
;
86 /* Check whether HRSRC32 already in map */
87 for ( i
= 0; i
< map
->nUsed
; i
++ )
88 if ( map
->elem
[i
].hRsrc
== hRsrc32
)
89 return (HRSRC16
)(i
+ 1);
91 /* If no space left, grow table */
92 if ( map
->nUsed
== map
->nAlloc
)
96 newElem
= HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
97 map
->elem
, (map
->nAlloc
+ HRSRC_MAP_BLOCKSIZE
) * sizeof(HRSRC_ELEM
) );
99 newElem
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
100 (map
->nAlloc
+ HRSRC_MAP_BLOCKSIZE
) * sizeof(HRSRC_ELEM
) );
104 ERR("Cannot grow HRSRC map\n" );
108 map
->nAlloc
+= HRSRC_MAP_BLOCKSIZE
;
111 /* Add HRSRC32 to table */
112 map
->elem
[map
->nUsed
].hRsrc
= hRsrc32
;
113 map
->elem
[map
->nUsed
].type
= type
;
116 return (HRSRC16
)map
->nUsed
;
119 /**********************************************************************
122 static HRSRC
MapHRsrc16To32( NE_MODULE
*pModule
, HRSRC16 hRsrc16
)
124 HRSRC_MAP
*map
= pModule
->rsrc32_map
;
125 if ( !map
|| !hRsrc16
|| hRsrc16
> map
->nUsed
) return 0;
127 return map
->elem
[hRsrc16
-1].hRsrc
;
130 /**********************************************************************
133 static WORD
MapHRsrc16ToType( NE_MODULE
*pModule
, HRSRC16 hRsrc16
)
135 HRSRC_MAP
*map
= pModule
->rsrc32_map
;
136 if ( !map
|| !hRsrc16
|| hRsrc16
> map
->nUsed
) return 0;
138 return map
->elem
[hRsrc16
-1].type
;
142 /**********************************************************************
145 * Convert a resource name from '#xxx' form to numerical id.
147 static inline LPCSTR
get_res_name( LPCSTR name
)
149 if (HIWORD(name
) && name
[0] == '#') name
= MAKEINTRESOURCEA( atoi( name
+ 1 ) );
154 /**********************************************************************
157 static inline NE_TYPEINFO
*next_typeinfo( NE_TYPEINFO
*info
)
159 return (NE_TYPEINFO
*)((char*)(info
+ 1) + info
->count
* sizeof(NE_NAMEINFO
));
163 /**********************************************************************
164 * get_default_res_handler
166 static inline FARPROC16
get_default_res_handler(void)
168 static FARPROC16 handler
;
170 if (!handler
) handler
= GetProcAddress16( GetModuleHandle16("KERNEL"), "DefResourceHandler" );
175 /***********************************************************************
178 * Find the type and resource id from their names.
179 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
181 static DWORD
NE_FindNameTableId( NE_MODULE
*pModule
, LPCSTR typeId
, LPCSTR resId
)
183 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->ne_rsrctab
+ 2);
184 NE_NAMEINFO
*pNameInfo
;
190 for (; pTypeInfo
->type_id
!= 0;
191 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+1) +
192 pTypeInfo
->count
* sizeof(NE_NAMEINFO
)))
194 if (pTypeInfo
->type_id
!= 0x800f) continue;
195 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
196 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
198 TRACE("NameTable entry: type=%04x id=%04x\n",
199 pTypeInfo
->type_id
, pNameInfo
->id
);
200 handle
= LoadResource16( pModule
->self
,
201 (HRSRC16
)((char *)pNameInfo
- (char *)pModule
) );
202 for(p
= LockResource16(handle
); p
&& *p
; p
= (WORD
*)((char*)p
+*p
))
204 TRACE(" type=%04x '%s' id=%04x '%s'\n",
205 p
[1], (char *)(p
+3), p
[2],
206 (char *)(p
+3)+strlen((char *)(p
+3))+1 );
207 /* Check for correct type */
211 if (!HIWORD(typeId
)) continue;
212 if (stricmp( typeId
, (char *)(p
+ 3) )) continue;
214 else if (HIWORD(typeId
) || (((DWORD
)typeId
& ~0x8000)!= p
[1]))
217 /* Now check for the id */
221 if (!HIWORD(resId
)) continue;
222 if (stricmp( resId
, (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
225 else if (HIWORD(resId
) || ((LOWORD(resId
) & ~0x8000) != p
[2]))
228 /* If we get here, we've found the entry */
231 ret
= MAKELONG( p
[1], p
[2] );
234 FreeResource16( handle
);
242 /***********************************************************************
245 * Find header struct for a particular resource type.
247 static NE_TYPEINFO
*NE_FindTypeSection( LPBYTE pResTab
, NE_TYPEINFO
*pTypeInfo
, LPCSTR typeId
)
249 /* start from pTypeInfo */
251 if (HIWORD(typeId
) != 0) /* Named type */
254 BYTE len
= strlen( str
);
255 while (pTypeInfo
->type_id
)
257 if (!(pTypeInfo
->type_id
& 0x8000))
259 BYTE
*p
= pResTab
+ pTypeInfo
->type_id
;
260 if ((*p
== len
) && !_strnicmp( (char*)p
+1, str
, len
))
262 TRACE(" Found type '%s'\n", str
);
266 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
267 pTypeInfo
= next_typeinfo(pTypeInfo
);
270 else /* Numeric type id */
272 WORD id
= LOWORD(typeId
) | 0x8000;
273 while (pTypeInfo
->type_id
)
275 if (pTypeInfo
->type_id
== id
)
277 TRACE(" Found type %04x\n", id
);
280 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
281 pTypeInfo
= next_typeinfo(pTypeInfo
);
288 /***********************************************************************
289 * NE_FindResourceFromType
291 * Find a resource once the type info structure has been found.
293 static NE_NAMEINFO
*NE_FindResourceFromType( LPBYTE pResTab
, NE_TYPEINFO
*pTypeInfo
, LPCSTR resId
)
297 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
299 if (HIWORD(resId
) != 0) /* Named resource */
302 BYTE len
= strlen( str
);
303 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
305 if (pNameInfo
->id
& 0x8000) continue;
306 p
= pResTab
+ pNameInfo
->id
;
307 if ((*p
== len
) && !_strnicmp( (char*)p
+1, str
, len
))
311 else /* Numeric resource id */
313 WORD id
= LOWORD(resId
) | 0x8000;
314 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
315 if (pNameInfo
->id
== id
) return pNameInfo
;
321 /***********************************************************************
322 * DefResourceHandler (KERNEL.456)
324 * This is the default LoadProc() function.
326 HGLOBAL16 WINAPI
NE_DefResourceHandler( HGLOBAL16 hMemObj
, HMODULE16 hModule
,
331 NE_NAMEINFO
* pNameInfo
;
332 NE_MODULE
* pModule
= NE_GetPtr( hModule
);
334 if (!pModule
) return 0;
336 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
337 pNameInfo
= (NE_NAMEINFO
*)((char *)pModule
+ hRsrc
);
340 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
342 handle
= AllocResource16( hModule
, hRsrc
, 0 );
346 if (!NE_READ_DATA( pModule
, GlobalLock16( handle
),
347 (int)pNameInfo
->offset
<< sizeShift
,
348 (int)pNameInfo
->length
<< sizeShift
))
350 GlobalFree16( handle
);
358 /**********************************************************************
359 * SetResourceHandler (KERNEL.67)
361 FARPROC16 WINAPI
SetResourceHandler16( HMODULE16 hModule
, LPCSTR typeId
, FARPROC16 resourceHandler
)
364 NE_TYPEINFO
*pTypeInfo
;
365 FARPROC16 prevHandler
= NULL
;
366 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
368 if (!pModule
|| !pModule
->ne_rsrctab
) return NULL
;
370 pResTab
= (LPBYTE
)pModule
+ pModule
->ne_rsrctab
;
371 pTypeInfo
= (NE_TYPEINFO
*)(pResTab
+ 2);
373 TRACE("module=%04x type=%s\n", hModule
, debugstr_a(typeId
) );
377 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, typeId
)))
379 prevHandler
= pTypeInfo
->resloader
;
380 pTypeInfo
->resloader
= resourceHandler
;
381 pTypeInfo
= next_typeinfo(pTypeInfo
);
383 if (!prevHandler
) prevHandler
= get_default_res_handler();
387 static inline DWORD
get_dword(LPCVOID
*p
)
389 DWORD ret
= *(const DWORD
*)*p
;
390 *p
= (const DWORD
*)*p
+ 1;
394 static inline void put_dword(LPVOID
*p
, DWORD d
)
397 *p
= (DWORD
*)*p
+ 1;
400 static inline WORD
get_word(LPCVOID
*p
)
402 WORD ret
= *(const WORD
*)*p
;
403 *p
= (const WORD
*)*p
+ 1;
407 static inline void put_word(LPVOID
*p
, WORD w
)
413 static inline BYTE
get_byte(LPCVOID
*p
)
415 BYTE ret
= *(const BYTE
*)*p
;
416 *p
= (const BYTE
*)*p
+ 1;
420 static inline void put_byte(LPVOID
*p
, BYTE b
)
426 /* convert a resource name */
427 static void convert_name( LPVOID
*dst
, LPCVOID
*src
)
430 switch (*(const WORD
*)*src
)
438 put_byte( dst
, 0xff );
439 put_word( dst
, get_word(src
) );
442 len
= WideCharToMultiByte( CP_ACP
, 0, *src
, -1, *dst
, 0x7fffffff, NULL
,NULL
);
443 *dst
= (char *)*dst
+ len
;
444 *src
= (LPCWSTR
)*src
+ lstrlenW( *src
) + 1;
449 /**********************************************************************
450 * ConvertDialog32To16 (KERNEL.615)
452 VOID WINAPI
ConvertDialog32To16( LPCVOID dialog32
, DWORD size
, LPVOID dialog16
)
454 WORD nbItems
, data
, dialogEx
;
457 style
= get_dword( &dialog32
);
458 put_dword( &dialog16
, style
);
459 dialogEx
= (style
== 0xffff0001); /* DIALOGEX resource */
462 put_dword( &dialog16
, get_dword( &dialog32
) ); /* helpID */
463 put_dword( &dialog16
, get_dword( &dialog32
) ); /* exStyle */
464 style
= get_dword( &dialog32
);
465 put_dword( &dialog16
, style
); /* style */
468 dialog32
= (const DWORD
*)dialog32
+ 1; /* exStyle ignored in 16-bit standard dialog */
470 nbItems
= get_word( &dialog32
);
471 put_byte( &dialog16
, nbItems
);
472 put_word( &dialog16
, get_word( &dialog32
) ); /* x */
473 put_word( &dialog16
, get_word( &dialog32
) ); /* y */
474 put_word( &dialog16
, get_word( &dialog32
) ); /* cx */
475 put_word( &dialog16
, get_word( &dialog32
) ); /* cy */
477 /* Transfer menu name */
478 convert_name( &dialog16
, &dialog32
);
480 /* Transfer class name */
481 convert_name( &dialog16
, &dialog32
);
483 /* Transfer window caption */
484 WideCharToMultiByte( CP_ACP
, 0, dialog32
, -1, dialog16
, 0x7fffffff, NULL
, NULL
);
485 dialog16
= (LPSTR
)dialog16
+ strlen( dialog16
) + 1;
486 dialog32
= (LPCWSTR
)dialog32
+ lstrlenW( dialog32
) + 1;
488 /* Transfer font info */
489 if (style
& DS_SETFONT
)
491 put_word( &dialog16
, get_word( &dialog32
) ); /* pointSize */
494 put_word( &dialog16
, get_word( &dialog32
) ); /* weight */
495 put_word( &dialog16
, get_word( &dialog32
) ); /* italic */
497 WideCharToMultiByte( CP_ACP
, 0, dialog32
, -1, dialog16
, 0x7fffffff, NULL
, NULL
); /* faceName */
498 dialog16
= (LPSTR
)dialog16
+ strlen( dialog16
) + 1;
499 dialog32
= (LPCWSTR
)dialog32
+ lstrlenW( dialog32
) + 1;
502 /* Transfer dialog items */
505 /* align on DWORD boundary (32-bit only) */
506 dialog32
= (LPCVOID
)(((UINT_PTR
)dialog32
+ 3) & ~3);
510 put_dword( &dialog16
, get_dword( &dialog32
) ); /* helpID */
511 put_dword( &dialog16
, get_dword( &dialog32
) ); /* exStyle */
512 put_dword( &dialog16
, get_dword( &dialog32
) ); /* style */
516 style
= get_dword( &dialog32
); /* save style */
517 dialog32
= (const DWORD
*)dialog32
+ 1; /* ignore exStyle */
520 put_word( &dialog16
, get_word( &dialog32
) ); /* x */
521 put_word( &dialog16
, get_word( &dialog32
) ); /* y */
522 put_word( &dialog16
, get_word( &dialog32
) ); /* cx */
523 put_word( &dialog16
, get_word( &dialog32
) ); /* cy */
526 put_dword( &dialog16
, get_dword( &dialog32
) ); /* ID */
529 put_word( &dialog16
, get_word( &dialog32
) ); /* ID */
530 put_dword( &dialog16
, style
); /* style from above */
533 /* Transfer class name */
534 switch (*(const WORD
*)dialog32
)
537 get_word( &dialog32
);
538 put_byte( &dialog16
, 0 );
541 get_word( &dialog32
);
542 put_byte( &dialog16
, get_word( &dialog32
) );
545 WideCharToMultiByte( CP_ACP
, 0, dialog32
, -1, dialog16
, 0x7fffffff, NULL
, NULL
);
546 dialog16
= (LPSTR
)dialog16
+ strlen( dialog16
) + 1;
547 dialog32
= (LPCWSTR
)dialog32
+ lstrlenW( dialog32
) + 1;
551 /* Transfer window name */
552 convert_name( &dialog16
, &dialog32
);
555 data
= get_word( &dialog32
);
557 put_word(&dialog16
, data
);
559 put_byte(&dialog16
,(BYTE
)data
);
563 memcpy( dialog16
, dialog32
, data
);
564 dialog16
= (BYTE
*)dialog16
+ data
;
565 dialog32
= (const BYTE
*)dialog32
+ data
;
574 /**********************************************************************
575 * GetDialog32Size (KERNEL.618)
577 WORD WINAPI
GetDialog32Size16( LPCVOID dialog32
)
579 LPCVOID p
= dialog32
;
580 WORD nbItems
, data
, dialogEx
;
583 style
= get_dword(&p
);
584 dialogEx
= (style
== 0xffff0001); /* DIALOGEX resource */
587 p
= (const DWORD
*)p
+ 1; /* helpID */
588 p
= (const DWORD
*)p
+ 1; /* exStyle */
589 style
= get_dword(&p
); /* style */
592 p
= (const DWORD
*)p
+ 1; /* exStyle */
594 nbItems
= get_word(&p
);
595 p
= (const WORD
*)p
+ 1; /* x */
596 p
= (const WORD
*)p
+ 1; /* y */
597 p
= (const WORD
*)p
+ 1; /* cx */
598 p
= (const WORD
*)p
+ 1; /* cy */
601 switch (*(const WORD
*)p
)
603 case 0x0000: p
= (const WORD
*)p
+ 1; break;
604 case 0xffff: p
= (const WORD
*)p
+ 2; break;
605 default: p
= (LPCWSTR
)p
+ lstrlenW( p
) + 1; break;
608 /* Skip class name */
609 switch (*(const WORD
*)p
)
611 case 0x0000: p
= (const WORD
*)p
+ 1; break;
612 case 0xffff: p
= (const WORD
*)p
+ 2; break;
613 default: p
= (LPCWSTR
)p
+ lstrlenW( p
) + 1; break;
616 /* Skip window caption */
617 p
= (LPCWSTR
)p
+ lstrlenW( p
) + 1;
620 if (style
& DS_SETFONT
)
622 p
= (const WORD
*)p
+ 1; /* pointSize */
625 p
= (const WORD
*)p
+ 1; /* weight */
626 p
= (const WORD
*)p
+ 1; /* italic */
628 p
= (LPCWSTR
)p
+ lstrlenW( p
) + 1; /* faceName */
631 /* Skip dialog items */
634 /* align on DWORD boundary */
635 p
= (LPCVOID
)(((UINT_PTR
)p
+ 3) & ~3);
639 p
= (const DWORD
*)p
+ 1; /* helpID */
640 p
= (const DWORD
*)p
+ 1; /* exStyle */
641 p
= (const DWORD
*)p
+ 1; /* style */
645 p
= (const DWORD
*)p
+ 1; /* style */
646 p
= (const DWORD
*)p
+ 1; /* exStyle */
649 p
= (const WORD
*)p
+ 1; /* x */
650 p
= (const WORD
*)p
+ 1; /* y */
651 p
= (const WORD
*)p
+ 1; /* cx */
652 p
= (const WORD
*)p
+ 1; /* cy */
655 p
= (const DWORD
*)p
+ 1; /* ID */
657 p
= (const WORD
*)p
+ 1; /* ID */
659 /* Skip class name */
660 switch (*(const WORD
*)p
)
662 case 0x0000: p
= (const WORD
*)p
+ 1; break;
663 case 0xffff: p
= (const WORD
*)p
+ 2; break;
664 default: p
= (LPCWSTR
)p
+ lstrlenW( p
) + 1; break;
667 /* Skip window name */
668 switch (*(const WORD
*)p
)
670 case 0x0000: p
= (const WORD
*)p
+ 1; break;
671 case 0xffff: p
= (const WORD
*)p
+ 2; break;
672 default: p
= (LPCWSTR
)p
+ lstrlenW( p
) + 1; break;
677 p
= (const BYTE
*)p
+ data
;
683 return (WORD
)((LPCSTR
)p
- (LPCSTR
)dialog32
);
687 /**********************************************************************
688 * ConvertMenu32To16 (KERNEL.616)
690 VOID WINAPI
ConvertMenu32To16( LPCVOID menu32
, DWORD size
, LPVOID menu16
)
692 WORD version
, headersize
, flags
, level
= 1;
694 version
= get_word( &menu32
);
695 headersize
= get_word( &menu32
);
696 put_word( &menu16
, version
);
697 put_word( &menu16
, headersize
);
700 memcpy( menu16
, menu32
, headersize
);
701 menu16
= (BYTE
*)menu16
+ headersize
;
702 menu32
= (const BYTE
*)menu32
+ headersize
;
706 if ( version
== 0 ) /* standard */
708 flags
= get_word( &menu32
);
709 put_word( &menu16
, flags
);
710 if ( !(flags
& MF_POPUP
) )
711 put_word( &menu16
, get_word( &menu32
) ); /* ID */
715 WideCharToMultiByte( CP_ACP
, 0, menu32
, -1, menu16
, 0x7fffffff, NULL
, NULL
);
716 menu16
= (LPSTR
)menu16
+ strlen( menu16
) + 1;
717 menu32
= (LPCWSTR
)menu32
+ lstrlenW( menu32
) + 1;
719 if ( flags
& MF_END
)
724 put_dword( &menu16
, get_dword( &menu32
) ); /* fType */
725 put_dword( &menu16
, get_dword( &menu32
) ); /* fState */
726 put_word( &menu16
, get_dword( &menu32
) ); /* ID */
727 flags
= get_word( &menu32
);
728 put_byte(&menu16
,flags
);
730 WideCharToMultiByte( CP_ACP
, 0, menu32
, -1, menu16
, 0x7fffffff, NULL
, NULL
);
731 menu16
= (LPSTR
)menu16
+ strlen( menu16
) + 1;
732 menu32
= (LPCWSTR
)menu32
+ lstrlenW( menu32
) + 1;
734 /* align on DWORD boundary (32-bit only) */
735 menu32
= (LPCVOID
)(((UINT_PTR
)menu32
+ 3) & ~3);
737 /* If popup, transfer helpid */
740 put_dword( &menu16
, get_dword( &menu32
) );
744 if ( flags
& MF_END
)
750 /**********************************************************************
751 * GetMenu32Size (KERNEL.617)
753 WORD WINAPI
GetMenu32Size16( LPCVOID menu32
)
756 WORD version
, headersize
, flags
, level
= 1;
758 version
= get_word(&p
);
759 headersize
= get_word(&p
);
760 p
= (const BYTE
*)p
+ headersize
;
763 if ( version
== 0 ) /* standard */
765 flags
= get_word(&p
);
766 if ( !(flags
& MF_POPUP
) )
767 p
= (const WORD
*)p
+ 1; /* ID */
771 p
= (LPCWSTR
)p
+ lstrlenW( p
) + 1;
773 if ( flags
& MF_END
)
778 p
= (const DWORD
*)p
+ 1; /* fType */
779 p
= (const DWORD
*)p
+ 1; /* fState */
780 p
= (const DWORD
*)p
+ 1; /* ID */
781 flags
= get_word(&p
);
783 p
= (LPCWSTR
)p
+ lstrlenW( p
) + 1;
785 /* align on DWORD boundary (32-bit only) */
786 p
= (LPCVOID
)(((UINT_PTR
)p
+ 3) & ~3);
788 /* If popup, skip helpid */
791 p
= (const DWORD
*)p
+ 1;
795 if ( flags
& MF_END
)
799 return (WORD
)((LPCSTR
)p
- (LPCSTR
)menu32
);
803 /**********************************************************************
804 * ConvertAccelerator32To16
806 static void ConvertAccelerator32To16( LPCVOID acc32
, DWORD size
, LPVOID acc16
)
813 type
= get_byte(&acc32
);
814 put_byte(&acc16
, type
);
817 /* Copy event and IDval */
818 put_word(&acc16
, get_word(&acc32
));
819 put_word(&acc16
, get_word(&acc32
));
823 } while ( !( type
& 0x80 ) );
827 /**********************************************************************
830 static HGLOBAL16
NE_LoadPEResource( NE_MODULE
*pModule
, WORD type
, LPCVOID bits
, DWORD size
)
834 TRACE("module=%04x type=%04x\n", pModule
->self
, type
);
836 handle
= GlobalAlloc16( 0, size
);
841 ConvertMenu32To16( bits
, size
, GlobalLock16( handle
) );
844 ConvertDialog32To16( bits
, size
, GlobalLock16( handle
) );
847 ConvertAccelerator32To16( bits
, size
, GlobalLock16( handle
) );
850 FIXME("not yet implemented!\n" );
853 memcpy( GlobalLock16( handle
), bits
, size
);
860 /**********************************************************************
861 * AllocResource (KERNEL.66)
863 HGLOBAL16 WINAPI
AllocResource16( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
865 NE_NAMEINFO
*pNameInfo
=NULL
;
869 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
870 if (!pModule
|| !pModule
->ne_rsrctab
|| !hRsrc
) return 0;
872 TRACE("module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
874 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
875 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
876 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
877 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
878 ret
= GlobalAlloc16( GMEM_FIXED
, size
);
879 if (ret
) FarSetOwner16( ret
, hModule
);
884 /**********************************************************************
885 * DirectResAlloc (KERNEL.168)
887 * Check Schulman, p. 232 for details
889 HGLOBAL16 WINAPI
DirectResAlloc16( HINSTANCE16 hInstance
, WORD wType
,
893 TRACE("(%04x,%04x,%04x)\n", hInstance
, wType
, wSize
);
894 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
895 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
896 CreateCursorIndirect. */
897 TRACE("(wType=%x)\n", wType
);
898 ret
= GlobalAlloc16( GMEM_MOVEABLE
, wSize
);
899 if (ret
) FarSetOwner16( ret
, hInstance
);
904 /**********************************************************************
905 * AccessResource (KERNEL.64)
907 INT16 WINAPI
AccessResource16( HINSTANCE16 hModule
, HRSRC16 hRsrc
)
910 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
912 if (!pModule
|| !pModule
->ne_rsrctab
|| !hRsrc
) return -1;
914 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
916 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
918 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
919 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
920 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
926 /**********************************************************************
927 * FindResource (KERNEL.60)
929 HRSRC16 WINAPI
FindResource16( HMODULE16 hModule
, LPCSTR name
, LPCSTR type
)
931 NE_TYPEINFO
*pTypeInfo
;
932 NE_NAMEINFO
*pNameInfo
;
934 NE_MODULE
*pModule
= get_module( hModule
);
936 if (!pModule
) return 0;
938 if (pModule
->module32
)
940 /* 32-bit PE module */
941 HRSRC hRsrc32
= FindResourceA( pModule
->module32
, name
, type
);
942 return MapHRsrc32To16( pModule
, hRsrc32
, HIWORD(type
) ? 0 : LOWORD(type
) );
945 TRACE("module=%04x name=%s type=%s\n", pModule
->self
, debugstr_a(name
), debugstr_a(type
) );
947 if (!pModule
->ne_rsrctab
) return 0;
949 type
= get_res_name( type
);
950 name
= get_res_name( name
);
952 if (HIWORD(type
) || HIWORD(name
))
954 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
957 type
= (LPCSTR
)(ULONG_PTR
)LOWORD(id
);
958 name
= (LPCSTR
)(ULONG_PTR
)HIWORD(id
);
961 pResTab
= (LPBYTE
)pModule
+ pModule
->ne_rsrctab
;
962 pTypeInfo
= (NE_TYPEINFO
*)( pResTab
+ 2 );
966 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, type
))) break;
967 if ((pNameInfo
= NE_FindResourceFromType( pResTab
, pTypeInfo
, name
)))
969 TRACE(" Found id %p\n", name
);
970 return (HRSRC16
)( (char *)pNameInfo
- (char *)pModule
);
972 pTypeInfo
= next_typeinfo(pTypeInfo
);
978 /**********************************************************************
979 * LoadResource (KERNEL.61)
981 HGLOBAL16 WINAPI
LoadResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
983 NE_TYPEINFO
*pTypeInfo
;
984 NE_NAMEINFO
*pNameInfo
= NULL
;
985 NE_MODULE
*pModule
= get_module( hModule
);
988 if (!hRsrc
|| !pModule
) return 0;
990 if (pModule
->module32
)
992 /* load 32-bit resource and convert it */
993 HRSRC hRsrc32
= MapHRsrc16To32( pModule
, hRsrc
);
994 WORD type
= MapHRsrc16ToType( pModule
, hRsrc
);
995 HGLOBAL hMem
= LoadResource( pModule
->module32
, hRsrc32
);
996 DWORD size
= SizeofResource( pModule
->module32
, hRsrc32
);
998 return NE_LoadPEResource( pModule
, type
, LockResource( hMem
), size
);
1001 /* first, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
1003 d
= pModule
->ne_rsrctab
+ 2;
1004 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
1007 if (pTypeInfo
->type_id
== 0) break; /* terminal entry */
1008 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
1011 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
1013 pNameInfo
= (NE_NAMEINFO
*)((char *)pModule
+ hRsrc
);
1016 else break; /* NE_NAMEINFO boundary mismatch */
1018 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
1023 if (pNameInfo
->handle
&& !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
1026 TRACE(" Already loaded, new count=%d\n", pNameInfo
->usage
);
1030 FARPROC16 resloader
= pTypeInfo
->resloader
;
1031 if (resloader
&& resloader
!= get_default_res_handler())
1036 args
[2] = pNameInfo
->handle
;
1037 args
[1] = pModule
->self
;
1039 WOWCallback16Ex( (DWORD
)resloader
, WCB16_PASCAL
, sizeof(args
), args
, &ret
);
1040 pNameInfo
->handle
= LOWORD(ret
);
1043 pNameInfo
->handle
= NE_DefResourceHandler( pNameInfo
->handle
, pModule
->self
, hRsrc
);
1045 if (pNameInfo
->handle
)
1048 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
1051 return pNameInfo
->handle
;
1057 /**********************************************************************
1058 * LockResource (KERNEL.62)
1060 SEGPTR WINAPI
WIN16_LockResource16( HGLOBAL16 handle
)
1062 TRACE("(%04x)\n", handle
);
1063 /* May need to reload the resource if discarded */
1064 return WOWGlobalLock16( handle
);
1068 /**********************************************************************
1069 * LockResource16 (KERNEL32.@)
1071 LPVOID WINAPI
LockResource16( HGLOBAL16 handle
)
1073 return MapSL( WIN16_LockResource16(handle
) );
1077 /**********************************************************************
1078 * SizeofResource (KERNEL.65)
1080 DWORD WINAPI
SizeofResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
1084 TRACE("(%x, %x)\n", hModule
, hRsrc
);
1086 if (!hRsrc
) return 0;
1087 if (!(pModule
= get_module( hModule
))) return 0;
1088 if (pModule
->ne_rsrctab
)
1090 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->ne_rsrctab
);
1091 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
1092 return (DWORD
)pNameInfo
->length
<< sizeShift
;
1094 if (pModule
->module32
)
1096 /* 32-bit PE module */
1097 return SizeofResource( pModule
->module32
, MapHRsrc16To32( pModule
, hRsrc
) );
1103 /**********************************************************************
1104 * FreeResource (KERNEL.63)
1106 BOOL16 WINAPI
FreeResource16( HGLOBAL16 handle
)
1110 NE_MODULE
*pModule
= NE_GetPtr( FarGetOwner16( handle
) );
1112 TRACE("(%04x)\n", handle
);
1114 /* Try NE resource first */
1116 if (pModule
&& pModule
->ne_rsrctab
)
1118 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->ne_rsrctab
+ 2);
1119 while (pTypeInfo
->type_id
)
1122 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
1123 for (count
= pTypeInfo
->count
; count
> 0; count
--)
1125 if (pNameInfo
->handle
== handle
)
1127 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
1128 if (pNameInfo
->usage
== 0)
1130 GlobalFree16( pNameInfo
->handle
);
1131 pNameInfo
->handle
= 0;
1132 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
1138 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;
1142 /* If this failed, call USER.DestroyIcon32; this will check
1143 whether it is a shared cursor/icon; if not it will call
1145 user
= GetModuleHandle16( "user" );
1146 if (user
&& (proc
= GetProcAddress16( user
, "DestroyIcon32" )))
1152 args
[0] = 1; /* CID_RESOURCE */
1153 WOWCallback16Ex( (SEGPTR
)proc
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
1154 return LOWORD(result
);
1157 return GlobalFree16( handle
);