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