4 * Copyright 1995 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
36 #include "wine/winbase16.h"
40 #include "kernel_private.h"
41 #include "kernel16_private.h"
42 #include "wine/exception.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(module
);
46 WINE_DECLARE_DEBUG_CHANNEL(loaddll
);
49 typedef struct _GPHANDLERDEF
61 struct ne_segment_table_entry_s
63 WORD seg_data_offset
; /* Sector offset of segment data */
64 WORD seg_data_length
; /* Length of segment data */
65 WORD seg_flags
; /* Flags associated with this segment */
66 WORD min_alloc
; /* Minimum allocation size for this */
69 #define hFirstModule (pThhook->hExeHead)
73 void *module_start
; /* 32-bit address of the module data */
74 int module_size
; /* Size of the module data */
75 void *code_start
; /* 32-bit address of DLL code */
76 void *data_start
; /* 32-bit address of DLL data */
77 const char *owner
; /* 32-bit dll that contains this dll */
78 const void *rsrc
; /* resources data */
79 } BUILTIN16_DESCRIPTOR
;
81 /* Table of all built-in DLLs */
85 static const BUILTIN16_DESCRIPTOR
*builtin_dlls
[MAX_DLLS
];
87 extern void SNOOP16_RegisterDLL(NE_MODULE
*,LPCSTR
);
88 extern FARPROC16
SNOOP16_GetProcAddress16(HMODULE16
,DWORD
,FARPROC16
);
90 static HINSTANCE16
NE_LoadModule( LPCSTR name
, BOOL lib_only
);
91 static BOOL16
NE_FreeModule( HMODULE16 hModule
, BOOL call_wep
);
93 static HINSTANCE16
MODULE_LoadModule16( LPCSTR libname
, BOOL implicit
, BOOL lib_only
);
95 static HMODULE16
NE_GetModuleByFilename( LPCSTR name
);
98 static WINE_EXCEPTION_FILTER(page_fault
)
100 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
||
101 GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION
)
102 return EXCEPTION_EXECUTE_HANDLER
;
103 return EXCEPTION_CONTINUE_SEARCH
;
107 /* patch all the flat cs references of the code segment if necessary */
108 inline static void patch_code_segment( void *code_segment
)
111 CALLFROM16
*call
= code_segment
;
112 if (call
->flatcs
== wine_get_cs()) return; /* nothing to patch */
113 while (call
->pushl
== 0x68)
115 call
->flatcs
= wine_get_cs();
122 /***********************************************************************
125 * locale-independent case conversion for module lookups
127 static int NE_strcasecmp( const char *str1
, const char *str2
)
130 for ( ; ; str1
++, str2
++)
131 if ((ret
= RtlUpperChar(*str1
) - RtlUpperChar(*str2
)) || !*str1
) break;
136 /***********************************************************************
139 * locale-independent case conversion for module lookups
141 static int NE_strncasecmp( const char *str1
, const char *str2
, int len
)
144 for ( ; len
> 0; len
--, str1
++, str2
++)
145 if ((ret
= RtlUpperChar(*str1
) - RtlUpperChar(*str2
)) || !*str1
) break;
150 /***********************************************************************
153 * Find a descriptor in the list
155 static const BUILTIN16_DESCRIPTOR
*find_dll_descr( const char *dllname
)
158 for (i
= 0; i
< MAX_DLLS
; i
++)
160 const BUILTIN16_DESCRIPTOR
*descr
= builtin_dlls
[i
];
163 IMAGE_OS2_HEADER
*pModule
= descr
->module_start
;
164 OFSTRUCT
*pOfs
= (OFSTRUCT
*)(pModule
+ 1);
165 BYTE
*name_table
= (BYTE
*)pModule
+ pModule
->ne_restab
;
167 /* check the dll file name */
168 if (!NE_strcasecmp( pOfs
->szPathName
, dllname
)) return descr
;
169 /* check the dll module name (without extension) */
170 if (!NE_strncasecmp( dllname
, name_table
+1, *name_table
) &&
171 !strcmp( dllname
+ *name_table
, ".dll" ))
179 /***********************************************************************
180 * __wine_register_dll_16 (KERNEL32.@)
182 * Register a built-in DLL descriptor.
184 void __wine_register_dll_16( const BUILTIN16_DESCRIPTOR
*descr
)
188 for (i
= 0; i
< MAX_DLLS
; i
++)
190 if (builtin_dlls
[i
]) continue;
191 builtin_dlls
[i
] = descr
;
194 assert( i
< MAX_DLLS
);
198 /***********************************************************************
199 * __wine_unregister_dll_16 (KERNEL32.@)
201 * Unregister a built-in DLL descriptor.
203 void __wine_unregister_dll_16( const BUILTIN16_DESCRIPTOR
*descr
)
207 for (i
= 0; i
< MAX_DLLS
; i
++)
209 if (builtin_dlls
[i
] != descr
) continue;
210 builtin_dlls
[i
] = NULL
;
216 /***********************************************************************
219 NE_MODULE
*NE_GetPtr( HMODULE16 hModule
)
221 return (NE_MODULE
*)GlobalLock16( GetExePtr(hModule
) );
225 /**********************************************************************
228 static void NE_RegisterModule( NE_MODULE
*pModule
)
230 pModule
->next
= hFirstModule
;
231 hFirstModule
= pModule
->self
;
235 /***********************************************************************
238 void NE_DumpModule( HMODULE16 hModule
)
248 if (!(pModule
= NE_GetPtr( hModule
)))
250 MESSAGE( "**** %04x is not a module handle\n", hModule
);
254 /* Dump the module info */
256 DPRINTF( "Module %04x:\n", hModule
);
257 DPRINTF( "count=%d flags=%04x heap=%d stack=%d\n",
258 pModule
->count
, pModule
->ne_flags
,
259 pModule
->ne_heap
, pModule
->ne_stack
);
260 DPRINTF( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
261 SELECTOROF(pModule
->ne_csip
), OFFSETOF(pModule
->ne_csip
),
262 SELECTOROF(pModule
->ne_sssp
), OFFSETOF(pModule
->ne_sssp
),
263 pModule
->ne_autodata
, pModule
->ne_cseg
, pModule
->ne_cmod
);
264 DPRINTF( "os_flags=%d swap_area=%d version=%04x\n",
265 pModule
->ne_exetyp
, pModule
->ne_swaparea
, pModule
->ne_expver
);
266 if (pModule
->ne_flags
& NE_FFLAGS_WIN32
)
267 DPRINTF( "PE module=%p\n", pModule
->module32
);
269 /* Dump the file info */
271 DPRINTF( "Filename: '%s'\n", NE_MODULE_NAME(pModule
) );
273 /* Dump the segment table */
275 DPRINTF( "Segment table:\n" );
276 pSeg
= NE_SEG_TABLE( pModule
);
277 for (i
= 0; i
< pModule
->ne_cseg
; i
++, pSeg
++)
278 DPRINTF( "%02x: pos=%d size=%d flags=%04x minsize=%d hSeg=%04x\n",
279 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
280 pSeg
->minsize
, pSeg
->hSeg
);
282 /* Dump the resource table */
284 DPRINTF( "Resource table:\n" );
285 if (pModule
->ne_rsrctab
)
287 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->ne_rsrctab
);
288 DPRINTF( "Alignment: %d\n", *pword
++ );
291 NE_TYPEINFO
*ptr
= (NE_TYPEINFO
*)pword
;
292 NE_NAMEINFO
*pname
= (NE_NAMEINFO
*)(ptr
+ 1);
293 DPRINTF( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
294 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
295 DPRINTF( "offset=%d len=%d id=%04x\n",
296 pname
->offset
, pname
->length
, pname
->id
);
297 pword
= (WORD
*)pname
;
300 else DPRINTF( "None\n" );
302 /* Dump the resident name table */
304 DPRINTF( "Resident-name table:\n" );
305 pstr
= (char *)pModule
+ pModule
->ne_restab
;
308 DPRINTF( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
309 *(WORD
*)(pstr
+ *pstr
+ 1) );
310 pstr
+= *pstr
+ 1 + sizeof(WORD
);
313 /* Dump the module reference table */
315 DPRINTF( "Module ref table:\n" );
316 if (pModule
->ne_modtab
)
318 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->ne_modtab
);
319 for (i
= 0; i
< pModule
->ne_cmod
; i
++, pword
++)
322 GetModuleName16( *pword
, name
, sizeof(name
) );
323 DPRINTF( "%d: %04x -> '%s'\n", i
, *pword
, name
);
326 else DPRINTF( "None\n" );
328 /* Dump the entry table */
330 DPRINTF( "Entry table:\n" );
331 bundle
= (ET_BUNDLE
*)((BYTE
*)pModule
+pModule
->ne_enttab
);
333 entry
= (ET_ENTRY
*)((BYTE
*)bundle
+6);
334 DPRINTF( "Bundle %d-%d: %02x\n", bundle
->first
, bundle
->last
, entry
->type
);
335 ordinal
= bundle
->first
;
336 while (ordinal
< bundle
->last
)
338 if (entry
->type
== 0xff)
339 DPRINTF("%d: %02x:%04x (moveable)\n", ordinal
++, entry
->segnum
, entry
->offs
);
341 DPRINTF("%d: %02x:%04x (fixed)\n", ordinal
++, entry
->segnum
, entry
->offs
);
344 } while ( (bundle
->next
) && (bundle
= ((ET_BUNDLE
*)((BYTE
*)pModule
+ bundle
->next
))) );
346 /* Dump the non-resident names table */
348 DPRINTF( "Non-resident names table:\n" );
349 if (pModule
->nrname_handle
)
351 pstr
= (char *)GlobalLock16( pModule
->nrname_handle
);
354 DPRINTF( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
355 *(WORD
*)(pstr
+ *pstr
+ 1) );
356 pstr
+= *pstr
+ 1 + sizeof(WORD
);
363 /***********************************************************************
366 * Walk the module list and print the modules.
368 void NE_WalkModules(void)
370 HMODULE16 hModule
= hFirstModule
;
371 MESSAGE( "Module Flags Name\n" );
374 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
377 MESSAGE( "Bad module %04x in list\n", hModule
);
380 MESSAGE( " %04x %04x %.*s\n", hModule
, pModule
->ne_flags
,
381 *((char *)pModule
+ pModule
->ne_restab
),
382 (char *)pModule
+ pModule
->ne_restab
+ 1 );
383 hModule
= pModule
->next
;
388 /***********************************************************************
389 * NE_InitResourceHandler
391 * Fill in 'resloader' fields in the resource table.
393 static void NE_InitResourceHandler( NE_MODULE
*pModule
)
395 static FARPROC16 proc
;
397 NE_TYPEINFO
*pTypeInfo
= (NE_TYPEINFO
*)((char *)pModule
+ pModule
->ne_rsrctab
+ 2);
399 TRACE("InitResourceHandler[%04x]\n", pModule
->self
);
401 if (!proc
) proc
= GetProcAddress16( GetModuleHandle16("KERNEL"), "DefResourceHandler" );
403 while(pTypeInfo
->type_id
)
405 memcpy_unaligned( &pTypeInfo
->resloader
, &proc
, sizeof(FARPROC16
) );
406 pTypeInfo
= (NE_TYPEINFO
*)((char*)(pTypeInfo
+ 1) + pTypeInfo
->count
* sizeof(NE_NAMEINFO
));
411 /***********************************************************************
414 * Lookup the ordinal for a given name.
416 WORD
NE_GetOrdinal( HMODULE16 hModule
, const char *name
)
418 unsigned char buffer
[256], *cpnt
;
422 if (!(pModule
= NE_GetPtr( hModule
))) return 0;
423 if (pModule
->ne_flags
& NE_FFLAGS_WIN32
) return 0;
425 TRACE("(%04x,'%s')\n", hModule
, name
);
427 /* First handle names of the form '#xxxx' */
429 if (name
[0] == '#') return atoi( name
+ 1 );
431 /* Now copy and uppercase the string */
433 strcpy( buffer
, name
);
434 for (cpnt
= buffer
; *cpnt
; cpnt
++) *cpnt
= RtlUpperChar(*cpnt
);
437 /* First search the resident names */
439 cpnt
= (char *)pModule
+ pModule
->ne_restab
;
441 /* Skip the first entry (module name) */
442 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
445 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
448 memcpy( &ordinal
, cpnt
+ *cpnt
+ 1, sizeof(ordinal
) );
449 TRACE(" Found: ordinal=%d\n", ordinal
);
452 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
455 /* Now search the non-resident names table */
457 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
458 cpnt
= (char *)GlobalLock16( pModule
->nrname_handle
);
460 /* Skip the first entry (module description string) */
461 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
464 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
467 memcpy( &ordinal
, cpnt
+ *cpnt
+ 1, sizeof(ordinal
) );
468 TRACE(" Found: ordinal=%d\n", ordinal
);
471 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
477 /***********************************************************************
480 FARPROC16 WINAPI
NE_GetEntryPoint( HMODULE16 hModule
, WORD ordinal
)
482 return NE_GetEntryPointEx( hModule
, ordinal
, TRUE
);
485 /***********************************************************************
488 FARPROC16
NE_GetEntryPointEx( HMODULE16 hModule
, WORD ordinal
, BOOL16 snoop
)
496 if (!(pModule
= NE_GetPtr( hModule
))) return 0;
497 assert( !(pModule
->ne_flags
& NE_FFLAGS_WIN32
) );
499 bundle
= (ET_BUNDLE
*)((BYTE
*)pModule
+ pModule
->ne_enttab
);
500 while ((ordinal
< bundle
->first
+ 1) || (ordinal
> bundle
->last
))
504 bundle
= (ET_BUNDLE
*)((BYTE
*)pModule
+ bundle
->next
);
507 entry
= (ET_ENTRY
*)((BYTE
*)bundle
+6);
508 for (i
=0; i
< (ordinal
- bundle
->first
- 1); i
++)
512 memcpy( &offset
, &entry
->offs
, sizeof(WORD
) );
514 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
515 else sel
= GlobalHandleToSel16(NE_SEG_TABLE(pModule
)[sel
-1].hSeg
);
517 return (FARPROC16
)MAKESEGPTR( sel
, offset
);
519 return (FARPROC16
)MAKESEGPTR( sel
, offset
);
521 return (FARPROC16
)SNOOP16_GetProcAddress16(hModule
,ordinal
,(FARPROC16
)MAKESEGPTR( sel
, offset
));
525 /***********************************************************************
526 * EntryAddrProc (KERNEL.667) Wine-specific export
528 * Return the entry point for a given ordinal.
530 FARPROC16 WINAPI
EntryAddrProc16( HMODULE16 hModule
, WORD ordinal
)
532 FARPROC16 ret
= NE_GetEntryPointEx( hModule
, ordinal
, TRUE
);
533 CURRENT_STACK16
->ecx
= hModule
; /* FIXME: might be incorrect value */
537 /***********************************************************************
540 * Change the value of an entry point. Use with caution!
541 * It can only change the offset value, not the selector.
543 BOOL16
NE_SetEntryPoint( HMODULE16 hModule
, WORD ordinal
, WORD offset
)
550 if (!(pModule
= NE_GetPtr( hModule
))) return FALSE
;
551 assert( !(pModule
->ne_flags
& NE_FFLAGS_WIN32
) );
553 bundle
= (ET_BUNDLE
*)((BYTE
*)pModule
+ pModule
->ne_enttab
);
554 while ((ordinal
< bundle
->first
+ 1) || (ordinal
> bundle
->last
))
556 bundle
= (ET_BUNDLE
*)((BYTE
*)pModule
+ bundle
->next
);
557 if (!(bundle
->next
)) return 0;
560 entry
= (ET_ENTRY
*)((BYTE
*)bundle
+6);
561 for (i
=0; i
< (ordinal
- bundle
->first
- 1); i
++)
564 memcpy( &entry
->offs
, &offset
, sizeof(WORD
) );
569 /***********************************************************************
572 HANDLE
NE_OpenFile( NE_MODULE
*pModule
)
575 char *name
= NE_MODULE_NAME( pModule
);
577 TRACE("(%p)\n", pModule
);
581 if (!DuplicateHandle( GetCurrentProcess(), pModule
->fd
,
582 GetCurrentProcess(), &handle
, 0, FALSE
,
583 DUPLICATE_SAME_ACCESS
)) handle
= INVALID_HANDLE_VALUE
;
587 handle
= CreateFileA( name
, GENERIC_READ
, FILE_SHARE_READ
,
588 NULL
, OPEN_EXISTING
, 0, 0 );
590 if (handle
== INVALID_HANDLE_VALUE
)
591 ERR( "Can't open file '%s' for module %04x\n", name
, pModule
->self
);
593 TRACE("opened '%s' -> %p\n", name
, handle
);
598 /* wrapper for SetFilePointer and ReadFile */
599 static BOOL
read_data( HANDLE handle
, LONG offset
, void *buffer
, DWORD size
)
603 if (SetFilePointer( handle
, offset
, NULL
, SEEK_SET
) == INVALID_SET_FILE_POINTER
) return FALSE
;
604 if (!ReadFile( handle
, buffer
, size
, &result
, NULL
)) return FALSE
;
605 return (result
== size
);
608 /***********************************************************************
611 static HMODULE16
NE_LoadExeHeader( HANDLE handle
, LPCSTR path
)
613 IMAGE_DOS_HEADER mz_header
;
614 IMAGE_OS2_HEADER ne_header
;
618 BYTE
*pData
, *pTempEntryTable
;
619 char *buffer
, *fastload
= NULL
;
620 unsigned int fastload_offset
= 0, fastload_length
= 0;
622 ET_BUNDLE
*bundle
, *oldbundle
;
625 /* Read a block from either the file or the fast-load area. */
626 #define READ(offset,size,buffer) \
627 ((fastload && ((offset) >= fastload_offset) && \
628 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
629 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
630 read_data( handle, (offset), (buffer), (size)))
632 if (!read_data( handle
, 0, &mz_header
, sizeof(mz_header
)) ||
633 (mz_header
.e_magic
!= IMAGE_DOS_SIGNATURE
))
634 return ERROR_BAD_FORMAT
;
636 if (!read_data( handle
, mz_header
.e_lfanew
, &ne_header
, sizeof(ne_header
) ))
637 return ERROR_BAD_FORMAT
;
639 if (ne_header
.ne_magic
== IMAGE_NT_SIGNATURE
) return (HMODULE16
)21; /* win32 exe */
640 if (ne_header
.ne_magic
== IMAGE_OS2_SIGNATURE_LX
) {
641 MESSAGE("Sorry, this is an OS/2 linear executable (LX) file!\n");
642 return (HMODULE16
)12;
644 if (ne_header
.ne_magic
!= IMAGE_OS2_SIGNATURE
) return ERROR_BAD_FORMAT
;
646 /* We now have a valid NE header */
648 /* check to be able to fall back to loading OS/2 programs as DOS
649 * FIXME: should this check be reversed in order to be less strict?
650 * (only fail for OS/2 ne_exetyp 0x01 here?) */
651 if ((ne_header
.ne_exetyp
!= 0x02 /* Windows */)
652 && (ne_header
.ne_exetyp
!= 0x04) /* Windows 386 */)
653 return ERROR_BAD_FORMAT
;
655 size
= sizeof(NE_MODULE
) +
657 ne_header
.ne_cseg
* sizeof(SEGTABLEENTRY
) +
659 ne_header
.ne_restab
- ne_header
.ne_rsrctab
+
660 /* resident names table */
661 ne_header
.ne_modtab
- ne_header
.ne_restab
+
662 /* module ref table */
663 ne_header
.ne_cmod
* sizeof(WORD
) +
664 /* imported names table */
665 ne_header
.ne_enttab
- ne_header
.ne_imptab
+
666 /* entry table length */
667 ne_header
.ne_cbenttab
+
668 /* entry table extra conversion space */
670 2 * (ne_header
.ne_cbenttab
- ne_header
.ne_cmovent
*6) +
671 /* loaded file info */
672 sizeof(OFSTRUCT
) - sizeof(ofs
->szPathName
) + strlen(path
) + 1;
674 hModule
= GlobalAlloc16( GMEM_FIXED
| GMEM_ZEROINIT
, size
);
675 if (!hModule
) return ERROR_BAD_FORMAT
;
677 FarSetOwner16( hModule
, hModule
);
678 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
679 memcpy( pModule
, &ne_header
, sizeof(ne_header
) );
681 /* check *programs* for default minimal stack size */
682 if ( (!(pModule
->ne_flags
& NE_FFLAGS_LIBMODULE
))
683 && (pModule
->ne_stack
< 0x1400) )
684 pModule
->ne_stack
= 0x1400;
685 pModule
->module32
= 0;
686 pModule
->self
= hModule
;
687 pModule
->self_loading_sel
= 0;
688 pData
= (BYTE
*)(pModule
+ 1);
690 /* Clear internal Wine flags in case they are set in the EXE file */
692 pModule
->ne_flags
&= ~(NE_FFLAGS_BUILTIN
| NE_FFLAGS_WIN32
);
694 /* Read the fast-load area */
696 if (ne_header
.ne_flagsothers
& NE_AFLAGS_FASTLOAD
)
698 fastload_offset
=ne_header
.ne_pretthunks
<< ne_header
.ne_align
;
699 fastload_length
=ne_header
.ne_psegrefbytes
<< ne_header
.ne_align
;
700 TRACE("Using fast-load area offset=%x len=%d\n",
701 fastload_offset
, fastload_length
);
702 if ((fastload
= HeapAlloc( GetProcessHeap(), 0, fastload_length
)) != NULL
)
704 if (!read_data( handle
, fastload_offset
, fastload
, fastload_length
))
706 HeapFree( GetProcessHeap(), 0, fastload
);
707 WARN("Error reading fast-load area!\n");
713 /* Get the segment table */
715 pModule
->ne_segtab
= pData
- (BYTE
*)pModule
;
716 buffer
= HeapAlloc( GetProcessHeap(), 0, ne_header
.ne_cseg
*
717 sizeof(struct ne_segment_table_entry_s
));
721 struct ne_segment_table_entry_s
*pSeg
;
723 if (!READ( mz_header
.e_lfanew
+ ne_header
.ne_segtab
,
724 ne_header
.ne_cseg
* sizeof(struct ne_segment_table_entry_s
),
727 HeapFree( GetProcessHeap(), 0, buffer
);
728 HeapFree( GetProcessHeap(), 0, fastload
);
729 GlobalFree16( hModule
);
730 return ERROR_BAD_FORMAT
;
732 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
733 for (i
= ne_header
.ne_cseg
; i
> 0; i
--, pSeg
++)
735 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
736 pData
+= sizeof(SEGTABLEENTRY
);
738 HeapFree( GetProcessHeap(), 0, buffer
);
742 HeapFree( GetProcessHeap(), 0, fastload
);
743 GlobalFree16( hModule
);
744 return ERROR_BAD_FORMAT
;
747 /* Get the resource table */
749 if (ne_header
.ne_rsrctab
< ne_header
.ne_restab
)
751 pModule
->ne_rsrctab
= pData
- (BYTE
*)pModule
;
752 if (!READ(mz_header
.e_lfanew
+ ne_header
.ne_rsrctab
,
753 ne_header
.ne_restab
- ne_header
.ne_rsrctab
,
755 return ERROR_BAD_FORMAT
;
756 pData
+= ne_header
.ne_restab
- ne_header
.ne_rsrctab
;
757 NE_InitResourceHandler( pModule
);
759 else pModule
->ne_rsrctab
= 0; /* No resource table */
761 /* Get the resident names table */
763 pModule
->ne_restab
= pData
- (BYTE
*)pModule
;
764 if (!READ( mz_header
.e_lfanew
+ ne_header
.ne_restab
,
765 ne_header
.ne_modtab
- ne_header
.ne_restab
,
768 HeapFree( GetProcessHeap(), 0, fastload
);
769 GlobalFree16( hModule
);
770 return ERROR_BAD_FORMAT
;
772 pData
+= ne_header
.ne_modtab
- ne_header
.ne_restab
;
774 /* Get the module references table */
776 if (ne_header
.ne_cmod
> 0)
778 pModule
->ne_modtab
= pData
- (BYTE
*)pModule
;
779 if (!READ( mz_header
.e_lfanew
+ ne_header
.ne_modtab
,
780 ne_header
.ne_cmod
* sizeof(WORD
),
783 HeapFree( GetProcessHeap(), 0, fastload
);
784 GlobalFree16( hModule
);
785 return ERROR_BAD_FORMAT
;
787 pData
+= ne_header
.ne_cmod
* sizeof(WORD
);
789 else pModule
->ne_modtab
= 0; /* No module references */
791 /* Get the imported names table */
793 pModule
->ne_imptab
= pData
- (BYTE
*)pModule
;
794 if (!READ( mz_header
.e_lfanew
+ ne_header
.ne_imptab
,
795 ne_header
.ne_enttab
- ne_header
.ne_imptab
,
798 HeapFree( GetProcessHeap(), 0, fastload
);
799 GlobalFree16( hModule
);
800 return ERROR_BAD_FORMAT
;
802 pData
+= ne_header
.ne_enttab
- ne_header
.ne_imptab
;
804 /* Load entry table, convert it to the optimized version used by Windows */
806 if ((pTempEntryTable
= HeapAlloc( GetProcessHeap(), 0, ne_header
.ne_cbenttab
)) != NULL
)
808 BYTE nr_entries
, type
, *s
;
810 TRACE("Converting entry table.\n");
811 pModule
->ne_enttab
= pData
- (BYTE
*)pModule
;
812 if (!READ( mz_header
.e_lfanew
+ ne_header
.ne_enttab
,
813 ne_header
.ne_cbenttab
, pTempEntryTable
))
815 HeapFree( GetProcessHeap(), 0, pTempEntryTable
);
816 HeapFree( GetProcessHeap(), 0, fastload
);
817 GlobalFree16( hModule
);
818 return ERROR_BAD_FORMAT
;
822 TRACE("entry table: offs %04x, len %04x, entries %d\n", ne_header
.ne_enttab
, ne_header
.ne_cbenttab
, *s
);
824 bundle
= (ET_BUNDLE
*)pData
;
825 TRACE("first bundle: %p\n", bundle
);
826 memset(bundle
, 0, sizeof(ET_BUNDLE
)); /* in case no entry table exists */
827 entry
= (ET_ENTRY
*)((BYTE
*)bundle
+6);
829 while ((nr_entries
= *s
++))
833 bundle
->last
+= nr_entries
;
840 entry
->segnum
= *s
++;
841 entry
->offs
= *(WORD
*)s
; s
+= 2;
842 /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
850 entry
->segnum
= type
;
851 entry
->offs
= *(WORD
*)s
; s
+= 2;
852 /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
858 if (bundle
->first
== bundle
->last
)
860 bundle
->first
+= nr_entries
;
861 bundle
->last
+= nr_entries
;
866 oldbundle
->next
= ((int)entry
- (int)pModule
);
867 bundle
= (ET_BUNDLE
*)entry
;
868 TRACE("new bundle: %p\n", bundle
);
869 bundle
->first
= bundle
->last
=
870 oldbundle
->last
+ nr_entries
;
872 entry
= (ET_ENTRY
*)(((BYTE
*)entry
)+sizeof(ET_BUNDLE
));
876 HeapFree( GetProcessHeap(), 0, pTempEntryTable
);
880 HeapFree( GetProcessHeap(), 0, fastload
);
881 GlobalFree16( hModule
);
882 return ERROR_BAD_FORMAT
;
885 pData
+= ne_header
.ne_cbenttab
+ sizeof(ET_BUNDLE
) +
886 2 * (ne_header
.ne_cbenttab
- ne_header
.ne_cmovent
*6);
888 if ((DWORD
)entry
> (DWORD
)pData
)
889 ERR("converted entry table bigger than reserved space !!!\nentry: %p, pData: %p. Please report !\n", entry
, pData
);
891 /* Store the filename information */
893 pModule
->fileinfo
= pData
- (BYTE
*)pModule
;
894 size
= sizeof(OFSTRUCT
) - sizeof(ofs
->szPathName
) + strlen(path
) + 1;
895 ofs
= (OFSTRUCT
*)pData
;
896 ofs
->cBytes
= size
- 1;
898 strcpy( ofs
->szPathName
, path
);
901 /* Free the fast-load area */
904 HeapFree( GetProcessHeap(), 0, fastload
);
906 /* Get the non-resident names table */
908 if (ne_header
.ne_cbnrestab
)
910 pModule
->nrname_handle
= GlobalAlloc16( 0, ne_header
.ne_cbnrestab
);
911 if (!pModule
->nrname_handle
)
913 GlobalFree16( hModule
);
914 return ERROR_BAD_FORMAT
;
916 FarSetOwner16( pModule
->nrname_handle
, hModule
);
917 buffer
= GlobalLock16( pModule
->nrname_handle
);
918 if (!read_data( handle
, ne_header
.ne_nrestab
, buffer
, ne_header
.ne_cbnrestab
))
920 GlobalFree16( pModule
->nrname_handle
);
921 GlobalFree16( hModule
);
922 return ERROR_BAD_FORMAT
;
925 else pModule
->nrname_handle
= 0;
927 /* Allocate a segment for the implicitly-loaded DLLs */
929 if (pModule
->ne_cmod
)
931 pModule
->dlls_to_init
= GlobalAlloc16( GMEM_ZEROINIT
,
932 (pModule
->ne_cmod
+1)*sizeof(HMODULE16
) );
933 if (!pModule
->dlls_to_init
)
935 if (pModule
->nrname_handle
) GlobalFree16( pModule
->nrname_handle
);
936 GlobalFree16( hModule
);
937 return ERROR_BAD_FORMAT
;
939 FarSetOwner16( pModule
->dlls_to_init
, hModule
);
941 else pModule
->dlls_to_init
= 0;
943 NE_RegisterModule( pModule
);
944 SNOOP16_RegisterDLL(pModule
,path
);
949 /***********************************************************************
952 * Load all DLLs implicitly linked to a module.
954 static BOOL
NE_LoadDLLs( NE_MODULE
*pModule
)
957 WORD
*pModRef
= (WORD
*)((char *)pModule
+ pModule
->ne_modtab
);
958 WORD
*pDLLs
= (WORD
*)GlobalLock16( pModule
->dlls_to_init
);
960 for (i
= 0; i
< pModule
->ne_cmod
; i
++, pModRef
++)
962 char buffer
[260], *p
;
963 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->ne_imptab
+ *pModRef
;
964 memcpy( buffer
, pstr
+ 1, *pstr
);
965 *(buffer
+ *pstr
) = 0; /* terminate it */
967 TRACE("Loading '%s'\n", buffer
);
968 if (!(*pModRef
= GetModuleHandle16( buffer
)))
970 /* If the DLL is not loaded yet, load it and store */
971 /* its handle in the list of DLLs to initialize. */
974 /* Append .DLL to name if no extension present */
975 if (!(p
= strrchr( buffer
, '.')) || strchr( p
, '/' ) || strchr( p
, '\\'))
976 strcat( buffer
, ".DLL" );
978 if ((hDLL
= MODULE_LoadModule16( buffer
, TRUE
, TRUE
)) < 32)
980 /* FIXME: cleanup what was done */
982 MESSAGE( "Could not load '%s' required by '%.*s', error=%d\n",
983 buffer
, *((BYTE
*)pModule
+ pModule
->ne_restab
),
984 (char *)pModule
+ pModule
->ne_restab
+ 1, hDLL
);
987 *pModRef
= GetExePtr( hDLL
);
990 else /* Increment the reference count of the DLL */
992 NE_MODULE
*pOldDLL
= NE_GetPtr( *pModRef
);
993 if (pOldDLL
) pOldDLL
->count
++;
1000 /**********************************************************************
1003 * Load first instance of NE module from file.
1005 * pModule must point to a module structure prepared by NE_LoadExeHeader.
1006 * This routine must never be called twice on a module.
1009 static HINSTANCE16
NE_DoLoadModule( NE_MODULE
*pModule
)
1011 /* Allocate the segments for this module */
1013 if (!NE_CreateAllSegments( pModule
))
1014 return ERROR_NOT_ENOUGH_MEMORY
; /* 8 */
1016 /* Load the referenced DLLs */
1018 if (!NE_LoadDLLs( pModule
))
1019 return ERROR_FILE_NOT_FOUND
; /* 2 */
1021 /* Load the segments */
1023 NE_LoadAllSegments( pModule
);
1025 /* Make sure the usage count is 1 on the first loading of */
1026 /* the module, even if it contains circular DLL references */
1030 return NE_GetInstance( pModule
);
1033 /**********************************************************************
1036 * Load first instance of NE module. (Note: caller is responsible for
1037 * ensuring the module isn't already loaded!)
1039 * If the module turns out to be an executable module, only a
1040 * handle to a module stub is returned; this needs to be initialized
1041 * by calling NE_DoLoadModule later, in the context of the newly
1044 * If lib_only is TRUE, however, the module is perforce treated
1045 * like a DLL module, even if it is an executable module.
1048 static HINSTANCE16
NE_LoadModule( LPCSTR name
, BOOL lib_only
)
1052 HINSTANCE16 hInstance
;
1058 if ((hFile
= OpenFile16( name
, &ofs
, OF_READ
|OF_SHARE_DENY_WRITE
)) == HFILE_ERROR16
)
1059 return ERROR_FILE_NOT_FOUND
;
1061 hModule
= NE_LoadExeHeader( DosFileHandleToWin32Handle(hFile
), ofs
.szPathName
);
1067 pModule
= NE_GetPtr( hModule
);
1069 drive_type
= GetDriveTypeA( ofs
.szPathName
);
1070 if (drive_type
!= DRIVE_REMOVABLE
&& drive_type
!= DRIVE_CDROM
)
1072 /* keep the file handle open if not on a removable media */
1073 DuplicateHandle( GetCurrentProcess(), DosFileHandleToWin32Handle(hFile
),
1074 GetCurrentProcess(), &pModule
->fd
, 0, FALSE
,
1075 DUPLICATE_SAME_ACCESS
);
1079 if ( !lib_only
&& !( pModule
->ne_flags
& NE_FFLAGS_LIBMODULE
) )
1082 hInstance
= NE_DoLoadModule( pModule
);
1083 if ( hInstance
< 32 )
1086 NE_FreeModule( hModule
, 0 );
1093 /***********************************************************************
1094 * NE_DoLoadBuiltinModule
1096 * Load a built-in Win16 module. Helper function for NE_LoadBuiltinModule.
1098 static HMODULE16
NE_DoLoadBuiltinModule( const BUILTIN16_DESCRIPTOR
*descr
)
1100 IMAGE_OS2_HEADER
*header
;
1104 SEGTABLEENTRY
*pSegTable
;
1107 hModule
= GLOBAL_CreateBlock( GMEM_MOVEABLE
, descr
->module_start
,
1108 descr
->module_size
, 0, WINE_LDT_FLAGS_DATA
);
1109 if (!hModule
) return ERROR_NOT_ENOUGH_MEMORY
;
1110 FarSetOwner16( hModule
, hModule
);
1112 header
= GlobalLock16( hModule
);
1113 pModule
= (NE_MODULE
*)header
;
1114 ofs
= (OFSTRUCT
*)(header
+ 1);
1115 /* move the fileinfo structure a bit further to make space for the Wine-specific fields */
1116 if (sizeof(*header
) + sizeof(*ofs
) < sizeof(*pModule
) + ofs
->cBytes
+ 1)
1118 FIXME( "module name %s too long\n", debugstr_a(ofs
->szPathName
) );
1119 return ERROR_NOT_ENOUGH_MEMORY
;
1121 memmove( pModule
+ 1, ofs
, ofs
->cBytes
+ 1 );
1124 pModule
->fileinfo
= sizeof(*pModule
);
1125 pModule
->self
= hModule
;
1126 /* NOTE: (Ab)use the rsrc32_map parameter for resource data pointer */
1127 pModule
->rsrc32_map
= (void *)descr
->rsrc
;
1129 /* Allocate the code segment */
1131 pSegTable
= NE_SEG_TABLE( pModule
);
1132 pSegTable
->hSeg
= GLOBAL_CreateBlock( GMEM_FIXED
, descr
->code_start
,
1133 pSegTable
->minsize
, hModule
,
1134 WINE_LDT_FLAGS_CODE
|WINE_LDT_FLAGS_32BIT
);
1135 if (!pSegTable
->hSeg
) return ERROR_NOT_ENOUGH_MEMORY
;
1136 patch_code_segment( descr
->code_start
);
1139 /* Allocate the data segment */
1141 minsize
= pSegTable
->minsize
? pSegTable
->minsize
: 0x10000;
1142 minsize
+= pModule
->ne_heap
;
1143 if (minsize
> 0x10000) minsize
= 0x10000;
1144 pSegTable
->hSeg
= GlobalAlloc16( GMEM_FIXED
, minsize
);
1145 if (!pSegTable
->hSeg
) return ERROR_NOT_ENOUGH_MEMORY
;
1146 FarSetOwner16( pSegTable
->hSeg
, hModule
);
1147 pModule
->dgroup_entry
= (char *)pSegTable
- (char *)pModule
;
1148 if (pSegTable
->minsize
) memcpy( GlobalLock16( pSegTable
->hSeg
),
1149 descr
->data_start
, pSegTable
->minsize
);
1150 if (pModule
->ne_heap
)
1151 LocalInit16( GlobalHandleToSel16(pSegTable
->hSeg
), pSegTable
->minsize
, minsize
);
1153 if (descr
->rsrc
) NE_InitResourceHandler(pModule
);
1155 NE_RegisterModule( pModule
);
1161 /**********************************************************************
1162 * MODULE_LoadModule16
1164 * Load a NE module in the order of the loadorder specification.
1165 * The caller is responsible that the module is not loaded already.
1168 static HINSTANCE16
MODULE_LoadModule16( LPCSTR libname
, BOOL implicit
, BOOL lib_only
)
1170 HINSTANCE16 hinst
= 2;
1173 const BUILTIN16_DESCRIPTOR
*descr
= NULL
;
1174 char dllname
[20], owner
[20], *p
;
1175 const char *basename
;
1178 /* strip path information */
1181 if (basename
[0] && basename
[1] == ':') basename
+= 2; /* strip drive specification */
1182 if ((p
= strrchr( basename
, '\\' ))) basename
= p
+ 1;
1183 if ((p
= strrchr( basename
, '/' ))) basename
= p
+ 1;
1185 if (strlen(basename
) < sizeof(dllname
)-4)
1187 strcpy( dllname
, basename
);
1188 p
= strrchr( dllname
, '.' );
1189 if (!p
) strcat( dllname
, ".dll" );
1190 for (p
= dllname
; *p
; p
++) if (*p
>= 'A' && *p
<= 'Z') *p
+= 32;
1192 if (wine_dll_get_owner( dllname
, owner
, sizeof(owner
), &owner_exists
) != -1)
1194 HMODULE mod32
= LoadLibraryA( owner
);
1197 if (!(descr
= find_dll_descr( dllname
)))
1199 FreeLibrary( mod32
);
1202 /* loading the 32-bit library can have the side effect of loading the module */
1203 /* if so, simply incr the ref count and return the module */
1204 if ((hModule
= GetModuleHandle16( libname
)))
1206 TRACE( "module %s already loaded by owner\n", libname
);
1207 pModule
= NE_GetPtr( hModule
);
1208 if (pModule
) pModule
->count
++;
1214 /* it's probably disabled by the load order config */
1215 WARN( "couldn't load owner %s for 16-bit dll %s\n", owner
, dllname
);
1216 return ERROR_FILE_NOT_FOUND
;
1223 TRACE("Trying built-in '%s'\n", libname
);
1224 hinst
= NE_DoLoadBuiltinModule( descr
);
1225 if (hinst
> 32) TRACE_(loaddll
)("Loaded module %s : builtin\n", debugstr_a(libname
));
1229 TRACE("Trying native dll '%s'\n", libname
);
1230 hinst
= NE_LoadModule(libname
, lib_only
);
1231 if (hinst
> 32) TRACE_(loaddll
)("Loaded module %s : native\n", debugstr_a(libname
));
1232 if (hinst
== ERROR_FILE_NOT_FOUND
&& owner_exists
) hinst
= 21; /* win32 module */
1235 if (hinst
> 32 && !implicit
)
1237 hModule
= GetModuleHandle16(libname
);
1240 ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get module handle. Filename too long ?\n",
1242 return ERROR_INVALID_HANDLE
;
1245 pModule
= NE_GetPtr(hModule
);
1248 ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get NE_MODULE pointer\n",
1250 return ERROR_INVALID_HANDLE
;
1253 TRACE("Loaded module '%s' at 0x%04x.\n", libname
, hinst
);
1256 * Call initialization routines for all loaded DLLs. Note that
1257 * when we load implicitly linked DLLs this will be done by InitTask().
1259 if(pModule
->ne_flags
& NE_FFLAGS_LIBMODULE
)
1261 NE_InitializeDLLs(hModule
);
1262 NE_DllProcessAttach(hModule
);
1265 return hinst
; /* The last error that occurred */
1269 /**********************************************************************
1272 * Create the thread for a 16-bit module.
1274 static HINSTANCE16
NE_CreateThread( NE_MODULE
*pModule
, WORD cmdShow
, LPCSTR cmdline
)
1279 HINSTANCE16 instance
= 0;
1281 if (!(hTask
= TASK_SpawnTask( pModule
, cmdShow
, cmdline
+ 1, *cmdline
, &hThread
)))
1284 /* Post event to start the task */
1285 PostEvent16( hTask
);
1287 /* Wait until we get the instance handle */
1290 DirectedYield16( hTask
);
1291 if (!IsTask16( hTask
)) /* thread has died */
1294 WaitForSingleObject( hThread
, INFINITE
);
1295 GetExitCodeThread( hThread
, &exit_code
);
1296 CloseHandle( hThread
);
1299 if (!(pTask
= GlobalLock16( hTask
))) break;
1300 instance
= pTask
->hInstance
;
1301 GlobalUnlock16( hTask
);
1302 } while (!instance
);
1304 CloseHandle( hThread
);
1309 /**********************************************************************
1310 * LoadModule (KERNEL.45)
1312 HINSTANCE16 WINAPI
LoadModule16( LPCSTR name
, LPVOID paramBlock
)
1314 BOOL lib_only
= !paramBlock
|| (paramBlock
== (LPVOID
)-1);
1315 LOADPARAMS16
*params
;
1323 if ( (hModule
= NE_GetModuleByFilename(name
) ) != 0 )
1325 /* Special case: second instance of an already loaded NE module */
1327 if ( !( pModule
= NE_GetPtr( hModule
) ) ) return ERROR_BAD_FORMAT
;
1328 if ( pModule
->module32
) return (HINSTANCE16
)21;
1330 /* Increment refcount */
1336 /* Main case: load first instance of NE module */
1338 if ( (hModule
= MODULE_LoadModule16( name
, FALSE
, lib_only
)) < 32 )
1341 if ( !(pModule
= NE_GetPtr( hModule
)) )
1342 return ERROR_BAD_FORMAT
;
1345 /* If library module, we just retrieve the instance handle */
1347 if ( ( pModule
->ne_flags
& NE_FFLAGS_LIBMODULE
) || lib_only
)
1348 return NE_GetInstance( pModule
);
1351 * At this point, we need to create a new process.
1353 * pModule points either to an already loaded module, whose refcount
1354 * has already been incremented (to avoid having the module vanish
1355 * in the meantime), or else to a stub module which contains only header
1358 params
= (LOADPARAMS16
*)paramBlock
;
1359 cmdShow
= ((WORD
*)MapSL(params
->showCmd
))[1];
1360 cmdline
= MapSL( params
->cmdLine
);
1361 return NE_CreateThread( pModule
, cmdShow
, cmdline
);
1365 /**********************************************************************
1368 * Startup code for a new 16-bit task.
1370 DWORD
NE_StartTask(void)
1372 TDB
*pTask
= TASK_GetCurrent();
1373 NE_MODULE
*pModule
= NE_GetPtr( pTask
->hModule
);
1374 HINSTANCE16 hInstance
, hPrevInstance
;
1375 SEGTABLEENTRY
*pSegTable
= NE_SEG_TABLE( pModule
);
1378 if ( pModule
->count
> 0 )
1380 /* Second instance of an already loaded NE module */
1381 /* Note that the refcount was already incremented by the parent */
1383 hPrevInstance
= NE_GetInstance( pModule
);
1385 if ( pModule
->ne_autodata
)
1386 if ( NE_CreateSegment( pModule
, pModule
->ne_autodata
) )
1387 NE_LoadSegment( pModule
, pModule
->ne_autodata
);
1389 hInstance
= NE_GetInstance( pModule
);
1390 TRACE("created second instance %04x[%d] of instance %04x.\n", hInstance
, pModule
->ne_autodata
, hPrevInstance
);
1395 /* Load first instance of NE module */
1397 pModule
->ne_flags
|= NE_FFLAGS_GUI
; /* FIXME: is this necessary? */
1399 hInstance
= NE_DoLoadModule( pModule
);
1403 if ( hInstance
>= 32 )
1407 /* Enter instance handles into task struct */
1409 pTask
->hInstance
= hInstance
;
1410 pTask
->hPrevInstance
= hPrevInstance
;
1412 /* Use DGROUP for 16-bit stack */
1414 if (!(sp
= OFFSETOF(pModule
->ne_sssp
)))
1415 sp
= pSegTable
[SELECTOROF(pModule
->ne_sssp
)-1].minsize
+ pModule
->ne_stack
;
1417 sp
-= sizeof(STACK16FRAME
);
1418 NtCurrentTeb()->WOW32Reserved
= (void *)MAKESEGPTR( GlobalHandleToSel16(hInstance
), sp
);
1420 /* Registers at initialization must be:
1422 * bx stack size in bytes
1423 * cx heap size in bytes
1424 * si previous app instance
1425 * di current app instance
1427 * es selector to the PSP
1428 * ds dgroup of the application
1430 * sp top of the stack
1432 memset( &context
, 0, sizeof(context
) );
1433 context
.SegCs
= GlobalHandleToSel16(pSegTable
[SELECTOROF(pModule
->ne_csip
) - 1].hSeg
);
1434 context
.SegDs
= GlobalHandleToSel16(pTask
->hInstance
);
1435 context
.SegEs
= pTask
->hPDB
;
1436 context
.SegFs
= wine_get_fs();
1437 context
.SegGs
= wine_get_gs();
1438 context
.Eip
= OFFSETOF(pModule
->ne_csip
);
1439 context
.Ebx
= pModule
->ne_stack
;
1440 context
.Ecx
= pModule
->ne_heap
;
1441 context
.Edi
= pTask
->hInstance
;
1442 context
.Esi
= pTask
->hPrevInstance
;
1444 /* Now call 16-bit entry point */
1446 TRACE("Starting main program: cs:ip=%04lx:%04lx ds=%04lx ss:sp=%04x:%04x\n",
1447 context
.SegCs
, context
.Eip
, context
.SegDs
,
1448 SELECTOROF(NtCurrentTeb()->WOW32Reserved
),
1449 OFFSETOF(NtCurrentTeb()->WOW32Reserved
) );
1451 WOWCallback16Ex( 0, WCB16_REGS
, 0, NULL
, (DWORD
*)&context
);
1452 ExitThread( LOWORD(context
.Eax
) );
1454 return hInstance
; /* error code */
1457 /***********************************************************************
1458 * LoadLibrary (KERNEL.95)
1459 * LoadLibrary16 (KERNEL32.35)
1461 HINSTANCE16 WINAPI
LoadLibrary16( LPCSTR libname
)
1463 return LoadModule16(libname
, (LPVOID
)-1 );
1467 /**********************************************************************
1470 * Call a DLL's WEP, allowing it to shut down.
1471 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
1473 static BOOL16
MODULE_CallWEP( HMODULE16 hModule
)
1476 FARPROC16 WEP
= GetProcAddress16( hModule
, "WEP" );
1477 if (!WEP
) return FALSE
;
1484 args
[0] = WEP_FREE_DLL
;
1485 WOWCallback16Ex( (DWORD
)WEP
, WCB16_PASCAL
, sizeof(args
), args
, &dwRet
);
1486 ret
= LOWORD(dwRet
);
1488 __EXCEPT(page_fault
)
1490 WARN("Page fault\n");
1499 /**********************************************************************
1502 * Implementation of FreeModule16().
1504 static BOOL16
NE_FreeModule( HMODULE16 hModule
, BOOL call_wep
)
1506 HMODULE16
*hPrevModule
;
1511 if (!(pModule
= NE_GetPtr( hModule
))) return FALSE
;
1512 hModule
= pModule
->self
;
1514 TRACE("%04x count %d\n", hModule
, pModule
->count
);
1516 if (((INT16
)(--pModule
->count
)) > 0 ) return TRUE
;
1517 else pModule
->count
= 0;
1519 if (pModule
->ne_flags
& NE_FFLAGS_BUILTIN
)
1520 return FALSE
; /* Can't free built-in module */
1522 if (call_wep
&& !(pModule
->ne_flags
& NE_FFLAGS_WIN32
))
1524 /* Free the objects owned by the DLL module */
1525 NE_CallUserSignalProc( hModule
, USIG16_DLL_UNLOAD
);
1527 if (pModule
->ne_flags
& NE_FFLAGS_LIBMODULE
)
1528 MODULE_CallWEP( hModule
);
1530 call_wep
= FALSE
; /* We are freeing a task -> no more WEPs */
1534 /* Clear magic number just in case */
1536 pModule
->ne_magic
= pModule
->self
= 0;
1537 if (pModule
->fd
) CloseHandle( pModule
->fd
);
1539 /* Remove it from the linked list */
1541 hPrevModule
= &hFirstModule
;
1542 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
1544 hPrevModule
= &(NE_GetPtr( *hPrevModule
))->next
;
1546 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
1548 /* Free the referenced modules */
1550 pModRef
= (HMODULE16
*)((char *)pModule
+ pModule
->ne_modtab
);
1551 for (i
= 0; i
< pModule
->ne_cmod
; i
++, pModRef
++)
1553 NE_FreeModule( *pModRef
, call_wep
);
1556 /* Free the module storage */
1558 GlobalFreeAll16( hModule
);
1563 /**********************************************************************
1564 * FreeModule (KERNEL.46)
1566 BOOL16 WINAPI
FreeModule16( HMODULE16 hModule
)
1568 return NE_FreeModule( hModule
, TRUE
);
1572 /***********************************************************************
1573 * FreeLibrary (KERNEL.96)
1574 * FreeLibrary16 (KERNEL32.36)
1576 void WINAPI
FreeLibrary16( HINSTANCE16 handle
)
1578 TRACE("%04x\n", handle
);
1579 FreeModule16( handle
);
1583 /***********************************************************************
1584 * GetModuleHandle16 (KERNEL32.@)
1586 HMODULE16 WINAPI
GetModuleHandle16( LPCSTR name
)
1588 HMODULE16 hModule
= hFirstModule
;
1590 BYTE len
, *name_table
;
1591 char tmpstr
[MAX_PATH
];
1594 TRACE("(%s)\n", name
);
1596 if (!HIWORD(name
)) return GetExePtr(LOWORD(name
));
1601 lstrcpynA(tmpstr
, name
, sizeof(tmpstr
));
1603 /* If 'name' matches exactly the module name of a module:
1604 * Return its handle.
1606 for (hModule
= hFirstModule
; hModule
; hModule
= pModule
->next
)
1608 pModule
= NE_GetPtr( hModule
);
1609 if (!pModule
) break;
1610 if (pModule
->ne_flags
& NE_FFLAGS_WIN32
) continue;
1612 name_table
= (BYTE
*)pModule
+ pModule
->ne_restab
;
1613 if ((*name_table
== len
) && !strncmp(name
, name_table
+1, len
))
1617 /* If uppercased 'name' matches exactly the module name of a module:
1620 for (s
= tmpstr
; *s
; s
++) *s
= RtlUpperChar(*s
);
1622 for (hModule
= hFirstModule
; hModule
; hModule
= pModule
->next
)
1624 pModule
= NE_GetPtr( hModule
);
1625 if (!pModule
) break;
1626 if (pModule
->ne_flags
& NE_FFLAGS_WIN32
) continue;
1628 name_table
= (BYTE
*)pModule
+ pModule
->ne_restab
;
1629 /* FIXME: the strncasecmp is WRONG. It should not be case insensitive,
1630 * but case sensitive! (Unfortunately Winword 6 and subdlls have
1631 * lowercased module names, but try to load uppercase DLLs, so this
1632 * 'i' compare is just a quickfix until the loader handles that
1633 * correctly. -MM 990705
1635 if ((*name_table
== len
) && !NE_strncasecmp(tmpstr
, name_table
+1, len
))
1639 /* If the base filename of 'name' matches the base filename of the module
1640 * filename of some module (case-insensitive compare):
1641 * Return its handle.
1644 /* basename: search backwards in passed name to \ / or : */
1645 s
= tmpstr
+ strlen(tmpstr
);
1648 if (s
[-1]=='/' || s
[-1]=='\\' || s
[-1]==':')
1653 /* search this in loaded filename list */
1654 for (hModule
= hFirstModule
; hModule
; hModule
= pModule
->next
)
1659 pModule
= NE_GetPtr( hModule
);
1660 if (!pModule
) break;
1661 if (!pModule
->fileinfo
) continue;
1662 if (pModule
->ne_flags
& NE_FFLAGS_WIN32
) continue;
1664 ofs
= (OFSTRUCT
*)((BYTE
*)pModule
+ pModule
->fileinfo
);
1665 loadedfn
= ((char*)ofs
->szPathName
) + strlen(ofs
->szPathName
);
1666 /* basename: search backwards in pathname to \ / or : */
1667 while (loadedfn
> (char*)ofs
->szPathName
)
1669 if (loadedfn
[-1]=='/' || loadedfn
[-1]=='\\' || loadedfn
[-1]==':')
1673 /* case insensitive compare ... */
1674 if (!NE_strcasecmp(loadedfn
, s
))
1681 /**********************************************************************
1682 * GetModuleName (KERNEL.27)
1684 BOOL16 WINAPI
GetModuleName16( HINSTANCE16 hinst
, LPSTR buf
, INT16 count
)
1689 if (!(pModule
= NE_GetPtr( hinst
))) return FALSE
;
1690 p
= (BYTE
*)pModule
+ pModule
->ne_restab
;
1691 if (count
> *p
) count
= *p
+ 1;
1694 memcpy( buf
, p
+ 1, count
- 1 );
1695 buf
[count
-1] = '\0';
1701 /**********************************************************************
1702 * GetModuleFileName (KERNEL.49)
1704 * Comment: see GetModuleFileNameA
1706 * Even if invoked by second instance of a program,
1707 * it still returns path of first one.
1709 INT16 WINAPI
GetModuleFileName16( HINSTANCE16 hModule
, LPSTR lpFileName
,
1714 /* Win95 does not query hModule if set to 0 !
1715 * Is this wrong or maybe Win3.1 only ? */
1716 if (!hModule
) hModule
= GetCurrentTask();
1718 if (!(pModule
= NE_GetPtr( hModule
))) return 0;
1719 lstrcpynA( lpFileName
, NE_MODULE_NAME(pModule
), nSize
);
1720 if (pModule
->ne_expver
>= 0x400)
1721 GetLongPathNameA(NE_MODULE_NAME(pModule
), lpFileName
, nSize
);
1722 TRACE("%04x -> '%s'\n", hModule
, lpFileName
);
1723 return strlen(lpFileName
);
1727 /**********************************************************************
1728 * GetModuleUsage (KERNEL.48)
1730 INT16 WINAPI
GetModuleUsage16( HINSTANCE16 hModule
)
1732 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
1733 return pModule
? pModule
->count
: 0;
1737 /**********************************************************************
1738 * GetExpWinVer (KERNEL.167)
1740 WORD WINAPI
GetExpWinVer16( HMODULE16 hModule
)
1742 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
1743 if ( !pModule
) return 0;
1746 * For built-in modules, fake the expected version the module should
1747 * have according to the Windows version emulated by Wine
1749 if ( !pModule
->ne_expver
)
1751 OSVERSIONINFOA versionInfo
;
1752 versionInfo
.dwOSVersionInfoSize
= sizeof(versionInfo
);
1754 if ( GetVersionExA( &versionInfo
) )
1755 pModule
->ne_expver
=
1756 (versionInfo
.dwMajorVersion
& 0xff) << 8
1757 | (versionInfo
.dwMinorVersion
& 0xff);
1760 return pModule
->ne_expver
;
1764 /***********************************************************************
1765 * WinExec (KERNEL.166)
1767 HINSTANCE16 WINAPI
WinExec16( LPCSTR lpCmdLine
, UINT16 nCmdShow
)
1769 LPCSTR p
, args
= NULL
;
1770 LPCSTR name_beg
, name_end
;
1771 LPSTR name
, cmdline
;
1774 char buffer
[MAX_PATH
];
1776 if (*lpCmdLine
== '"') /* has to be only one and only at beginning ! */
1778 name_beg
= lpCmdLine
+1;
1779 p
= strchr ( lpCmdLine
+1, '"' );
1783 args
= strchr ( p
, ' ' );
1785 else /* yes, even valid with trailing '"' missing */
1786 name_end
= lpCmdLine
+strlen(lpCmdLine
);
1790 name_beg
= lpCmdLine
;
1791 args
= strchr( lpCmdLine
, ' ' );
1792 name_end
= args
? args
: lpCmdLine
+strlen(lpCmdLine
);
1795 if ((name_beg
== lpCmdLine
) && (!args
))
1796 { /* just use the original cmdline string as file name */
1797 name
= (LPSTR
)lpCmdLine
;
1801 if (!(name
= HeapAlloc( GetProcessHeap(), 0, name_end
- name_beg
+ 1 )))
1802 return ERROR_NOT_ENOUGH_MEMORY
;
1803 memcpy( name
, name_beg
, name_end
- name_beg
);
1804 name
[name_end
- name_beg
] = '\0';
1810 arglen
= strlen(args
);
1811 cmdline
= HeapAlloc( GetProcessHeap(), 0, 2 + arglen
);
1812 cmdline
[0] = (BYTE
)arglen
;
1813 strcpy( cmdline
+ 1, args
);
1817 cmdline
= HeapAlloc( GetProcessHeap(), 0, 2 );
1818 cmdline
[0] = cmdline
[1] = 0;
1821 TRACE("name: '%s', cmdline: '%.*s'\n", name
, cmdline
[0], &cmdline
[1]);
1823 if (SearchPathA( NULL
, name
, ".exe", sizeof(buffer
), buffer
, NULL
))
1825 LOADPARAMS16 params
;
1828 showCmd
[1] = nCmdShow
;
1830 params
.hEnvironment
= 0;
1831 params
.cmdLine
= MapLS( cmdline
);
1832 params
.showCmd
= MapLS( showCmd
);
1833 params
.reserved
= 0;
1835 ret
= LoadModule16( buffer
, ¶ms
);
1836 UnMapLS( params
.cmdLine
);
1837 UnMapLS( params
.showCmd
);
1839 else ret
= GetLastError();
1841 HeapFree( GetProcessHeap(), 0, cmdline
);
1842 if (name
!= lpCmdLine
) HeapFree( GetProcessHeap(), 0, name
);
1844 if (ret
== 21 || ret
== ERROR_BAD_FORMAT
) /* 32-bit module or unknown executable*/
1847 ReleaseThunkLock( &count
);
1848 ret
= LOWORD( WinExec( lpCmdLine
, nCmdShow
) );
1849 RestoreThunkLock( count
);
1854 /***********************************************************************
1855 * GetProcAddress (KERNEL.50)
1857 FARPROC16 WINAPI
GetProcAddress16( HMODULE16 hModule
, LPCSTR name
)
1862 if (!hModule
) hModule
= GetCurrentTask();
1863 hModule
= GetExePtr( hModule
);
1865 if (HIWORD(name
) != 0)
1867 ordinal
= NE_GetOrdinal( hModule
, name
);
1868 TRACE("%04x '%s'\n", hModule
, name
);
1872 ordinal
= LOWORD(name
);
1873 TRACE("%04x %04x\n", hModule
, ordinal
);
1875 if (!ordinal
) return (FARPROC16
)0;
1877 ret
= NE_GetEntryPoint( hModule
, ordinal
);
1879 TRACE("returning %08x\n", (UINT
)ret
);
1884 /***************************************************************************
1885 * HasGPHandler (KERNEL.338)
1887 SEGPTR WINAPI
HasGPHandler16( SEGPTR address
)
1892 GPHANDLERDEF
*gpHandler
;
1894 if ( (hModule
= FarGetOwner16( SELECTOROF(address
) )) != 0
1895 && (gpOrdinal
= NE_GetOrdinal( hModule
, "__GP" )) != 0
1896 && (gpPtr
= (SEGPTR
)NE_GetEntryPointEx( hModule
, gpOrdinal
, FALSE
)) != 0
1897 && !IsBadReadPtr16( gpPtr
, sizeof(GPHANDLERDEF
) )
1898 && (gpHandler
= MapSL( gpPtr
)) != NULL
)
1900 while (gpHandler
->selector
)
1902 if ( SELECTOROF(address
) == gpHandler
->selector
1903 && OFFSETOF(address
) >= gpHandler
->rangeStart
1904 && OFFSETOF(address
) < gpHandler
->rangeEnd
)
1905 return MAKESEGPTR( gpHandler
->selector
, gpHandler
->handler
);
1914 /**********************************************************************
1915 * GetModuleHandle (KERNEL.47)
1917 * Find a module from a module name.
1919 * NOTE: The current implementation works the same way the Windows 95 one
1920 * does. Do not try to 'fix' it, fix the callers.
1921 * + It does not do ANY extension handling (except that strange .EXE bit)!
1922 * + It does not care about paths, just about basenames. (same as Windows)
1926 * the win16 module handle if found
1928 * HIWORD (undocumented, see "Undocumented Windows", chapter 5):
1929 * Always hFirstModule
1931 DWORD WINAPI
WIN16_GetModuleHandle( SEGPTR name
)
1933 if (HIWORD(name
) == 0)
1934 return MAKELONG(GetExePtr( (HINSTANCE16
)name
), hFirstModule
);
1935 return MAKELONG(GetModuleHandle16( MapSL(name
)), hFirstModule
);
1938 /**********************************************************************
1939 * NE_GetModuleByFilename
1941 static HMODULE16
NE_GetModuleByFilename( LPCSTR name
)
1945 BYTE len
, *name_table
;
1946 char tmpstr
[MAX_PATH
];
1949 lstrcpynA(tmpstr
, name
, sizeof(tmpstr
));
1951 /* If the base filename of 'name' matches the base filename of the module
1952 * filename of some module (case-insensitive compare):
1953 * Return its handle.
1956 /* basename: search backwards in passed name to \ / or : */
1957 s
= tmpstr
+ strlen(tmpstr
);
1960 if (s
[-1]=='/' || s
[-1]=='\\' || s
[-1]==':')
1965 /* search this in loaded filename list */
1966 for (hModule
= hFirstModule
; hModule
; hModule
= pModule
->next
)
1971 pModule
= NE_GetPtr( hModule
);
1972 if (!pModule
) break;
1973 if (!pModule
->fileinfo
) continue;
1974 if (pModule
->ne_flags
& NE_FFLAGS_WIN32
) continue;
1976 ofs
= (OFSTRUCT
*)((BYTE
*)pModule
+ pModule
->fileinfo
);
1977 loadedfn
= ((char*)ofs
->szPathName
) + strlen(ofs
->szPathName
);
1978 /* basename: search backwards in pathname to \ / or : */
1979 while (loadedfn
> (char*)ofs
->szPathName
)
1981 if (loadedfn
[-1]=='/' || loadedfn
[-1]=='\\' || loadedfn
[-1]==':')
1985 /* case insensitive compare ... */
1986 if (!NE_strcasecmp(loadedfn
, s
))
1989 /* If basename (without ext) matches the module name of a module:
1990 * Return its handle.
1993 if ( (p
= strrchr( s
, '.' )) != NULL
) *p
= '\0';
1996 for (hModule
= hFirstModule
; hModule
; hModule
= pModule
->next
)
1998 pModule
= NE_GetPtr( hModule
);
1999 if (!pModule
) break;
2000 if (pModule
->ne_flags
& NE_FFLAGS_WIN32
) continue;
2002 name_table
= (BYTE
*)pModule
+ pModule
->ne_restab
;
2003 if ((*name_table
== len
) && !NE_strncasecmp(s
, name_table
+1, len
))
2010 /***********************************************************************
2011 * GetProcAddress16 (KERNEL32.37)
2012 * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
2014 FARPROC16 WINAPI
WIN32_GetProcAddress16( HMODULE hModule
, LPCSTR name
)
2016 if (!hModule
) return 0;
2017 if (HIWORD(hModule
))
2019 WARN("hModule is Win32 handle (%p)\n", hModule
);
2022 return GetProcAddress16( LOWORD(hModule
), name
);
2025 /**********************************************************************
2026 * ModuleFirst (TOOLHELP.59)
2028 BOOL16 WINAPI
ModuleFirst16( MODULEENTRY
*lpme
)
2030 lpme
->wNext
= hFirstModule
;
2031 return ModuleNext16( lpme
);
2035 /**********************************************************************
2036 * ModuleNext (TOOLHELP.60)
2038 BOOL16 WINAPI
ModuleNext16( MODULEENTRY
*lpme
)
2043 if (!lpme
->wNext
) return FALSE
;
2044 if (!(pModule
= NE_GetPtr( lpme
->wNext
))) return FALSE
;
2045 name
= (char *)pModule
+ pModule
->ne_restab
;
2046 memcpy( lpme
->szModule
, name
+ 1, min(*name
, MAX_MODULE_NAME
) );
2047 lpme
->szModule
[min(*name
, MAX_MODULE_NAME
)] = '\0';
2048 lpme
->hModule
= lpme
->wNext
;
2049 lpme
->wcUsage
= pModule
->count
;
2050 lstrcpynA( lpme
->szExePath
, NE_MODULE_NAME(pModule
), sizeof(lpme
->szExePath
) );
2051 lpme
->wNext
= pModule
->next
;
2056 /**********************************************************************
2057 * ModuleFindName (TOOLHELP.61)
2059 BOOL16 WINAPI
ModuleFindName16( MODULEENTRY
*lpme
, LPCSTR name
)
2061 lpme
->wNext
= GetModuleHandle16( name
);
2062 return ModuleNext16( lpme
);
2066 /**********************************************************************
2067 * ModuleFindHandle (TOOLHELP.62)
2069 BOOL16 WINAPI
ModuleFindHandle16( MODULEENTRY
*lpme
, HMODULE16 hModule
)
2071 hModule
= GetExePtr( hModule
);
2072 lpme
->wNext
= hModule
;
2073 return ModuleNext16( lpme
);
2077 /***************************************************************************
2078 * IsRomModule (KERNEL.323)
2080 BOOL16 WINAPI
IsRomModule16( HMODULE16 unused
)
2085 /***************************************************************************
2086 * IsRomFile (KERNEL.326)
2088 BOOL16 WINAPI
IsRomFile16( HFILE16 unused
)
2093 /***********************************************************************
2094 * create_dummy_module
2096 * Create a dummy NE module for Win32 or Winelib.
2098 static HMODULE16
create_dummy_module( HMODULE module32
)
2102 SEGTABLEENTRY
*pSegment
;
2105 const char* basename
;
2108 char filename
[MAX_PATH
];
2109 IMAGE_NT_HEADERS
*nt
= RtlImageNtHeader( module32
);
2111 if (!nt
) return ERROR_BAD_FORMAT
;
2113 /* Extract base filename */
2114 len
= GetModuleFileNameA( module32
, filename
, sizeof(filename
) );
2115 if (!len
|| len
>= sizeof(filename
)) return ERROR_BAD_FORMAT
;
2116 basename
= strrchr(filename
, '\\');
2117 if (!basename
) basename
= filename
;
2119 len
= strlen(basename
);
2120 if ((s
= strchr(basename
, '.'))) len
= s
- basename
;
2122 /* Allocate module */
2123 of_size
= sizeof(OFSTRUCT
) - sizeof(ofs
->szPathName
)
2124 + strlen(filename
) + 1;
2125 size
= sizeof(NE_MODULE
) +
2126 /* loaded file info */
2127 ((of_size
+ 3) & ~3) +
2128 /* segment table: DS,CS */
2129 2 * sizeof(SEGTABLEENTRY
) +
2132 /* several empty tables */
2135 hModule
= GlobalAlloc16( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
2136 if (!hModule
) return ERROR_BAD_FORMAT
;
2138 FarSetOwner16( hModule
, hModule
);
2139 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
2141 /* Set all used entries */
2142 pModule
->ne_magic
= IMAGE_OS2_SIGNATURE
;
2145 pModule
->ne_flags
= NE_FFLAGS_WIN32
;
2146 pModule
->ne_autodata
= 0;
2147 pModule
->ne_sssp
= MAKESEGPTR( 0, 1 );
2148 pModule
->ne_csip
= MAKESEGPTR( 0, 2 );
2149 pModule
->ne_heap
= 0;
2150 pModule
->ne_stack
= 0;
2151 pModule
->ne_cseg
= 2;
2152 pModule
->ne_cmod
= 0;
2153 pModule
->ne_cbnrestab
= 0;
2154 pModule
->fileinfo
= sizeof(NE_MODULE
);
2155 pModule
->ne_exetyp
= NE_OSFLAGS_WINDOWS
;
2156 pModule
->self
= hModule
;
2157 pModule
->module32
= module32
;
2159 /* Set version and flags */
2160 pModule
->ne_expver
= ((nt
->OptionalHeader
.MajorSubsystemVersion
& 0xff) << 8 ) |
2161 (nt
->OptionalHeader
.MinorSubsystemVersion
& 0xff);
2162 if (nt
->FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
2163 pModule
->ne_flags
|= NE_FFLAGS_LIBMODULE
| NE_FFLAGS_SINGLEDATA
;
2165 /* Set loaded file information */
2166 ofs
= (OFSTRUCT
*)(pModule
+ 1);
2167 memset( ofs
, 0, of_size
);
2168 ofs
->cBytes
= of_size
< 256 ? of_size
: 255; /* FIXME */
2169 strcpy( ofs
->szPathName
, filename
);
2171 pSegment
= (SEGTABLEENTRY
*)((char*)(pModule
+ 1) + ((of_size
+ 3) & ~3));
2172 pModule
->ne_segtab
= (char *)pSegment
- (char *)pModule
;
2175 pSegment
->flags
= NE_SEGFLAGS_DATA
;
2176 pSegment
->minsize
= 0x1000;
2179 pSegment
->flags
= 0;
2183 pStr
= (char *)pSegment
;
2184 pModule
->ne_restab
= pStr
- (char *)pModule
;
2187 lstrcpynA( pStr
+1, basename
, len
+1 );
2190 /* All tables zero terminated */
2191 pModule
->ne_rsrctab
= pModule
->ne_imptab
= pModule
->ne_enttab
= (char *)pStr
- (char *)pModule
;
2193 NE_RegisterModule( pModule
);
2194 LoadLibraryA( filename
); /* increment the ref count of the 32-bit module */
2198 /***********************************************************************
2199 * PrivateLoadLibrary (KERNEL32.@)
2201 * FIXME: rough guesswork, don't know what "Private" means
2203 HINSTANCE16 WINAPI
PrivateLoadLibrary(LPCSTR libname
)
2205 return LoadLibrary16(libname
);
2208 /***********************************************************************
2209 * PrivateFreeLibrary (KERNEL32.@)
2211 * FIXME: rough guesswork, don't know what "Private" means
2213 void WINAPI
PrivateFreeLibrary(HINSTANCE16 handle
)
2215 FreeLibrary16(handle
);
2218 /***********************************************************************
2219 * LoadLibrary32 (KERNEL.452)
2220 * LoadSystemLibrary32 (KERNEL.482)
2222 HMODULE WINAPI
LoadLibrary32_16( LPCSTR libname
)
2227 ReleaseThunkLock( &count
);
2228 hModule
= LoadLibraryA( libname
);
2229 RestoreThunkLock( count
);
2233 /***************************************************************************
2234 * MapHModuleLS (KERNEL32.@)
2236 HMODULE16 WINAPI
MapHModuleLS(HMODULE hmod
)
2242 return TASK_GetCurrent()->hInstance
;
2244 return LOWORD(hmod
); /* we already have a 16 bit module handle */
2245 pModule
= (NE_MODULE
*)GlobalLock16(hFirstModule
);
2247 if (pModule
->module32
== hmod
)
2248 return pModule
->self
;
2249 pModule
= (NE_MODULE
*)GlobalLock16(pModule
->next
);
2251 if ((ret
= create_dummy_module( hmod
)) < 32)
2259 /***************************************************************************
2260 * MapHModuleSL (KERNEL32.@)
2262 HMODULE WINAPI
MapHModuleSL(HMODULE16 hmod
)
2267 TDB
*pTask
= TASK_GetCurrent();
2268 hmod
= pTask
->hModule
;
2270 pModule
= (NE_MODULE
*)GlobalLock16(hmod
);
2271 if ((pModule
->ne_magic
!= IMAGE_OS2_SIGNATURE
) || !(pModule
->ne_flags
& NE_FFLAGS_WIN32
))
2273 return pModule
->module32
;
2276 /***************************************************************************
2277 * MapHInstLS (KERNEL32.@)
2278 * MapHInstLS (KERNEL.472)
2280 void WINAPI
__regs_MapHInstLS( CONTEXT86
*context
)
2282 context
->Eax
= MapHModuleLS( (HMODULE
)context
->Eax
);
2284 #ifdef DEFINE_REGS_ENTRYPOINT
2285 DEFINE_REGS_ENTRYPOINT( MapHInstLS
, 0, 0 );
2288 /***************************************************************************
2289 * MapHInstSL (KERNEL32.@)
2290 * MapHInstSL (KERNEL.473)
2292 void WINAPI
__regs_MapHInstSL( CONTEXT86
*context
)
2294 context
->Eax
= (DWORD
)MapHModuleSL( context
->Eax
);
2296 #ifdef DEFINE_REGS_ENTRYPOINT
2297 DEFINE_REGS_ENTRYPOINT( MapHInstSL
, 0, 0 );
2300 /***************************************************************************
2301 * MapHInstLS_PN (KERNEL32.@)
2303 void WINAPI
__regs_MapHInstLS_PN( CONTEXT86
*context
)
2305 if (context
->Eax
) context
->Eax
= MapHModuleLS( (HMODULE
)context
->Eax
);
2307 #ifdef DEFINE_REGS_ENTRYPOINT
2308 DEFINE_REGS_ENTRYPOINT( MapHInstLS_PN
, 0, 0 );
2311 /***************************************************************************
2312 * MapHInstSL_PN (KERNEL32.@)
2314 void WINAPI
__regs_MapHInstSL_PN( CONTEXT86
*context
)
2316 if (context
->Eax
) context
->Eax
= (DWORD
)MapHModuleSL( context
->Eax
);
2318 #ifdef DEFINE_REGS_ENTRYPOINT
2319 DEFINE_REGS_ENTRYPOINT( MapHInstSL_PN
, 0, 0 );