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"
30 #include <sys/types.h>
35 #include "wine/winbase16.h"
36 #include "wine/winuser16.h"
37 #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
)
98 if ( !(newElem
= (HRSRC_ELEM
*)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
100 (map
->nAlloc
+ HRSRC_MAP_BLOCKSIZE
)
101 * sizeof(HRSRC_ELEM
) ) ))
103 ERR("Cannot grow HRSRC map\n" );
107 map
->nAlloc
+= HRSRC_MAP_BLOCKSIZE
;
110 /* Add HRSRC32 to table */
111 map
->elem
[map
->nUsed
].hRsrc
= hRsrc32
;
112 map
->elem
[map
->nUsed
].type
= type
;
115 return (HRSRC16
)map
->nUsed
;
118 /**********************************************************************
121 static HRSRC
MapHRsrc16To32( NE_MODULE
*pModule
, HRSRC16 hRsrc16
)
123 HRSRC_MAP
*map
= (HRSRC_MAP
*)pModule
->hRsrcMap
;
124 if ( !map
|| !hRsrc16
|| hRsrc16
> map
->nUsed
) return 0;
126 return map
->elem
[hRsrc16
-1].hRsrc
;
129 /**********************************************************************
132 static WORD
MapHRsrc16ToType( NE_MODULE
*pModule
, HRSRC16 hRsrc16
)
134 HRSRC_MAP
*map
= (HRSRC_MAP
*)pModule
->hRsrcMap
;
135 if ( !map
|| !hRsrc16
|| hRsrc16
> map
->nUsed
) return 0;
137 return map
->elem
[hRsrc16
-1].type
;
141 /**********************************************************************
144 * Convert a resource name from '#xxx' form to numerical id.
146 static inline LPCSTR
get_res_name( LPCSTR name
)
148 if (HIWORD(name
) && name
[0] == '#') name
= (LPCSTR
)atoi( name
+ 1 );
153 /**********************************************************************
156 static inline NE_TYPEINFO
*next_typeinfo( NE_TYPEINFO
*info
)
158 return (NE_TYPEINFO
*)((char*)(info
+ 1) + info
->count
* sizeof(NE_NAMEINFO
));
162 /**********************************************************************
163 * get_default_res_handler
165 static inline FARPROC16
get_default_res_handler(void)
167 static FARPROC16 handler
;
169 if (!handler
) handler
= GetProcAddress16( GetModuleHandle16("KERNEL"), "DefResourceHandler" );
174 /***********************************************************************
177 * Find the type and resource id from their names.
178 * Return value is MAKELONG( typeId, resId ), or 0 if not found.
180 static DWORD
NE_FindNameTableId( NE_MODULE
*pModule
, LPCSTR typeId
, LPCSTR resId
)
182 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
183 NE_NAMEINFO
*pNameInfo
;
189 for (; pTypeInfo
->type_id
!= 0;
190 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+1) +
191 pTypeInfo
->count
* sizeof(NE_NAMEINFO
)))
193 if (pTypeInfo
->type_id
!= 0x800f) continue;
194 pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
195 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
197 TRACE("NameTable entry: type=%04x id=%04x\n",
198 pTypeInfo
->type_id
, pNameInfo
->id
);
199 handle
= LoadResource16( pModule
->self
,
200 (HRSRC16
)((int)pNameInfo
- (int)pModule
) );
201 for(p
= (WORD
*)LockResource16(handle
); p
&& *p
; p
= (WORD
*)((char*)p
+*p
))
203 TRACE(" type=%04x '%s' id=%04x '%s'\n",
204 p
[1], (char *)(p
+3), p
[2],
205 (char *)(p
+3)+strlen((char *)(p
+3))+1 );
206 /* Check for correct type */
210 if (!HIWORD(typeId
)) continue;
211 if (strcasecmp( typeId
, (char *)(p
+ 3) )) continue;
213 else if (HIWORD(typeId
) || (((DWORD
)typeId
& ~0x8000)!= p
[1]))
216 /* Now check for the id */
220 if (!HIWORD(resId
)) continue;
221 if (strcasecmp( resId
, (char*)(p
+3)+strlen((char*)(p
+3))+1 )) continue;
224 else if (HIWORD(resId
) || (((DWORD
)resId
& ~0x8000) != p
[2]))
227 /* If we get here, we've found the entry */
230 ret
= MAKELONG( p
[1], p
[2] );
233 FreeResource16( handle
);
241 /***********************************************************************
244 * Find header struct for a particular resource type.
246 static NE_TYPEINFO
*NE_FindTypeSection( LPBYTE pResTab
, NE_TYPEINFO
*pTypeInfo
, LPCSTR typeId
)
248 /* start from pTypeInfo */
250 if (HIWORD(typeId
) != 0) /* Named type */
253 BYTE len
= strlen( str
);
254 while (pTypeInfo
->type_id
)
256 if (!(pTypeInfo
->type_id
& 0x8000))
258 BYTE
*p
= pResTab
+ pTypeInfo
->type_id
;
259 if ((*p
== len
) && !strncasecmp( p
+1, str
, len
))
261 TRACE(" Found type '%s'\n", str
);
265 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
266 pTypeInfo
= next_typeinfo(pTypeInfo
);
269 else /* Numeric type id */
271 WORD id
= LOWORD(typeId
) | 0x8000;
272 while (pTypeInfo
->type_id
)
274 if (pTypeInfo
->type_id
== id
)
276 TRACE(" Found type %04x\n", id
);
279 TRACE(" Skipping type %04x\n", pTypeInfo
->type_id
);
280 pTypeInfo
= next_typeinfo(pTypeInfo
);
287 /***********************************************************************
288 * NE_FindResourceFromType
290 * Find a resource once the type info structure has been found.
292 static NE_NAMEINFO
*NE_FindResourceFromType( LPBYTE pResTab
, NE_TYPEINFO
*pTypeInfo
, LPCSTR resId
)
296 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
298 if (HIWORD(resId
) != 0) /* Named resource */
301 BYTE len
= strlen( str
);
302 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
304 if (pNameInfo
->id
& 0x8000) continue;
305 p
= pResTab
+ pNameInfo
->id
;
306 if ((*p
== len
) && !strncasecmp( p
+1, str
, len
))
310 else /* Numeric resource id */
312 WORD id
= LOWORD(resId
) | 0x8000;
313 for (count
= pTypeInfo
->count
; count
> 0; count
--, pNameInfo
++)
314 if (pNameInfo
->id
== id
) return pNameInfo
;
320 /***********************************************************************
321 * DefResourceHandler (KERNEL.456)
323 * This is the default LoadProc() function.
325 HGLOBAL16 WINAPI
NE_DefResourceHandler( HGLOBAL16 hMemObj
, HMODULE16 hModule
,
329 NE_MODULE
* pModule
= NE_GetPtr( hModule
);
330 if (pModule
&& (pModule
->flags
& NE_FFLAGS_BUILTIN
))
333 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
334 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
337 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
339 handle
= AllocResource16( hModule
, hRsrc
, 0 );
343 /* NOTE: hRsrcMap points to start of built-in resource data */
344 memcpy( GlobalLock16( handle
),
345 (char *)pModule
->hRsrcMap
+ (pNameInfo
->offset
<< sizeShift
),
346 pNameInfo
->length
<< sizeShift
);
350 if (pModule
&& (fd
= NE_OpenFile( pModule
)) != INVALID_HANDLE_VALUE
)
353 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
354 NE_NAMEINFO
* pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
356 TRACE("loading, pos=%d, len=%d\n",
357 (int)pNameInfo
->offset
<< sizeShift
,
358 (int)pNameInfo
->length
<< sizeShift
);
360 handle
= GlobalReAlloc16( hMemObj
, pNameInfo
->length
<< sizeShift
, 0 );
362 handle
= AllocResource16( hModule
, hRsrc
, 0 );
367 SetFilePointer( fd
, (int)pNameInfo
->offset
<< sizeShift
, NULL
, SEEK_SET
);
368 ReadFile( fd
, GlobalLock16( handle
), (int)pNameInfo
->length
<< sizeShift
,
378 /**********************************************************************
379 * SetResourceHandler (KERNEL.67)
381 FARPROC16 WINAPI
SetResourceHandler16( HMODULE16 hModule
, LPCSTR typeId
, FARPROC16 resourceHandler
)
384 NE_TYPEINFO
*pTypeInfo
;
385 FARPROC16 prevHandler
= NULL
;
386 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
388 if (!pModule
|| !pModule
->res_table
) return NULL
;
390 pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
391 pTypeInfo
= (NE_TYPEINFO
*)(pResTab
+ 2);
393 TRACE("module=%04x type=%s\n", hModule
, debugstr_a(typeId
) );
397 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, typeId
)))
399 memcpy_unaligned( &prevHandler
, &pTypeInfo
->resloader
, sizeof(FARPROC16
) );
400 memcpy_unaligned( &pTypeInfo
->resloader
, &resourceHandler
, sizeof(FARPROC16
) );
401 pTypeInfo
= next_typeinfo(pTypeInfo
);
403 if (!prevHandler
) prevHandler
= get_default_res_handler();
408 /**********************************************************************
409 * ConvertDialog32To16 (KERNEL.615)
411 VOID WINAPI
ConvertDialog32To16( LPVOID dialog32
, DWORD size
, LPVOID dialog16
)
414 WORD nbItems
, data
, dialogEx
;
417 style
= *((DWORD
*)dialog16
)++ = *((DWORD
*)p
)++;
418 dialogEx
= (style
== 0xffff0001); /* DIALOGEX resource */
421 *((DWORD
*)dialog16
)++ = *((DWORD
*)p
)++; /* helpID */
422 *((DWORD
*)dialog16
)++ = *((DWORD
*)p
)++; /* exStyle */
423 style
= *((DWORD
*)dialog16
)++ = *((DWORD
*)p
)++; /* style */
426 ((DWORD
*)p
)++; /* exStyle ignored in 16-bit standard dialog */
428 nbItems
= *((BYTE
*)dialog16
)++ = (BYTE
)*((WORD
*)p
)++;
429 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* x */
430 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* y */
431 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* cx */
432 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* cy */
434 /* Transfer menu name */
435 switch (*((WORD
*)p
))
437 case 0x0000: ((WORD
*)p
)++; *((BYTE
*)dialog16
)++ = 0; break;
438 case 0xffff: ((WORD
*)p
)++; *((BYTE
*)dialog16
)++ = 0xff;
439 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; break;
440 default: WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)p
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
,NULL
);
441 ((LPSTR
)dialog16
) += strlen( (LPSTR
)dialog16
) + 1;
442 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
446 /* Transfer class name */
447 switch (*((WORD
*)p
))
449 case 0x0000: ((WORD
*)p
)++; *((BYTE
*)dialog16
)++ = 0; break;
450 case 0xffff: ((WORD
*)p
)++; *((BYTE
*)dialog16
)++ = 0xff;
451 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; break;
452 default: WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)p
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
,NULL
);
453 ((LPSTR
)dialog16
) += strlen( (LPSTR
)dialog16
) + 1;
454 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
458 /* Transfer window caption */
459 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)p
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
,NULL
);
460 ((LPSTR
)dialog16
) += strlen( (LPSTR
)dialog16
) + 1;
461 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
463 /* Transfer font info */
464 if (style
& DS_SETFONT
)
466 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* pointSize */
469 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* weight */
470 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* italic */
472 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)p
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
,NULL
); /* faceName */
473 ((LPSTR
)dialog16
) += strlen( (LPSTR
)dialog16
) + 1;
474 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
477 /* Transfer dialog items */
480 /* align on DWORD boundary (32-bit only) */
481 p
= (LPVOID
)((((int)p
) + 3) & ~3);
485 *((DWORD
*)dialog16
)++ = *((DWORD
*)p
)++; /* helpID */
486 *((DWORD
*)dialog16
)++ = *((DWORD
*)p
)++; /* exStyle */
487 *((DWORD
*)dialog16
)++ = *((DWORD
*)p
)++; /* style */
491 style
= *((DWORD
*)p
)++; /* save style */
492 ((DWORD
*)p
)++; /* ignore exStyle */
495 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* x */
496 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* y */
497 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* cx */
498 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* cy */
501 *((DWORD
*)dialog16
)++ = *((DWORD
*)p
)++; /* ID */
504 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; /* ID */
505 *((DWORD
*)dialog16
)++ = style
; /* style from above */
508 /* Transfer class name */
509 switch (*((WORD
*)p
))
511 case 0x0000: ((WORD
*)p
)++; *((BYTE
*)dialog16
)++ = 0; break;
512 case 0xffff: ((WORD
*)p
)++;
513 *((BYTE
*)dialog16
)++ = (BYTE
)*((WORD
*)p
)++; break;
514 default: WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)p
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
,NULL
);
515 ((LPSTR
)dialog16
) += strlen( (LPSTR
)dialog16
) + 1;
516 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
520 /* Transfer window name */
521 switch (*((WORD
*)p
))
523 case 0x0000: ((WORD
*)p
)++; *((BYTE
*)dialog16
)++ = 0; break;
524 case 0xffff: ((WORD
*)p
)++; *((BYTE
*)dialog16
)++ = 0xff;
525 *((WORD
*)dialog16
)++ = *((WORD
*)p
)++; break;
526 default: WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)p
, -1, (LPSTR
)dialog16
, 0x7fffffff, NULL
,NULL
);
527 ((LPSTR
)dialog16
) += strlen( (LPSTR
)dialog16
) + 1;
528 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
533 data
= *((WORD
*)p
)++;
535 *((WORD
*)dialog16
)++ = data
;
537 *((BYTE
*)dialog16
)++ = (BYTE
)data
;
541 memcpy( dialog16
, p
, data
);
542 (LPSTR
)dialog16
+= data
;
552 /**********************************************************************
553 * GetDialog32Size (KERNEL.618)
555 WORD WINAPI
GetDialog32Size16( LPVOID dialog32
)
558 WORD nbItems
, data
, dialogEx
;
561 style
= *((DWORD
*)p
)++;
562 dialogEx
= (style
== 0xffff0001); /* DIALOGEX resource */
565 ((DWORD
*)p
)++; /* helpID */
566 ((DWORD
*)p
)++; /* exStyle */
567 style
= *((DWORD
*)p
)++; /* style */
570 ((DWORD
*)p
)++; /* exStyle */
572 nbItems
= *((WORD
*)p
)++;
573 ((WORD
*)p
)++; /* x */
574 ((WORD
*)p
)++; /* y */
575 ((WORD
*)p
)++; /* cx */
576 ((WORD
*)p
)++; /* cy */
579 switch (*((WORD
*)p
))
581 case 0x0000: ((WORD
*)p
)++; break;
582 case 0xffff: ((WORD
*)p
) += 2; break;
583 default: ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1; break;
586 /* Skip class name */
587 switch (*((WORD
*)p
))
589 case 0x0000: ((WORD
*)p
)++; break;
590 case 0xffff: ((WORD
*)p
) += 2; break;
591 default: ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1; break;
594 /* Skip window caption */
595 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
598 if (style
& DS_SETFONT
)
600 ((WORD
*)p
)++; /* pointSize */
603 ((WORD
*)p
)++; /* weight */
604 ((WORD
*)p
)++; /* italic */
606 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1; /* faceName */
609 /* Skip dialog items */
612 /* align on DWORD boundary */
613 p
= (LPVOID
)((((int)p
) + 3) & ~3);
617 ((DWORD
*)p
)++; /* helpID */
618 ((DWORD
*)p
)++; /* exStyle */
619 ((DWORD
*)p
)++; /* style */
623 ((DWORD
*)p
)++; /* style */
624 ((DWORD
*)p
)++; /* exStyle */
627 ((WORD
*)p
)++; /* x */
628 ((WORD
*)p
)++; /* y */
629 ((WORD
*)p
)++; /* cx */
630 ((WORD
*)p
)++; /* cy */
633 ((DWORD
*)p
)++; /* ID */
635 ((WORD
*)p
)++; /* ID */
637 /* Skip class name */
638 switch (*((WORD
*)p
))
640 case 0x0000: ((WORD
*)p
)++; break;
641 case 0xffff: ((WORD
*)p
) += 2; break;
642 default: ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1; break;
645 /* Skip window name */
646 switch (*((WORD
*)p
))
648 case 0x0000: ((WORD
*)p
)++; break;
649 case 0xffff: ((WORD
*)p
) += 2; break;
650 default: ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1; break;
654 data
= *((WORD
*)p
)++;
661 return (WORD
)((LPSTR
)p
- (LPSTR
)dialog32
);
665 /**********************************************************************
666 * ConvertMenu32To16 (KERNEL.616)
668 VOID WINAPI
ConvertMenu32To16( LPVOID menu32
, DWORD size
, LPVOID menu16
)
671 WORD version
, headersize
, flags
, level
= 1;
673 version
= *((WORD
*)menu16
)++ = *((WORD
*)p
)++;
674 headersize
= *((WORD
*)menu16
)++ = *((WORD
*)p
)++;
677 memcpy( menu16
, p
, headersize
);
678 ((LPSTR
)menu16
) += headersize
;
679 ((LPSTR
)p
) += headersize
;
683 if ( version
== 0 ) /* standard */
685 flags
= *((WORD
*)menu16
)++ = *((WORD
*)p
)++;
686 if ( !(flags
& MF_POPUP
) )
687 *((WORD
*)menu16
)++ = *((WORD
*)p
)++; /* ID */
691 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)p
, -1, (LPSTR
)menu16
, 0x7fffffff, NULL
,NULL
);
692 ((LPSTR
)menu16
) += strlen( (LPSTR
)menu16
) + 1;
693 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
695 if ( flags
& MF_END
)
700 *((DWORD
*)menu16
)++ = *((DWORD
*)p
)++; /* fType */
701 *((DWORD
*)menu16
)++ = *((DWORD
*)p
)++; /* fState */
702 *((WORD
*)menu16
)++ = (WORD
)*((DWORD
*)p
)++; /* ID */
703 flags
= *((BYTE
*)menu16
)++ = (BYTE
)*((WORD
*)p
)++;
705 WideCharToMultiByte( CP_ACP
, 0, (LPWSTR
)p
, -1, (LPSTR
)menu16
, 0x7fffffff, NULL
,NULL
);
706 ((LPSTR
)menu16
) += strlen( (LPSTR
)menu16
) + 1;
707 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
709 /* align on DWORD boundary (32-bit only) */
710 p
= (LPVOID
)((((int)p
) + 3) & ~3);
712 /* If popup, transfer helpid */
715 *((DWORD
*)menu16
)++ = *((DWORD
*)p
)++;
719 if ( flags
& MF_END
)
725 /**********************************************************************
726 * GetMenu32Size (KERNEL.617)
728 WORD WINAPI
GetMenu32Size16( LPVOID menu32
)
731 WORD version
, headersize
, flags
, level
= 1;
733 version
= *((WORD
*)p
)++;
734 headersize
= *((WORD
*)p
)++;
735 ((LPSTR
)p
) += headersize
;
738 if ( version
== 0 ) /* standard */
740 flags
= *((WORD
*)p
)++;
741 if ( !(flags
& MF_POPUP
) )
742 ((WORD
*)p
)++; /* ID */
746 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
748 if ( flags
& MF_END
)
753 ((DWORD
*)p
)++; /* fType */
754 ((DWORD
*)p
)++; /* fState */
755 ((DWORD
*)p
)++; /* ID */
756 flags
= *((WORD
*)p
)++;
758 ((LPWSTR
)p
) += strlenW( (LPWSTR
)p
) + 1;
760 /* align on DWORD boundary (32-bit only) */
761 p
= (LPVOID
)((((int)p
) + 3) & ~3);
763 /* If popup, skip helpid */
770 if ( flags
& MF_END
)
774 return (WORD
)((LPSTR
)p
- (LPSTR
)menu32
);
778 /**********************************************************************
779 * ConvertAccelerator32To16
781 static void ConvertAccelerator32To16( LPVOID acc32
, DWORD size
, LPVOID acc16
)
788 type
= *((BYTE
*)acc16
)++ = *((BYTE
*)acc32
)++;
791 /* Copy event and IDval */
792 *((WORD
*)acc16
)++ = *((WORD
*)acc32
)++;
793 *((WORD
*)acc16
)++ = *((WORD
*)acc32
)++;
797 } while ( !( type
& 0x80 ) );
801 /**********************************************************************
804 static HGLOBAL16
NE_LoadPEResource( NE_MODULE
*pModule
, WORD type
, LPVOID bits
, DWORD size
)
808 TRACE("module=%04x type=%04x\n", pModule
->self
, type
);
810 handle
= GlobalAlloc16( 0, size
);
815 ConvertMenu32To16( bits
, size
, GlobalLock16( handle
) );
818 ConvertDialog32To16( bits
, size
, GlobalLock16( handle
) );
821 ConvertAccelerator32To16( bits
, size
, GlobalLock16( handle
) );
824 FIXME("not yet implemented!\n" );
827 memcpy( GlobalLock16( handle
), bits
, size
);
834 /**********************************************************************
835 * AllocResource (KERNEL.66)
837 HGLOBAL16 WINAPI
AllocResource16( HMODULE16 hModule
, HRSRC16 hRsrc
, DWORD size
)
839 NE_NAMEINFO
*pNameInfo
=NULL
;
843 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
844 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return 0;
846 TRACE("module=%04x res=%04x size=%ld\n", hModule
, hRsrc
, size
);
848 sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
849 pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
850 if (size
< (DWORD
)pNameInfo
->length
<< sizeShift
)
851 size
= (DWORD
)pNameInfo
->length
<< sizeShift
;
852 ret
= GlobalAlloc16( GMEM_FIXED
, size
);
853 if (ret
) FarSetOwner16( ret
, hModule
);
858 /**********************************************************************
859 * DirectResAlloc (KERNEL.168)
861 * Check Schulman, p. 232 for details
863 HGLOBAL16 WINAPI
DirectResAlloc16( HINSTANCE16 hInstance
, WORD wType
,
867 TRACE("(%04x,%04x,%04x)\n", hInstance
, wType
, wSize
);
868 if (!(hInstance
= GetExePtr( hInstance
))) return 0;
869 if(wType
!= 0x10) /* 0x10 is the only observed value, passed from
870 CreateCursorIndirect. */
871 TRACE("(wType=%x)\n", wType
);
872 ret
= GlobalAlloc16( GMEM_MOVEABLE
, wSize
);
873 if (ret
) FarSetOwner16( ret
, hInstance
);
878 /**********************************************************************
879 * AccessResource (KERNEL.64)
881 INT16 WINAPI
AccessResource16( HINSTANCE16 hModule
, HRSRC16 hRsrc
)
884 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
886 if (!pModule
|| !pModule
->res_table
|| !hRsrc
) return -1;
888 TRACE("module=%04x res=%04x\n", pModule
->self
, hRsrc
);
890 if ((fd
= _lopen16( NE_MODULE_NAME(pModule
), OF_READ
)) != HFILE_ERROR16
)
892 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
893 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
894 _llseek16( fd
, (int)pNameInfo
->offset
<< sizeShift
, SEEK_SET
);
900 /**********************************************************************
901 * FindResource (KERNEL.60)
903 HRSRC16 WINAPI
FindResource16( HMODULE16 hModule
, LPCSTR name
, LPCSTR type
)
905 NE_TYPEINFO
*pTypeInfo
;
906 NE_NAMEINFO
*pNameInfo
;
908 NE_MODULE
*pModule
= get_module( hModule
);
910 if (!pModule
) return 0;
912 if (pModule
->module32
)
914 /* 32-bit PE module */
915 HRSRC hRsrc32
= FindResourceA( pModule
->module32
, name
, type
);
916 return MapHRsrc32To16( pModule
, hRsrc32
, HIWORD(type
) ? 0 : LOWORD(type
) );
919 TRACE("module=%04x name=%s type=%s\n", pModule
->self
, debugstr_a(name
), debugstr_a(type
) );
921 if (!pModule
->res_table
) return 0;
923 type
= get_res_name( type
);
924 name
= get_res_name( name
);
926 if (HIWORD(type
) || HIWORD(name
))
928 DWORD id
= NE_FindNameTableId( pModule
, type
, name
);
931 type
= (LPCSTR
)(ULONG_PTR
)LOWORD(id
);
932 name
= (LPCSTR
)(ULONG_PTR
)HIWORD(id
);
935 pResTab
= (LPBYTE
)pModule
+ pModule
->res_table
;
936 pTypeInfo
= (NE_TYPEINFO
*)( pResTab
+ 2 );
940 if (!(pTypeInfo
= NE_FindTypeSection( pResTab
, pTypeInfo
, type
))) break;
941 if ((pNameInfo
= NE_FindResourceFromType( pResTab
, pTypeInfo
, name
)))
943 TRACE(" Found id %08lx\n", (DWORD
)name
);
944 return (HRSRC16
)( (char *)pNameInfo
- (char *)pModule
);
946 pTypeInfo
= next_typeinfo(pTypeInfo
);
952 /**********************************************************************
953 * LoadResource (KERNEL.61)
955 HGLOBAL16 WINAPI
LoadResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
957 NE_TYPEINFO
*pTypeInfo
;
958 NE_NAMEINFO
*pNameInfo
= NULL
;
959 NE_MODULE
*pModule
= get_module( hModule
);
962 if (!hRsrc
|| !pModule
) return 0;
964 if (pModule
->module32
)
966 /* load 32-bit resource and convert it */
967 HRSRC hRsrc32
= MapHRsrc16To32( pModule
, hRsrc
);
968 WORD type
= MapHRsrc16ToType( pModule
, hRsrc
);
969 HGLOBAL hMem
= LoadResource( pModule
->module32
, hRsrc32
);
970 DWORD size
= SizeofResource( pModule
->module32
, hRsrc32
);
972 return NE_LoadPEResource( pModule
, type
, LockResource( hMem
), size
);
975 /* first, verify hRsrc (just an offset from pModule to the needed pNameInfo) */
977 d
= pModule
->res_table
+ 2;
978 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
981 if (pTypeInfo
->type_id
== 0) break; /* terminal entry */
982 d
+= sizeof(NE_TYPEINFO
) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
);
985 if( ((d
- hRsrc
)%sizeof(NE_NAMEINFO
)) == 0 )
987 pNameInfo
= (NE_NAMEINFO
*)((char *)pModule
+ hRsrc
);
990 else break; /* NE_NAMEINFO boundary mismatch */
992 pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ d
);
997 if (pNameInfo
->handle
&& !(GlobalFlags16(pNameInfo
->handle
) & GMEM_DISCARDED
))
1000 TRACE(" Already loaded, new count=%d\n", pNameInfo
->usage
);
1004 FARPROC16 resloader
;
1005 memcpy_unaligned( &resloader
, &pTypeInfo
->resloader
, sizeof(FARPROC16
) );
1006 if (resloader
&& resloader
!= get_default_res_handler())
1011 args
[2] = pNameInfo
->handle
;
1012 args
[1] = pModule
->self
;
1014 WOWCallback16Ex( (DWORD
)resloader
, WCB16_PASCAL
, sizeof(args
), args
, &ret
);
1015 pNameInfo
->handle
= LOWORD(ret
);
1018 pNameInfo
->handle
= NE_DefResourceHandler( pNameInfo
->handle
, pModule
->self
, hRsrc
);
1020 if (pNameInfo
->handle
)
1023 pNameInfo
->flags
|= NE_SEGFLAGS_LOADED
;
1026 return pNameInfo
->handle
;
1032 /**********************************************************************
1033 * LockResource (KERNEL.62)
1035 SEGPTR WINAPI
WIN16_LockResource16( HGLOBAL16 handle
)
1037 TRACE("(%04x)\n", handle
);
1038 /* May need to reload the resource if discarded */
1039 return K32WOWGlobalLock16( handle
);
1043 /**********************************************************************
1044 * LockResource16 (KERNEL32.@)
1046 LPVOID WINAPI
LockResource16( HGLOBAL16 handle
)
1048 return MapSL( WIN16_LockResource16(handle
) );
1052 /**********************************************************************
1053 * SizeofResource (KERNEL.65)
1055 DWORD WINAPI
SizeofResource16( HMODULE16 hModule
, HRSRC16 hRsrc
)
1057 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
1059 TRACE("(%x, %x)\n", hModule
, hRsrc
);
1061 if (!hRsrc
) return 0;
1062 if (!(pModule
= get_module( hModule
))) return 0;
1063 if (pModule
->res_table
)
1065 WORD sizeShift
= *(WORD
*)((char *)pModule
+ pModule
->res_table
);
1066 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)((char*)pModule
+ hRsrc
);
1067 return (DWORD
)pNameInfo
->length
<< sizeShift
;
1069 if (pModule
->module32
)
1071 /* 32-bit PE module */
1072 return SizeofResource( pModule
->module32
, MapHRsrc16To32( pModule
, hRsrc
) );
1078 typedef WORD (WINAPI
*pDestroyIcon32Proc
)( HGLOBAL16 handle
, UINT16 flags
);
1080 /**********************************************************************
1081 * FreeResource (KERNEL.63)
1083 BOOL16 WINAPI
FreeResource16( HGLOBAL16 handle
)
1085 pDestroyIcon32Proc proc
;
1087 NE_MODULE
*pModule
= NE_GetPtr( FarGetOwner16( handle
) );
1089 TRACE("(%04x)\n", handle
);
1091 /* Try NE resource first */
1093 if (pModule
&& pModule
->res_table
)
1095 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->res_table
+ 2);
1096 while (pTypeInfo
->type_id
)
1099 NE_NAMEINFO
*pNameInfo
= (NE_NAMEINFO
*)(pTypeInfo
+ 1);
1100 for (count
= pTypeInfo
->count
; count
> 0; count
--)
1102 if (pNameInfo
->handle
== handle
)
1104 if (pNameInfo
->usage
> 0) pNameInfo
->usage
--;
1105 if (pNameInfo
->usage
== 0)
1107 GlobalFree16( pNameInfo
->handle
);
1108 pNameInfo
->handle
= 0;
1109 pNameInfo
->flags
&= ~NE_SEGFLAGS_LOADED
;
1115 pTypeInfo
= (NE_TYPEINFO
*)pNameInfo
;
1119 /* If this failed, call USER.DestroyIcon32; this will check
1120 whether it is a shared cursor/icon; if not it will call
1122 user
= GetModuleHandleA( "user32.dll" );
1123 if (user
&& (proc
= (pDestroyIcon32Proc
)GetProcAddress( user
, "DestroyIcon32" )))
1124 return proc( handle
, 1 /*CID_RESOURCE*/ );
1126 return GlobalFree16( handle
);