Assorted spelling and case fixes.
[wine] / dlls / kernel / ne_module.c
1 /*
2  * NE modules
3  *
4  * Copyright 1995 Alexandre Julliard
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #include <ctype.h>
34
35 #include "ntstatus.h"
36 #include "windef.h"
37 #include "winbase.h"
38 #include "wine/winbase16.h"
39 #include "winerror.h"
40 #include "wownt32.h"
41 #include "module.h"
42 #include "toolhelp.h"
43 #include "file.h"
44 #include "builtin16.h"
45 #include "stackframe.h"
46 #include "excpt.h"
47 #include "kernel_private.h"
48 #include "wine/unicode.h"
49 #include "wine/exception.h"
50 #include "wine/debug.h"
51
52 WINE_DEFAULT_DEBUG_CHANNEL(module);
53 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
54
55 #include "pshpack1.h"
56 typedef struct _GPHANDLERDEF
57 {
58     WORD selector;
59     WORD rangeStart;
60     WORD rangeEnd;
61     WORD handler;
62 } GPHANDLERDEF;
63 #include "poppack.h"
64
65 /*
66  * Segment table entry
67  */
68 struct ne_segment_table_entry_s
69 {
70     WORD seg_data_offset;   /* Sector offset of segment data    */
71     WORD seg_data_length;   /* Length of segment data           */
72     WORD seg_flags;         /* Flags associated with this segment       */
73     WORD min_alloc;         /* Minimum allocation size for this */
74 };
75
76 #define hFirstModule (pThhook->hExeHead)
77
78 typedef struct
79 {
80     void       *module_start;      /* 32-bit address of the module data */
81     int         module_size;       /* Size of the module data */
82     void       *code_start;        /* 32-bit address of DLL code */
83     void       *data_start;        /* 32-bit address of DLL data */
84     const char *owner;             /* 32-bit dll that contains this dll */
85     const void *rsrc;              /* resources data */
86 } BUILTIN16_DESCRIPTOR;
87
88 /* Table of all built-in DLLs */
89
90 #define MAX_DLLS 50
91
92 static const BUILTIN16_DESCRIPTOR *builtin_dlls[MAX_DLLS];
93
94 extern void SNOOP16_RegisterDLL(NE_MODULE*,LPCSTR);
95 extern FARPROC16 SNOOP16_GetProcAddress16(HMODULE16,DWORD,FARPROC16);
96
97 static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only );
98 static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep );
99
100 static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only );
101
102 static HMODULE16 NE_GetModuleByFilename( LPCSTR name );
103
104
105 static WINE_EXCEPTION_FILTER(page_fault)
106 {
107     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
108         GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
109         return EXCEPTION_EXECUTE_HANDLER;
110     return EXCEPTION_CONTINUE_SEARCH;
111 }
112
113
114 /* patch all the flat cs references of the code segment if necessary */
115 inline static void patch_code_segment( void *code_segment )
116 {
117 #ifdef __i386__
118     CALLFROM16 *call = code_segment;
119     if (call->flatcs == wine_get_cs()) return;  /* nothing to patch */
120     while (call->pushl == 0x68)
121     {
122         call->flatcs = wine_get_cs();
123         call++;
124     }
125 #endif
126 }
127
128
129 /***********************************************************************
130  *           find_dll_descr
131  *
132  * Find a descriptor in the list
133  */
134 static const BUILTIN16_DESCRIPTOR *find_dll_descr( const char *dllname )
135 {
136     int i;
137     for (i = 0; i < MAX_DLLS; i++)
138     {
139         const BUILTIN16_DESCRIPTOR *descr = builtin_dlls[i];
140         if (descr)
141         {
142             NE_MODULE *pModule = (NE_MODULE *)descr->module_start;
143             OFSTRUCT *pOfs = (OFSTRUCT *)((LPBYTE)pModule + pModule->fileinfo);
144             BYTE *name_table = (BYTE *)pModule + pModule->name_table;
145
146             /* check the dll file name */
147             if (!FILE_strcasecmp( pOfs->szPathName, dllname )) return descr;
148             /* check the dll module name (without extension) */
149             if (!FILE_strncasecmp( dllname, name_table+1, *name_table ) &&
150                 !strcmp( dllname + *name_table, ".dll" ))
151                 return descr;
152         }
153     }
154     return NULL;
155 }
156
157
158 /***********************************************************************
159  *           __wine_register_dll_16 (KERNEL32.@)
160  *
161  * Register a built-in DLL descriptor.
162  */
163 void __wine_register_dll_16( const BUILTIN16_DESCRIPTOR *descr )
164 {
165     int i;
166
167     for (i = 0; i < MAX_DLLS; i++)
168     {
169         if (builtin_dlls[i]) continue;
170         builtin_dlls[i] = descr;
171         break;
172     }
173     assert( i < MAX_DLLS );
174 }
175
176
177 /***********************************************************************
178  *           __wine_unregister_dll_16 (KERNEL32.@)
179  *
180  * Unregister a built-in DLL descriptor.
181  */
182 void __wine_unregister_dll_16( const BUILTIN16_DESCRIPTOR *descr )
183 {
184     int i;
185
186     for (i = 0; i < MAX_DLLS; i++)
187     {
188         if (builtin_dlls[i] != descr) continue;
189         builtin_dlls[i] = NULL;
190         break;
191     }
192 }
193
194
195 /***********************************************************************
196  *           NE_GetPtr
197  */
198 NE_MODULE *NE_GetPtr( HMODULE16 hModule )
199 {
200     return (NE_MODULE *)GlobalLock16( GetExePtr(hModule) );
201 }
202
203
204 /**********************************************************************
205  *           NE_RegisterModule
206  */
207 static void NE_RegisterModule( NE_MODULE *pModule )
208 {
209     pModule->next = hFirstModule;
210     hFirstModule = pModule->self;
211 }
212
213
214 /***********************************************************************
215  *           NE_DumpModule
216  */
217 void NE_DumpModule( HMODULE16 hModule )
218 {
219     int i, ordinal;
220     SEGTABLEENTRY *pSeg;
221     BYTE *pstr;
222     WORD *pword;
223     NE_MODULE *pModule;
224     ET_BUNDLE *bundle;
225     ET_ENTRY *entry;
226
227     if (!(pModule = NE_GetPtr( hModule )))
228     {
229         MESSAGE( "**** %04x is not a module handle\n", hModule );
230         return;
231     }
232
233       /* Dump the module info */
234     DPRINTF( "---\n" );
235     DPRINTF( "Module %04x:\n", hModule );
236     DPRINTF( "count=%d flags=%04x heap=%d stack=%d\n",
237              pModule->count, pModule->flags,
238              pModule->heap_size, pModule->stack_size );
239     DPRINTF( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
240              pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
241              pModule->seg_count, pModule->modref_count );
242     DPRINTF( "os_flags=%d swap_area=%d version=%04x\n",
243              pModule->os_flags, pModule->min_swap_area,
244              pModule->expected_version );
245     if (pModule->flags & NE_FFLAGS_WIN32)
246         DPRINTF( "PE module=%p\n", pModule->module32 );
247
248       /* Dump the file info */
249     DPRINTF( "---\n" );
250     DPRINTF( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
251
252       /* Dump the segment table */
253     DPRINTF( "---\n" );
254     DPRINTF( "Segment table:\n" );
255     pSeg = NE_SEG_TABLE( pModule );
256     for (i = 0; i < pModule->seg_count; i++, pSeg++)
257         DPRINTF( "%02x: pos=%d size=%d flags=%04x minsize=%d hSeg=%04x\n",
258                  i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
259                  pSeg->minsize, pSeg->hSeg );
260
261       /* Dump the resource table */
262     DPRINTF( "---\n" );
263     DPRINTF( "Resource table:\n" );
264     if (pModule->res_table)
265     {
266         pword = (WORD *)((BYTE *)pModule + pModule->res_table);
267         DPRINTF( "Alignment: %d\n", *pword++ );
268         while (*pword)
269         {
270             NE_TYPEINFO *ptr = (NE_TYPEINFO *)pword;
271             NE_NAMEINFO *pname = (NE_NAMEINFO *)(ptr + 1);
272             DPRINTF( "id=%04x count=%d\n", ptr->type_id, ptr->count );
273             for (i = 0; i < ptr->count; i++, pname++)
274                 DPRINTF( "offset=%d len=%d id=%04x\n",
275                       pname->offset, pname->length, pname->id );
276             pword = (WORD *)pname;
277         }
278     }
279     else DPRINTF( "None\n" );
280
281       /* Dump the resident name table */
282     DPRINTF( "---\n" );
283     DPRINTF( "Resident-name table:\n" );
284     pstr = (char *)pModule + pModule->name_table;
285     while (*pstr)
286     {
287         DPRINTF( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
288                  *(WORD *)(pstr + *pstr + 1) );
289         pstr += *pstr + 1 + sizeof(WORD);
290     }
291
292       /* Dump the module reference table */
293     DPRINTF( "---\n" );
294     DPRINTF( "Module ref table:\n" );
295     if (pModule->modref_table)
296     {
297         pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
298         for (i = 0; i < pModule->modref_count; i++, pword++)
299         {
300             char name[10];
301             GetModuleName16( *pword, name, sizeof(name) );
302             DPRINTF( "%d: %04x -> '%s'\n", i, *pword, name );
303         }
304     }
305     else DPRINTF( "None\n" );
306
307       /* Dump the entry table */
308     DPRINTF( "---\n" );
309     DPRINTF( "Entry table:\n" );
310     bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);
311     do {
312         entry = (ET_ENTRY *)((BYTE *)bundle+6);
313         DPRINTF( "Bundle %d-%d: %02x\n", bundle->first, bundle->last, entry->type);
314         ordinal = bundle->first;
315         while (ordinal < bundle->last)
316         {
317             if (entry->type == 0xff)
318                 DPRINTF("%d: %02x:%04x (moveable)\n", ordinal++, entry->segnum, entry->offs);
319             else
320                 DPRINTF("%d: %02x:%04x (fixed)\n", ordinal++, entry->segnum, entry->offs);
321             entry++;
322         }
323     } while ( (bundle->next) && (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
324
325     /* Dump the non-resident names table */
326     DPRINTF( "---\n" );
327     DPRINTF( "Non-resident names table:\n" );
328     if (pModule->nrname_handle)
329     {
330         pstr = (char *)GlobalLock16( pModule->nrname_handle );
331         while (*pstr)
332         {
333             DPRINTF( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
334                    *(WORD *)(pstr + *pstr + 1) );
335             pstr += *pstr + 1 + sizeof(WORD);
336         }
337     }
338     DPRINTF( "\n" );
339 }
340
341
342 /***********************************************************************
343  *           NE_WalkModules
344  *
345  * Walk the module list and print the modules.
346  */
347 void NE_WalkModules(void)
348 {
349     HMODULE16 hModule = hFirstModule;
350     MESSAGE( "Module Flags Name\n" );
351     while (hModule)
352     {
353         NE_MODULE *pModule = NE_GetPtr( hModule );
354         if (!pModule)
355         {
356             MESSAGE( "Bad module %04x in list\n", hModule );
357             return;
358         }
359         MESSAGE( " %04x  %04x  %.*s\n", hModule, pModule->flags,
360                  *((char *)pModule + pModule->name_table),
361                  (char *)pModule + pModule->name_table + 1 );
362         hModule = pModule->next;
363     }
364 }
365
366
367 /***********************************************************************
368  *           NE_InitResourceHandler
369  *
370  * Fill in 'resloader' fields in the resource table.
371  */
372 static void NE_InitResourceHandler( NE_MODULE *pModule )
373 {
374     static FARPROC16 proc;
375
376     NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
377
378     TRACE("InitResourceHandler[%04x]\n", pModule->self );
379
380     if (!proc) proc = GetProcAddress16( GetModuleHandle16("KERNEL"), "DefResourceHandler" );
381
382     while(pTypeInfo->type_id)
383     {
384         memcpy_unaligned( &pTypeInfo->resloader, &proc, sizeof(FARPROC16) );
385         pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo + 1) + pTypeInfo->count * sizeof(NE_NAMEINFO));
386     }
387 }
388
389
390 /***********************************************************************
391  *           NE_GetOrdinal
392  *
393  * Lookup the ordinal for a given name.
394  */
395 WORD NE_GetOrdinal( HMODULE16 hModule, const char *name )
396 {
397     unsigned char buffer[256], *cpnt;
398     BYTE len;
399     NE_MODULE *pModule;
400
401     if (!(pModule = NE_GetPtr( hModule ))) return 0;
402     if (pModule->flags & NE_FFLAGS_WIN32) return 0;
403
404     TRACE("(%04x,'%s')\n", hModule, name );
405
406       /* First handle names of the form '#xxxx' */
407
408     if (name[0] == '#') return atoi( name + 1 );
409
410       /* Now copy and uppercase the string */
411
412     strcpy( buffer, name );
413     for (cpnt = buffer; *cpnt; cpnt++) *cpnt = FILE_toupper(*cpnt);
414     len = cpnt - buffer;
415
416       /* First search the resident names */
417
418     cpnt = (char *)pModule + pModule->name_table;
419
420       /* Skip the first entry (module name) */
421     cpnt += *cpnt + 1 + sizeof(WORD);
422     while (*cpnt)
423     {
424         if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
425         {
426             WORD ordinal;
427             memcpy( &ordinal, cpnt + *cpnt + 1, sizeof(ordinal) );
428             TRACE("  Found: ordinal=%d\n", ordinal );
429             return ordinal;
430         }
431         cpnt += *cpnt + 1 + sizeof(WORD);
432     }
433
434       /* Now search the non-resident names table */
435
436     if (!pModule->nrname_handle) return 0;  /* No non-resident table */
437     cpnt = (char *)GlobalLock16( pModule->nrname_handle );
438
439       /* Skip the first entry (module description string) */
440     cpnt += *cpnt + 1 + sizeof(WORD);
441     while (*cpnt)
442     {
443         if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
444         {
445             WORD ordinal;
446             memcpy( &ordinal, cpnt + *cpnt + 1, sizeof(ordinal) );
447             TRACE("  Found: ordinal=%d\n", ordinal );
448             return ordinal;
449         }
450         cpnt += *cpnt + 1 + sizeof(WORD);
451     }
452     return 0;
453 }
454
455
456 /***********************************************************************
457  *              NE_GetEntryPoint
458  */
459 FARPROC16 WINAPI NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
460 {
461     return NE_GetEntryPointEx( hModule, ordinal, TRUE );
462 }
463
464 /***********************************************************************
465  *              NE_GetEntryPointEx
466  */
467 FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop )
468 {
469     NE_MODULE *pModule;
470     WORD sel, offset, i;
471
472     ET_ENTRY *entry;
473     ET_BUNDLE *bundle;
474
475     if (!(pModule = NE_GetPtr( hModule ))) return 0;
476     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
477
478     bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
479     while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
480     {
481         if (!(bundle->next))
482             return 0;
483         bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
484     }
485
486     entry = (ET_ENTRY *)((BYTE *)bundle+6);
487     for (i=0; i < (ordinal - bundle->first - 1); i++)
488         entry++;
489
490     sel = entry->segnum;
491     memcpy( &offset, &entry->offs, sizeof(WORD) );
492
493     if (sel == 0xfe) sel = 0xffff;  /* constant entry */
494     else sel = GlobalHandleToSel16(NE_SEG_TABLE(pModule)[sel-1].hSeg);
495     if (sel==0xffff)
496         return (FARPROC16)MAKESEGPTR( sel, offset );
497     if (!snoop)
498         return (FARPROC16)MAKESEGPTR( sel, offset );
499     else
500         return (FARPROC16)SNOOP16_GetProcAddress16(hModule,ordinal,(FARPROC16)MAKESEGPTR( sel, offset ));
501 }
502
503
504 /***********************************************************************
505  *              EntryAddrProc (KERNEL.667) Wine-specific export
506  *
507  * Return the entry point for a given ordinal.
508  */
509 FARPROC16 WINAPI EntryAddrProc16( HMODULE16 hModule, WORD ordinal )
510 {
511     FARPROC16 ret = NE_GetEntryPointEx( hModule, ordinal, TRUE );
512     CURRENT_STACK16->ecx = hModule; /* FIXME: might be incorrect value */
513     return ret;
514 }
515
516 /***********************************************************************
517  *           NE_SetEntryPoint
518  *
519  * Change the value of an entry point. Use with caution!
520  * It can only change the offset value, not the selector.
521  */
522 BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
523 {
524     NE_MODULE *pModule;
525     ET_ENTRY *entry;
526     ET_BUNDLE *bundle;
527     int i;
528
529     if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
530     assert( !(pModule->flags & NE_FFLAGS_WIN32) );
531
532     bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
533     while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
534     {
535         bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
536         if (!(bundle->next)) return 0;
537     }
538
539     entry = (ET_ENTRY *)((BYTE *)bundle+6);
540     for (i=0; i < (ordinal - bundle->first - 1); i++)
541         entry++;
542
543     memcpy( &entry->offs, &offset, sizeof(WORD) );
544     return TRUE;
545 }
546
547
548 /***********************************************************************
549  *           NE_OpenFile
550  */
551 HANDLE NE_OpenFile( NE_MODULE *pModule )
552 {
553     HANDLE handle;
554     char *name = NE_MODULE_NAME( pModule );
555
556     TRACE("(%p)\n", pModule );
557
558     if (pModule->fd)
559     {
560         if (!DuplicateHandle( GetCurrentProcess(), pModule->fd,
561                               GetCurrentProcess(), &handle, 0, FALSE,
562                               DUPLICATE_SAME_ACCESS )) handle = INVALID_HANDLE_VALUE;
563     }
564     else
565     {
566         handle = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
567                               NULL, OPEN_EXISTING, 0, 0 );
568     }
569     if (handle == INVALID_HANDLE_VALUE)
570         ERR( "Can't open file '%s' for module %04x\n", name, pModule->self );
571
572     TRACE("opened '%s' -> %p\n", name, handle);
573     return handle;
574 }
575
576
577 /* wrapper for SetFilePointer and ReadFile */
578 static BOOL read_data( HANDLE handle, LONG offset, void *buffer, DWORD size )
579 {
580     DWORD result;
581
582     if (SetFilePointer( handle, offset, NULL, SEEK_SET ) == INVALID_SET_FILE_POINTER) return FALSE;
583     if (!ReadFile( handle, buffer, size, &result, NULL )) return FALSE;
584     return (result == size);
585 }
586
587 /***********************************************************************
588  *           NE_LoadExeHeader
589  */
590 static HMODULE16 NE_LoadExeHeader( HANDLE handle, LPCSTR path )
591 {
592     IMAGE_DOS_HEADER mz_header;
593     IMAGE_OS2_HEADER ne_header;
594     int size;
595     HMODULE16 hModule;
596     NE_MODULE *pModule;
597     BYTE *pData, *pTempEntryTable;
598     char *buffer, *fastload = NULL;
599     int fastload_offset = 0, fastload_length = 0;
600     ET_ENTRY *entry;
601     ET_BUNDLE *bundle, *oldbundle;
602     OFSTRUCT *ofs;
603
604   /* Read a block from either the file or the fast-load area. */
605 #define READ(offset,size,buffer) \
606        ((fastload && ((offset) >= fastload_offset) && \
607          ((offset)+(size) <= fastload_offset+fastload_length)) ? \
608         (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
609          read_data( handle, (offset), (buffer), (size)))
610
611     if (!read_data( handle, 0, &mz_header, sizeof(mz_header)) ||
612         (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
613         return (HMODULE16)11;  /* invalid exe */
614
615     if (!read_data( handle, mz_header.e_lfanew, &ne_header, sizeof(ne_header) ))
616         return (HMODULE16)11;  /* invalid exe */
617
618     if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE16)21;  /* win32 exe */
619     if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
620         MESSAGE("Sorry, this is an OS/2 linear executable (LX) file !\n");
621         return (HMODULE16)12;
622     }
623     if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE16)11;  /* invalid exe */
624
625     /* We now have a valid NE header */
626
627     size = sizeof(NE_MODULE) +
628              /* segment table */
629            ne_header.ne_cseg * sizeof(SEGTABLEENTRY) +
630              /* resource table */
631            ne_header.ne_restab - ne_header.ne_rsrctab +
632              /* resident names table */
633            ne_header.ne_modtab - ne_header.ne_restab +
634              /* module ref table */
635            ne_header.ne_cmod * sizeof(WORD) +
636              /* imported names table */
637            ne_header.ne_enttab - ne_header.ne_imptab +
638              /* entry table length */
639            ne_header.ne_cbenttab +
640              /* entry table extra conversion space */
641            sizeof(ET_BUNDLE) +
642            2 * (ne_header.ne_cbenttab - ne_header.ne_cmovent*6) +
643              /* loaded file info */
644            sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
645
646     hModule = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, size );
647     if (!hModule) return (HMODULE16)11;  /* invalid exe */
648
649     FarSetOwner16( hModule, hModule );
650     pModule = (NE_MODULE *)GlobalLock16( hModule );
651     memcpy( pModule, &ne_header, sizeof(ne_header) );
652     pModule->count = 0;
653     /* check *programs* for default minimal stack size */
654     if ( (!(pModule->flags & NE_FFLAGS_LIBMODULE))
655          && (pModule->stack_size < 0x1400) )
656         pModule->stack_size = 0x1400;
657     pModule->module32 = 0;
658     pModule->self = hModule;
659     pModule->self_loading_sel = 0;
660     pData = (BYTE *)(pModule + 1);
661
662     /* Clear internal Wine flags in case they are set in the EXE file */
663
664     pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
665
666     /* Read the fast-load area */
667
668     if (ne_header.ne_flagsothers & NE_AFLAGS_FASTLOAD)
669     {
670         fastload_offset=ne_header.ne_pretthunks << ne_header.ne_align;
671         fastload_length=ne_header.ne_psegrefbytes << ne_header.ne_align;
672         TRACE("Using fast-load area offset=%x len=%d\n",
673                         fastload_offset, fastload_length );
674         if ((fastload = HeapAlloc( GetProcessHeap(), 0, fastload_length )) != NULL)
675         {
676             if (!read_data( handle, fastload_offset, fastload, fastload_length))
677             {
678                 HeapFree( GetProcessHeap(), 0, fastload );
679                 WARN("Error reading fast-load area!\n");
680                 fastload = NULL;
681             }
682         }
683     }
684
685     /* Get the segment table */
686
687     pModule->seg_table = pData - (BYTE *)pModule;
688     buffer = HeapAlloc( GetProcessHeap(), 0, ne_header.ne_cseg *
689                                       sizeof(struct ne_segment_table_entry_s));
690     if (buffer)
691     {
692         int i;
693         struct ne_segment_table_entry_s *pSeg;
694
695         if (!READ( mz_header.e_lfanew + ne_header.ne_segtab,
696              ne_header.ne_cseg * sizeof(struct ne_segment_table_entry_s),
697              buffer ))
698         {
699             HeapFree( GetProcessHeap(), 0, buffer );
700             if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
701             GlobalFree16( hModule );
702             return (HMODULE16)11;  /* invalid exe */
703         }
704         pSeg = (struct ne_segment_table_entry_s *)buffer;
705         for (i = ne_header.ne_cseg; i > 0; i--, pSeg++)
706         {
707             memcpy( pData, pSeg, sizeof(*pSeg) );
708             pData += sizeof(SEGTABLEENTRY);
709         }
710         HeapFree( GetProcessHeap(), 0, buffer );
711     }
712     else
713     {
714         if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
715         GlobalFree16( hModule );
716         return (HMODULE16)11;  /* invalid exe */
717     }
718
719     /* Get the resource table */
720
721     if (ne_header.ne_rsrctab < ne_header.ne_restab)
722     {
723         pModule->res_table = pData - (BYTE *)pModule;
724         if (!READ(mz_header.e_lfanew + ne_header.ne_rsrctab,
725                   ne_header.ne_restab - ne_header.ne_rsrctab,
726                   pData ))
727             return (HMODULE16)11;  /* invalid exe */
728         pData += ne_header.ne_restab - ne_header.ne_rsrctab;
729         NE_InitResourceHandler( pModule );
730     }
731     else pModule->res_table = 0;  /* No resource table */
732
733     /* Get the resident names table */
734
735     pModule->name_table = pData - (BYTE *)pModule;
736     if (!READ( mz_header.e_lfanew + ne_header.ne_restab,
737                ne_header.ne_modtab - ne_header.ne_restab,
738                pData ))
739     {
740         if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
741         GlobalFree16( hModule );
742         return (HMODULE16)11;  /* invalid exe */
743     }
744     pData += ne_header.ne_modtab - ne_header.ne_restab;
745
746     /* Get the module references table */
747
748     if (ne_header.ne_cmod > 0)
749     {
750         pModule->modref_table = pData - (BYTE *)pModule;
751         if (!READ( mz_header.e_lfanew + ne_header.ne_modtab,
752                   ne_header.ne_cmod * sizeof(WORD),
753                   pData ))
754         {
755             if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
756             GlobalFree16( hModule );
757             return (HMODULE16)11;  /* invalid exe */
758         }
759         pData += ne_header.ne_cmod * sizeof(WORD);
760     }
761     else pModule->modref_table = 0;  /* No module references */
762
763     /* Get the imported names table */
764
765     pModule->import_table = pData - (BYTE *)pModule;
766     if (!READ( mz_header.e_lfanew + ne_header.ne_imptab,
767                ne_header.ne_enttab - ne_header.ne_imptab,
768                pData ))
769     {
770         if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
771         GlobalFree16( hModule );
772         return (HMODULE16)11;  /* invalid exe */
773     }
774     pData += ne_header.ne_enttab - ne_header.ne_imptab;
775
776     /* Load entry table, convert it to the optimized version used by Windows */
777
778     if ((pTempEntryTable = HeapAlloc( GetProcessHeap(), 0, ne_header.ne_cbenttab)) != NULL)
779     {
780         BYTE nr_entries, type, *s;
781
782         TRACE("Converting entry table.\n");
783         pModule->entry_table = pData - (BYTE *)pModule;
784         if (!READ( mz_header.e_lfanew + ne_header.ne_enttab,
785                    ne_header.ne_cbenttab, pTempEntryTable ))
786         {
787             HeapFree( GetProcessHeap(), 0, pTempEntryTable );
788             if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
789             GlobalFree16( hModule );
790             return (HMODULE16)11;  /* invalid exe */
791         }
792
793         s = pTempEntryTable;
794         TRACE("entry table: offs %04x, len %04x, entries %d\n", ne_header.ne_enttab, ne_header.ne_cbenttab, *s);
795
796         bundle = (ET_BUNDLE *)pData;
797         TRACE("first bundle: %p\n", bundle);
798         memset(bundle, 0, sizeof(ET_BUNDLE)); /* in case no entry table exists */
799         entry = (ET_ENTRY *)((BYTE *)bundle+6);
800
801         while ((nr_entries = *s++))
802         {
803             if ((type = *s++))
804             {
805                 bundle->last += nr_entries;
806                 if (type == 0xff)
807                 while (nr_entries--)
808                 {
809                     entry->type   = type;
810                     entry->flags  = *s++;
811                     s += 2;
812                     entry->segnum = *s++;
813                     entry->offs   = *(WORD *)s; s += 2;
814                     /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
815                     entry++;
816                 }
817                 else
818                 while (nr_entries--)
819                 {
820                     entry->type   = type;
821                     entry->flags  = *s++;
822                     entry->segnum = type;
823                     entry->offs   = *(WORD *)s; s += 2;
824                     /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
825                     entry++;
826                 }
827             }
828             else
829             {
830                 if (bundle->first == bundle->last)
831                 {
832                     bundle->first += nr_entries;
833                     bundle->last += nr_entries;
834                 }
835                 else
836                 {
837                     oldbundle = bundle;
838                     oldbundle->next = ((int)entry - (int)pModule);
839                     bundle = (ET_BUNDLE *)entry;
840                     TRACE("new bundle: %p\n", bundle);
841                     bundle->first = bundle->last =
842                         oldbundle->last + nr_entries;
843                     bundle->next = 0;
844                     (BYTE *)entry += sizeof(ET_BUNDLE);
845                 }
846             }
847         }
848         HeapFree( GetProcessHeap(), 0, pTempEntryTable );
849     }
850     else
851     {
852         if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
853         GlobalFree16( hModule );
854         return (HMODULE16)11;  /* invalid exe */
855     }
856
857     pData += ne_header.ne_cbenttab + sizeof(ET_BUNDLE) +
858         2 * (ne_header.ne_cbenttab - ne_header.ne_cmovent*6);
859
860     if ((DWORD)entry > (DWORD)pData)
861        ERR("converted entry table bigger than reserved space !!!\nentry: %p, pData: %p. Please report !\n", entry, pData);
862
863     /* Store the filename information */
864
865     pModule->fileinfo = pData - (BYTE *)pModule;
866     size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
867     ofs = (OFSTRUCT *)pData;
868     ofs->cBytes = size - 1;
869     ofs->fFixedDisk = 1;
870     strcpy( ofs->szPathName, path );
871     pData += size;
872
873     /* Free the fast-load area */
874
875 #undef READ
876     if (fastload) HeapFree( GetProcessHeap(), 0, fastload );
877
878     /* Get the non-resident names table */
879
880     if (ne_header.ne_cbnrestab)
881     {
882         pModule->nrname_handle = GlobalAlloc16( 0, ne_header.ne_cbnrestab );
883         if (!pModule->nrname_handle)
884         {
885             GlobalFree16( hModule );
886             return (HMODULE16)11;  /* invalid exe */
887         }
888         FarSetOwner16( pModule->nrname_handle, hModule );
889         buffer = GlobalLock16( pModule->nrname_handle );
890         if (!read_data( handle, ne_header.ne_nrestab, buffer, ne_header.ne_cbnrestab ))
891         {
892             GlobalFree16( pModule->nrname_handle );
893             GlobalFree16( hModule );
894             return (HMODULE16)11;  /* invalid exe */
895         }
896     }
897     else pModule->nrname_handle = 0;
898
899     /* Allocate a segment for the implicitly-loaded DLLs */
900
901     if (pModule->modref_count)
902     {
903         pModule->dlls_to_init = GlobalAlloc16( GMEM_ZEROINIT,
904                                                (pModule->modref_count+1)*sizeof(HMODULE16) );
905         if (!pModule->dlls_to_init)
906         {
907             if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
908             GlobalFree16( hModule );
909             return (HMODULE16)11;  /* invalid exe */
910         }
911         FarSetOwner16( pModule->dlls_to_init, hModule );
912     }
913     else pModule->dlls_to_init = 0;
914
915     NE_RegisterModule( pModule );
916     SNOOP16_RegisterDLL(pModule,path);
917     return hModule;
918 }
919
920
921 /***********************************************************************
922  *           NE_LoadDLLs
923  *
924  * Load all DLLs implicitly linked to a module.
925  */
926 static BOOL NE_LoadDLLs( NE_MODULE *pModule )
927 {
928     int i;
929     WORD *pModRef = (WORD *)((char *)pModule + pModule->modref_table);
930     WORD *pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
931
932     for (i = 0; i < pModule->modref_count; i++, pModRef++)
933     {
934         char buffer[260], *p;
935         BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
936         memcpy( buffer, pstr + 1, *pstr );
937         *(buffer + *pstr) = 0; /* terminate it */
938
939         TRACE("Loading '%s'\n", buffer );
940         if (!(*pModRef = GetModuleHandle16( buffer )))
941         {
942             /* If the DLL is not loaded yet, load it and store */
943             /* its handle in the list of DLLs to initialize.   */
944             HMODULE16 hDLL;
945
946             /* Append .DLL to name if no extension present */
947             if (!(p = strrchr( buffer, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
948                     strcat( buffer, ".DLL" );
949
950             if ((hDLL = MODULE_LoadModule16( buffer, TRUE, TRUE )) < 32)
951             {
952                 /* FIXME: cleanup what was done */
953
954                 MESSAGE( "Could not load '%s' required by '%.*s', error=%d\n",
955                      buffer, *((BYTE*)pModule + pModule->name_table),
956                      (char *)pModule + pModule->name_table + 1, hDLL );
957                 return FALSE;
958             }
959             *pModRef = GetExePtr( hDLL );
960             *pDLLs++ = *pModRef;
961         }
962         else  /* Increment the reference count of the DLL */
963         {
964             NE_MODULE *pOldDLL = NE_GetPtr( *pModRef );
965             if (pOldDLL) pOldDLL->count++;
966         }
967     }
968     return TRUE;
969 }
970
971
972 /**********************************************************************
973  *          NE_DoLoadModule
974  *
975  * Load first instance of NE module from file.
976  *
977  * pModule must point to a module structure prepared by NE_LoadExeHeader.
978  * This routine must never be called twice on a module.
979  *
980  */
981 static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule )
982 {
983     /* Allocate the segments for this module */
984
985     if (!NE_CreateAllSegments( pModule ))
986         return ERROR_NOT_ENOUGH_MEMORY; /* 8 */
987
988     /* Load the referenced DLLs */
989
990     if (!NE_LoadDLLs( pModule ))
991         return ERROR_FILE_NOT_FOUND; /* 2 */
992
993     /* Load the segments */
994
995     NE_LoadAllSegments( pModule );
996
997     /* Make sure the usage count is 1 on the first loading of  */
998     /* the module, even if it contains circular DLL references */
999
1000     pModule->count = 1;
1001
1002     return NE_GetInstance( pModule );
1003 }
1004
1005 /**********************************************************************
1006  *          NE_LoadModule
1007  *
1008  * Load first instance of NE module. (Note: caller is responsible for
1009  * ensuring the module isn't already loaded!)
1010  *
1011  * If the module turns out to be an executable module, only a
1012  * handle to a module stub is returned; this needs to be initialized
1013  * by calling NE_DoLoadModule later, in the context of the newly
1014  * created process.
1015  *
1016  * If lib_only is TRUE, however, the module is perforce treated
1017  * like a DLL module, even if it is an executable module.
1018  *
1019  */
1020 static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only )
1021 {
1022     NE_MODULE *pModule;
1023     HMODULE16 hModule;
1024     HINSTANCE16 hInstance;
1025     HFILE16 hFile;
1026     OFSTRUCT ofs;
1027     UINT drive_type;
1028
1029     /* Open file */
1030     if ((hFile = OpenFile16( name, &ofs, OF_READ|OF_SHARE_DENY_WRITE )) == HFILE_ERROR16)
1031         return ERROR_FILE_NOT_FOUND;
1032
1033     hModule = NE_LoadExeHeader( DosFileHandleToWin32Handle(hFile), ofs.szPathName );
1034     if (hModule < 32)
1035     {
1036         _lclose16( hFile );
1037         return hModule;
1038     }
1039     pModule = NE_GetPtr( hModule );
1040
1041     drive_type = GetDriveTypeA( ofs.szPathName );
1042     if (drive_type != DRIVE_REMOVABLE && drive_type != DRIVE_CDROM)
1043     {
1044         /* keep the file handle open if not on a removable media */
1045         DuplicateHandle( GetCurrentProcess(), DosFileHandleToWin32Handle(hFile),
1046                          GetCurrentProcess(), &pModule->fd, 0, FALSE,
1047                          DUPLICATE_SAME_ACCESS );
1048     }
1049     _lclose16( hFile );
1050
1051     if ( !lib_only && !( pModule->flags & NE_FFLAGS_LIBMODULE ) )
1052         return hModule;
1053
1054     hInstance = NE_DoLoadModule( pModule );
1055     if ( hInstance < 32 )
1056     {
1057         /* cleanup ... */
1058         NE_FreeModule( hModule, 0 );
1059     }
1060
1061     return hInstance;
1062 }
1063
1064
1065 /***********************************************************************
1066  *           NE_DoLoadBuiltinModule
1067  *
1068  * Load a built-in Win16 module. Helper function for NE_LoadBuiltinModule.
1069  */
1070 static HMODULE16 NE_DoLoadBuiltinModule( const BUILTIN16_DESCRIPTOR *descr )
1071 {
1072     NE_MODULE *pModule;
1073     int minsize;
1074     SEGTABLEENTRY *pSegTable;
1075     HMODULE16 hModule;
1076
1077     hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, descr->module_start,
1078                                   descr->module_size, 0, WINE_LDT_FLAGS_DATA );
1079     if (!hModule) return ERROR_NOT_ENOUGH_MEMORY;
1080     FarSetOwner16( hModule, hModule );
1081
1082     pModule = (NE_MODULE *)GlobalLock16( hModule );
1083     pModule->self = hModule;
1084     /* NOTE: (Ab)use the hRsrcMap parameter for resource data pointer */
1085     pModule->hRsrcMap = (void *)descr->rsrc;
1086
1087     /* Allocate the code segment */
1088
1089     pSegTable = NE_SEG_TABLE( pModule );
1090     pSegTable->hSeg = GLOBAL_CreateBlock( GMEM_FIXED, descr->code_start,
1091                                           pSegTable->minsize, hModule,
1092                                           WINE_LDT_FLAGS_CODE|WINE_LDT_FLAGS_32BIT );
1093     if (!pSegTable->hSeg) return ERROR_NOT_ENOUGH_MEMORY;
1094     patch_code_segment( descr->code_start );
1095     pSegTable++;
1096
1097     /* Allocate the data segment */
1098
1099     minsize = pSegTable->minsize ? pSegTable->minsize : 0x10000;
1100     minsize += pModule->heap_size;
1101     if (minsize > 0x10000) minsize = 0x10000;
1102     pSegTable->hSeg = GlobalAlloc16( GMEM_FIXED, minsize );
1103     if (!pSegTable->hSeg) return ERROR_NOT_ENOUGH_MEMORY;
1104     FarSetOwner16( pSegTable->hSeg, hModule );
1105     if (pSegTable->minsize) memcpy( GlobalLock16( pSegTable->hSeg ),
1106                                     descr->data_start, pSegTable->minsize);
1107     if (pModule->heap_size)
1108         LocalInit16( GlobalHandleToSel16(pSegTable->hSeg), pSegTable->minsize, minsize );
1109
1110     if (descr->rsrc) NE_InitResourceHandler(pModule);
1111
1112     NE_RegisterModule( pModule );
1113
1114     return hModule;
1115 }
1116
1117
1118 /**********************************************************************
1119  *          MODULE_LoadModule16
1120  *
1121  * Load a NE module in the order of the loadorder specification.
1122  * The caller is responsible that the module is not loaded already.
1123  *
1124  */
1125 static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only )
1126 {
1127     HINSTANCE16 hinst = 2;
1128     HMODULE16 hModule;
1129     NE_MODULE *pModule;
1130     const BUILTIN16_DESCRIPTOR *descr = NULL;
1131     char dllname[20], owner[20], *p;
1132     const char *basename;
1133
1134     /* strip path information */
1135
1136     basename = libname;
1137     if (basename[0] && basename[1] == ':') basename += 2;  /* strip drive specification */
1138     if ((p = strrchr( basename, '\\' ))) basename = p + 1;
1139     if ((p = strrchr( basename, '/' ))) basename = p + 1;
1140
1141     if (strlen(basename) < sizeof(dllname)-4)
1142     {
1143         strcpy( dllname, basename );
1144         p = strrchr( dllname, '.' );
1145         if (!p) strcat( dllname, ".dll" );
1146         for (p = dllname; *p; p++) *p = FILE_tolower(*p);
1147
1148         if (!(descr = find_dll_descr( dllname )))
1149         {
1150             int file_exists;
1151
1152             if (wine_dll_get_owner( dllname, owner, sizeof(owner), &file_exists ) == -1)
1153             {
1154                 if (file_exists) return 21;  /* it may be a Win32 module then */
1155             }
1156             else  /* found 32-bit owner, try to load it */
1157             {
1158                 HMODULE mod32 = LoadLibraryA( owner );
1159                 if (mod32)
1160                 {
1161                     if (!(descr = find_dll_descr( dllname ))) FreeLibrary( mod32 );
1162                     /* loading the 32-bit library can have the side effect of loading the module */
1163                     /* if so, simply incr the ref count and return the module */
1164                     if ((hModule = GetModuleHandle16( libname )))
1165                     {
1166                         TRACE( "module %s already loaded by owner\n", libname );
1167                         pModule = NE_GetPtr( hModule );
1168                         if (pModule) pModule->count++;
1169                         return hModule;
1170                     }
1171                 }
1172                 else
1173                 {
1174                     /* it's probably disabled by the load order config */
1175                     WARN( "couldn't load owner %s for 16-bit dll %s\n", owner, dllname );
1176                     return ERROR_FILE_NOT_FOUND;
1177                 }
1178             }
1179         }
1180     }
1181
1182     if (descr)
1183     {
1184         TRACE("Trying built-in '%s'\n", libname);
1185         hinst = NE_DoLoadBuiltinModule( descr );
1186         if (hinst > 32) TRACE_(loaddll)("Loaded module %s : builtin\n", debugstr_a(libname));
1187     }
1188     else
1189     {
1190         TRACE("Trying native dll '%s'\n", libname);
1191         hinst = NE_LoadModule(libname, lib_only);
1192         if (hinst > 32) TRACE_(loaddll)("Loaded module %s : native\n", debugstr_a(libname));
1193     }
1194
1195     if (hinst > 32 && !implicit)
1196     {
1197         hModule = GetModuleHandle16(libname);
1198         if(!hModule)
1199         {
1200             ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get module handle. Filename too long ?\n",
1201                 libname, hinst);
1202             return ERROR_INVALID_HANDLE;
1203         }
1204
1205         pModule = NE_GetPtr(hModule);
1206         if(!pModule)
1207         {
1208             ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get NE_MODULE pointer\n",
1209                 libname, hinst);
1210             return ERROR_INVALID_HANDLE;
1211         }
1212
1213         TRACE("Loaded module '%s' at 0x%04x.\n", libname, hinst);
1214
1215         /*
1216          * Call initialization routines for all loaded DLLs. Note that
1217          * when we load implicitly linked DLLs this will be done by InitTask().
1218          */
1219         if(pModule->flags & NE_FFLAGS_LIBMODULE)
1220         {
1221             NE_InitializeDLLs(hModule);
1222             NE_DllProcessAttach(hModule);
1223         }
1224     }
1225     return hinst;       /* The last error that occurred */
1226 }
1227
1228
1229 /**********************************************************************
1230  *          NE_CreateThread
1231  *
1232  * Create the thread for a 16-bit module.
1233  */
1234 static HINSTANCE16 NE_CreateThread( NE_MODULE *pModule, WORD cmdShow, LPCSTR cmdline )
1235 {
1236     HANDLE hThread;
1237     TDB *pTask;
1238     HTASK16 hTask;
1239     HINSTANCE16 instance = 0;
1240
1241     if (!(hTask = TASK_SpawnTask( pModule, cmdShow, cmdline + 1, *cmdline, &hThread )))
1242         return 0;
1243
1244     /* Post event to start the task */
1245     PostEvent16( hTask );
1246
1247     /* Wait until we get the instance handle */
1248     do
1249     {
1250         DirectedYield16( hTask );
1251         if (!IsTask16( hTask ))  /* thread has died */
1252         {
1253             DWORD exit_code;
1254             WaitForSingleObject( hThread, INFINITE );
1255             GetExitCodeThread( hThread, &exit_code );
1256             CloseHandle( hThread );
1257             return exit_code;
1258         }
1259         if (!(pTask = GlobalLock16( hTask ))) break;
1260         instance = pTask->hInstance;
1261         GlobalUnlock16( hTask );
1262     } while (!instance);
1263
1264     CloseHandle( hThread );
1265     return instance;
1266 }
1267
1268
1269 /**********************************************************************
1270  *          LoadModule      (KERNEL.45)
1271  */
1272 HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
1273 {
1274     BOOL lib_only = !paramBlock || (paramBlock == (LPVOID)-1);
1275     LOADPARAMS16 *params;
1276     HMODULE16 hModule;
1277     NE_MODULE *pModule;
1278     LPSTR cmdline;
1279     WORD cmdShow;
1280
1281     /* Load module */
1282
1283     if ( (hModule = NE_GetModuleByFilename(name) ) != 0 )
1284     {
1285         /* Special case: second instance of an already loaded NE module */
1286
1287         if ( !( pModule = NE_GetPtr( hModule ) ) ) return (HINSTANCE16)11;
1288         if ( pModule->module32 ) return (HINSTANCE16)21;
1289
1290         /* Increment refcount */
1291
1292         pModule->count++;
1293     }
1294     else
1295     {
1296         /* Main case: load first instance of NE module */
1297
1298         if ( (hModule = MODULE_LoadModule16( name, FALSE, lib_only )) < 32 )
1299             return hModule;
1300
1301         if ( !(pModule = NE_GetPtr( hModule )) )
1302             return (HINSTANCE16)11;
1303     }
1304
1305     /* If library module, we just retrieve the instance handle */
1306
1307     if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
1308         return NE_GetInstance( pModule );
1309
1310     /*
1311      *  At this point, we need to create a new process.
1312      *
1313      *  pModule points either to an already loaded module, whose refcount
1314      *  has already been incremented (to avoid having the module vanish
1315      *  in the meantime), or else to a stub module which contains only header
1316      *  information.
1317      */
1318     params = (LOADPARAMS16 *)paramBlock;
1319     cmdShow = ((WORD *)MapSL(params->showCmd))[1];
1320     cmdline = MapSL( params->cmdLine );
1321     return NE_CreateThread( pModule, cmdShow, cmdline );
1322 }
1323
1324
1325 /**********************************************************************
1326  *          NE_StartTask
1327  *
1328  * Startup code for a new 16-bit task.
1329  */
1330 DWORD NE_StartTask(void)
1331 {
1332     TDB *pTask = TASK_GetCurrent();
1333     NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
1334     HINSTANCE16 hInstance, hPrevInstance;
1335     SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
1336     WORD sp;
1337
1338     if ( pModule->count > 0 )
1339     {
1340         /* Second instance of an already loaded NE module */
1341         /* Note that the refcount was already incremented by the parent */
1342
1343         hPrevInstance = NE_GetInstance( pModule );
1344
1345         if ( pModule->dgroup )
1346             if ( NE_CreateSegment( pModule, pModule->dgroup ) )
1347                 NE_LoadSegment( pModule, pModule->dgroup );
1348
1349         hInstance = NE_GetInstance( pModule );
1350         TRACE("created second instance %04x[%d] of instance %04x.\n", hInstance, pModule->dgroup, hPrevInstance);
1351
1352     }
1353     else
1354     {
1355         /* Load first instance of NE module */
1356
1357         pModule->flags |= NE_FFLAGS_GUI;  /* FIXME: is this necessary? */
1358
1359         hInstance = NE_DoLoadModule( pModule );
1360         hPrevInstance = 0;
1361     }
1362
1363     if ( hInstance >= 32 )
1364     {
1365         CONTEXT86 context;
1366
1367         /* Enter instance handles into task struct */
1368
1369         pTask->hInstance = hInstance;
1370         pTask->hPrevInstance = hPrevInstance;
1371
1372         /* Use DGROUP for 16-bit stack */
1373
1374         if (!(sp = pModule->sp))
1375             sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
1376         sp &= ~1;
1377         sp -= sizeof(STACK16FRAME);
1378         NtCurrentTeb()->cur_stack = MAKESEGPTR( GlobalHandleToSel16(hInstance), sp );
1379
1380         /* Registers at initialization must be:
1381          * ax   zero
1382          * bx   stack size in bytes
1383          * cx   heap size in bytes
1384          * si   previous app instance
1385          * di   current app instance
1386          * bp   zero
1387          * es   selector to the PSP
1388          * ds   dgroup of the application
1389          * ss   stack selector
1390          * sp   top of the stack
1391          */
1392         memset( &context, 0, sizeof(context) );
1393         context.SegCs  = GlobalHandleToSel16(pSegTable[pModule->cs - 1].hSeg);
1394         context.SegDs  = GlobalHandleToSel16(pTask->hInstance);
1395         context.SegEs  = pTask->hPDB;
1396         context.SegFs  = wine_get_fs();
1397         context.SegGs  = wine_get_gs();
1398         context.Eip    = pModule->ip;
1399         context.Ebx    = pModule->stack_size;
1400         context.Ecx    = pModule->heap_size;
1401         context.Edi    = pTask->hInstance;
1402         context.Esi    = pTask->hPrevInstance;
1403
1404         /* Now call 16-bit entry point */
1405
1406         TRACE("Starting main program: cs:ip=%04lx:%04lx ds=%04lx ss:sp=%04x:%04x\n",
1407               context.SegCs, context.Eip, context.SegDs,
1408               SELECTOROF(NtCurrentTeb()->cur_stack),
1409               OFFSETOF(NtCurrentTeb()->cur_stack) );
1410
1411         WOWCallback16Ex( 0, WCB16_REGS, 0, NULL, (DWORD *)&context );
1412         ExitThread( LOWORD(context.Eax) );
1413     }
1414     return hInstance;  /* error code */
1415 }
1416
1417 /***********************************************************************
1418  *           LoadLibrary     (KERNEL.95)
1419  *           LoadLibrary16   (KERNEL32.35)
1420  */
1421 HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
1422 {
1423     return LoadModule16(libname, (LPVOID)-1 );
1424 }
1425
1426
1427 /**********************************************************************
1428  *          MODULE_CallWEP
1429  *
1430  * Call a DLL's WEP, allowing it to shut down.
1431  * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
1432  */
1433 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
1434 {
1435     BOOL16 ret;
1436     FARPROC16 WEP = GetProcAddress16( hModule, "WEP" );
1437     if (!WEP) return FALSE;
1438
1439     __TRY
1440     {
1441         WORD args[1];
1442         DWORD dwRet;
1443
1444         args[0] = WEP_FREE_DLL;
1445         WOWCallback16Ex( (DWORD)WEP, WCB16_PASCAL, sizeof(args), args, &dwRet );
1446         ret = LOWORD(dwRet);
1447     }
1448     __EXCEPT(page_fault)
1449     {
1450         WARN("Page fault\n");
1451         ret = 0;
1452     }
1453     __ENDTRY
1454
1455     return ret;
1456 }
1457
1458
1459 /**********************************************************************
1460  *          NE_FreeModule
1461  *
1462  * Implementation of FreeModule16().
1463  */
1464 static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep )
1465 {
1466     HMODULE16 *hPrevModule;
1467     NE_MODULE *pModule;
1468     HMODULE16 *pModRef;
1469     int i;
1470
1471     if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
1472     hModule = pModule->self;
1473
1474     TRACE("%04x count %d\n", hModule, pModule->count );
1475
1476     if (((INT16)(--pModule->count)) > 0 ) return TRUE;
1477     else pModule->count = 0;
1478
1479     if (pModule->flags & NE_FFLAGS_BUILTIN)
1480         return FALSE;  /* Can't free built-in module */
1481
1482     if (call_wep && !(pModule->flags & NE_FFLAGS_WIN32))
1483     {
1484         /* Free the objects owned by the DLL module */
1485         NE_CallUserSignalProc( hModule, USIG16_DLL_UNLOAD );
1486
1487         if (pModule->flags & NE_FFLAGS_LIBMODULE)
1488             MODULE_CallWEP( hModule );
1489         else
1490             call_wep = FALSE;  /* We are freeing a task -> no more WEPs */
1491     }
1492
1493
1494     /* Clear magic number just in case */
1495
1496     pModule->magic = pModule->self = 0;
1497     if (pModule->fd) CloseHandle( pModule->fd );
1498
1499       /* Remove it from the linked list */
1500
1501     hPrevModule = &hFirstModule;
1502     while (*hPrevModule && (*hPrevModule != hModule))
1503     {
1504         hPrevModule = &(NE_GetPtr( *hPrevModule ))->next;
1505     }
1506     if (*hPrevModule) *hPrevModule = pModule->next;
1507
1508     /* Free the referenced modules */
1509
1510     pModRef = (HMODULE16*)((char *)pModule + pModule->modref_table);
1511     for (i = 0; i < pModule->modref_count; i++, pModRef++)
1512     {
1513         NE_FreeModule( *pModRef, call_wep );
1514     }
1515
1516     /* Free the module storage */
1517
1518     GlobalFreeAll16( hModule );
1519     return TRUE;
1520 }
1521
1522
1523 /**********************************************************************
1524  *          FreeModule    (KERNEL.46)
1525  */
1526 BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
1527 {
1528     return NE_FreeModule( hModule, TRUE );
1529 }
1530
1531
1532 /***********************************************************************
1533  *           FreeLibrary     (KERNEL.96)
1534  *           FreeLibrary16   (KERNEL32.36)
1535  */
1536 void WINAPI FreeLibrary16( HINSTANCE16 handle )
1537 {
1538     TRACE("%04x\n", handle );
1539     FreeModule16( handle );
1540 }
1541
1542
1543 /***********************************************************************
1544  *          GetModuleHandle16 (KERNEL32.@)
1545  */
1546 HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
1547 {
1548     HMODULE16   hModule = hFirstModule;
1549     LPSTR       s;
1550     BYTE        len, *name_table;
1551     char        tmpstr[MAX_PATH];
1552     NE_MODULE *pModule;
1553
1554     TRACE("(%s)\n", name);
1555
1556     if (!HIWORD(name)) return GetExePtr(LOWORD(name));
1557
1558     len = strlen(name);
1559     if (!len) return 0;
1560
1561     lstrcpynA(tmpstr, name, sizeof(tmpstr));
1562
1563     /* If 'name' matches exactly the module name of a module:
1564      * Return its handle.
1565      */
1566     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1567     {
1568         pModule = NE_GetPtr( hModule );
1569         if (!pModule) break;
1570         if (pModule->flags & NE_FFLAGS_WIN32) continue;
1571
1572         name_table = (BYTE *)pModule + pModule->name_table;
1573         if ((*name_table == len) && !strncmp(name, name_table+1, len))
1574             return hModule;
1575     }
1576
1577     /* If uppercased 'name' matches exactly the module name of a module:
1578      * Return its handle
1579      */
1580     for (s = tmpstr; *s; s++) *s = FILE_toupper(*s);
1581
1582     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1583     {
1584         pModule = NE_GetPtr( hModule );
1585         if (!pModule) break;
1586         if (pModule->flags & NE_FFLAGS_WIN32) continue;
1587
1588         name_table = (BYTE *)pModule + pModule->name_table;
1589         /* FIXME: the strncasecmp is WRONG. It should not be case insensitive,
1590          * but case sensitive! (Unfortunately Winword 6 and subdlls have
1591          * lowercased module names, but try to load uppercase DLLs, so this
1592          * 'i' compare is just a quickfix until the loader handles that
1593          * correctly. -MM 990705
1594          */
1595         if ((*name_table == len) && !FILE_strncasecmp(tmpstr, name_table+1, len))
1596             return hModule;
1597     }
1598
1599     /* If the base filename of 'name' matches the base filename of the module
1600      * filename of some module (case-insensitive compare):
1601      * Return its handle.
1602      */
1603
1604     /* basename: search backwards in passed name to \ / or : */
1605     s = tmpstr + strlen(tmpstr);
1606     while (s > tmpstr)
1607     {
1608         if (s[-1]=='/' || s[-1]=='\\' || s[-1]==':')
1609                 break;
1610         s--;
1611     }
1612
1613     /* search this in loaded filename list */
1614     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1615     {
1616         char            *loadedfn;
1617         OFSTRUCT        *ofs;
1618
1619         pModule = NE_GetPtr( hModule );
1620         if (!pModule) break;
1621         if (!pModule->fileinfo) continue;
1622         if (pModule->flags & NE_FFLAGS_WIN32) continue;
1623
1624         ofs = (OFSTRUCT*)((BYTE *)pModule + pModule->fileinfo);
1625         loadedfn = ((char*)ofs->szPathName) + strlen(ofs->szPathName);
1626         /* basename: search backwards in pathname to \ / or : */
1627         while (loadedfn > (char*)ofs->szPathName)
1628         {
1629             if (loadedfn[-1]=='/' || loadedfn[-1]=='\\' || loadedfn[-1]==':')
1630                     break;
1631             loadedfn--;
1632         }
1633         /* case insensitive compare ... */
1634         if (!FILE_strcasecmp(loadedfn, s))
1635             return hModule;
1636     }
1637     return 0;
1638 }
1639
1640
1641 /**********************************************************************
1642  *          GetModuleName    (KERNEL.27)
1643  */
1644 BOOL16 WINAPI GetModuleName16( HINSTANCE16 hinst, LPSTR buf, INT16 count )
1645 {
1646     NE_MODULE *pModule;
1647     BYTE *p;
1648
1649     if (!(pModule = NE_GetPtr( hinst ))) return FALSE;
1650     p = (BYTE *)pModule + pModule->name_table;
1651     if (count > *p) count = *p + 1;
1652     if (count > 0)
1653     {
1654         memcpy( buf, p + 1, count - 1 );
1655         buf[count-1] = '\0';
1656     }
1657     return TRUE;
1658 }
1659
1660
1661 /**********************************************************************
1662  *          GetModuleFileName      (KERNEL.49)
1663  *
1664  * Comment: see GetModuleFileNameA
1665  *
1666  * Even if invoked by second instance of a program,
1667  * it still returns path of first one.
1668  */
1669 INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
1670                                   INT16 nSize )
1671 {
1672     NE_MODULE *pModule;
1673
1674     /* Win95 does not query hModule if set to 0 !
1675      * Is this wrong or maybe Win3.1 only ? */
1676     if (!hModule) hModule = GetCurrentTask();
1677
1678     if (!(pModule = NE_GetPtr( hModule ))) return 0;
1679     lstrcpynA( lpFileName, NE_MODULE_NAME(pModule), nSize );
1680     if (pModule->expected_version >= 0x400)
1681         GetLongPathNameA(NE_MODULE_NAME(pModule), lpFileName, nSize);
1682     TRACE("%04x -> '%s'\n", hModule, lpFileName );
1683     return strlen(lpFileName);
1684 }
1685
1686
1687 /**********************************************************************
1688  *          GetModuleUsage    (KERNEL.48)
1689  */
1690 INT16 WINAPI GetModuleUsage16( HINSTANCE16 hModule )
1691 {
1692     NE_MODULE *pModule = NE_GetPtr( hModule );
1693     return pModule ? pModule->count : 0;
1694 }
1695
1696
1697 /**********************************************************************
1698  *          GetExpWinVer    (KERNEL.167)
1699  */
1700 WORD WINAPI GetExpWinVer16( HMODULE16 hModule )
1701 {
1702     NE_MODULE *pModule = NE_GetPtr( hModule );
1703     if ( !pModule ) return 0;
1704
1705     /*
1706      * For built-in modules, fake the expected version the module should
1707      * have according to the Windows version emulated by Wine
1708      */
1709     if ( !pModule->expected_version )
1710     {
1711         OSVERSIONINFOA versionInfo;
1712         versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
1713
1714         if ( GetVersionExA( &versionInfo ) )
1715             pModule->expected_version =
1716                      (versionInfo.dwMajorVersion & 0xff) << 8
1717                    | (versionInfo.dwMinorVersion & 0xff);
1718     }
1719
1720     return pModule->expected_version;
1721 }
1722
1723
1724 /***********************************************************************
1725  *           WinExec     (KERNEL.166)
1726  */
1727 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
1728 {
1729     LPCSTR p, args = NULL;
1730     LPCSTR name_beg, name_end;
1731     LPSTR name, cmdline;
1732     int arglen;
1733     HINSTANCE16 ret;
1734     char buffer[MAX_PATH];
1735
1736     if (*lpCmdLine == '"') /* has to be only one and only at beginning ! */
1737     {
1738         name_beg = lpCmdLine+1;
1739         p = strchr ( lpCmdLine+1, '"' );
1740         if (p)
1741         {
1742             name_end = p;
1743             args = strchr ( p, ' ' );
1744         }
1745         else /* yes, even valid with trailing '"' missing */
1746             name_end = lpCmdLine+strlen(lpCmdLine);
1747     }
1748     else
1749     {
1750         name_beg = lpCmdLine;
1751         args = strchr( lpCmdLine, ' ' );
1752         name_end = args ? args : lpCmdLine+strlen(lpCmdLine);
1753     }
1754
1755     if ((name_beg == lpCmdLine) && (!args))
1756     { /* just use the original cmdline string as file name */
1757         name = (LPSTR)lpCmdLine;
1758     }
1759     else
1760     {
1761         if (!(name = HeapAlloc( GetProcessHeap(), 0, name_end - name_beg + 1 )))
1762             return ERROR_NOT_ENOUGH_MEMORY;
1763         memcpy( name, name_beg, name_end - name_beg );
1764         name[name_end - name_beg] = '\0';
1765     }
1766
1767     if (args)
1768     {
1769         args++;
1770         arglen = strlen(args);
1771         cmdline = HeapAlloc( GetProcessHeap(), 0, 2 + arglen );
1772         cmdline[0] = (BYTE)arglen;
1773         strcpy( cmdline + 1, args );
1774     }
1775     else
1776     {
1777         cmdline = HeapAlloc( GetProcessHeap(), 0, 2 );
1778         cmdline[0] = cmdline[1] = 0;
1779     }
1780
1781     TRACE("name: '%s', cmdline: '%.*s'\n", name, cmdline[0], &cmdline[1]);
1782
1783     if (SearchPathA( NULL, name, ".exe", sizeof(buffer), buffer, NULL ))
1784     {
1785         LOADPARAMS16 params;
1786         WORD showCmd[2];
1787         showCmd[0] = 2;
1788         showCmd[1] = nCmdShow;
1789
1790         params.hEnvironment = 0;
1791         params.cmdLine = MapLS( cmdline );
1792         params.showCmd = MapLS( showCmd );
1793         params.reserved = 0;
1794
1795         ret = LoadModule16( buffer, &params );
1796         UnMapLS( params.cmdLine );
1797         UnMapLS( params.showCmd );
1798     }
1799     else ret = GetLastError();
1800
1801     HeapFree( GetProcessHeap(), 0, cmdline );
1802     if (name != lpCmdLine) HeapFree( GetProcessHeap(), 0, name );
1803
1804     if (ret == 21)  /* 32-bit module */
1805     {
1806         DWORD count;
1807         ReleaseThunkLock( &count );
1808         ret = LOWORD( WinExec( lpCmdLine, nCmdShow ) );
1809         RestoreThunkLock( count );
1810     }
1811     return ret;
1812 }
1813
1814 /***********************************************************************
1815  *           GetProcAddress   (KERNEL.50)
1816  */
1817 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, LPCSTR name )
1818 {
1819     WORD ordinal;
1820     FARPROC16 ret;
1821
1822     if (!hModule) hModule = GetCurrentTask();
1823     hModule = GetExePtr( hModule );
1824
1825     if (HIWORD(name) != 0)
1826     {
1827         ordinal = NE_GetOrdinal( hModule, name );
1828         TRACE("%04x '%s'\n", hModule, name );
1829     }
1830     else
1831     {
1832         ordinal = LOWORD(name);
1833         TRACE("%04x %04x\n", hModule, ordinal );
1834     }
1835     if (!ordinal) return (FARPROC16)0;
1836
1837     ret = NE_GetEntryPoint( hModule, ordinal );
1838
1839     TRACE("returning %08x\n", (UINT)ret );
1840     return ret;
1841 }
1842
1843
1844 /***************************************************************************
1845  *              HasGPHandler                    (KERNEL.338)
1846  */
1847 SEGPTR WINAPI HasGPHandler16( SEGPTR address )
1848 {
1849     HMODULE16 hModule;
1850     int gpOrdinal;
1851     SEGPTR gpPtr;
1852     GPHANDLERDEF *gpHandler;
1853
1854     if (    (hModule = FarGetOwner16( SELECTOROF(address) )) != 0
1855          && (gpOrdinal = NE_GetOrdinal( hModule, "__GP" )) != 0
1856          && (gpPtr = (SEGPTR)NE_GetEntryPointEx( hModule, gpOrdinal, FALSE )) != 0
1857          && !IsBadReadPtr16( gpPtr, sizeof(GPHANDLERDEF) )
1858          && (gpHandler = MapSL( gpPtr )) != NULL )
1859     {
1860         while (gpHandler->selector)
1861         {
1862             if (    SELECTOROF(address) == gpHandler->selector
1863                  && OFFSETOF(address)   >= gpHandler->rangeStart
1864                  && OFFSETOF(address)   <  gpHandler->rangeEnd  )
1865                 return MAKESEGPTR( gpHandler->selector, gpHandler->handler );
1866             gpHandler++;
1867         }
1868     }
1869
1870     return 0;
1871 }
1872
1873
1874 /**********************************************************************
1875  *          GetModuleHandle    (KERNEL.47)
1876  *
1877  * Find a module from a module name.
1878  *
1879  * NOTE: The current implementation works the same way the Windows 95 one
1880  *       does. Do not try to 'fix' it, fix the callers.
1881  *       + It does not do ANY extension handling (except that strange .EXE bit)!
1882  *       + It does not care about paths, just about basenames. (same as Windows)
1883  *
1884  * RETURNS
1885  *   LOWORD:
1886  *      the win16 module handle if found
1887  *      0 if not
1888  *   HIWORD (undocumented, see "Undocumented Windows", chapter 5):
1889  *      Always hFirstModule
1890  */
1891 DWORD WINAPI WIN16_GetModuleHandle( SEGPTR name )
1892 {
1893     if (HIWORD(name) == 0)
1894         return MAKELONG(GetExePtr( (HINSTANCE16)name), hFirstModule );
1895     return MAKELONG(GetModuleHandle16( MapSL(name)), hFirstModule );
1896 }
1897
1898 /**********************************************************************
1899  *          NE_GetModuleByFilename
1900  */
1901 static HMODULE16 NE_GetModuleByFilename( LPCSTR name )
1902 {
1903     HMODULE16   hModule;
1904     LPSTR       s, p;
1905     BYTE        len, *name_table;
1906     char        tmpstr[MAX_PATH];
1907     NE_MODULE *pModule;
1908
1909     lstrcpynA(tmpstr, name, sizeof(tmpstr));
1910
1911     /* If the base filename of 'name' matches the base filename of the module
1912      * filename of some module (case-insensitive compare):
1913      * Return its handle.
1914      */
1915
1916     /* basename: search backwards in passed name to \ / or : */
1917     s = tmpstr + strlen(tmpstr);
1918     while (s > tmpstr)
1919     {
1920         if (s[-1]=='/' || s[-1]=='\\' || s[-1]==':')
1921                 break;
1922         s--;
1923     }
1924
1925     /* search this in loaded filename list */
1926     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1927     {
1928         char            *loadedfn;
1929         OFSTRUCT        *ofs;
1930
1931         pModule = NE_GetPtr( hModule );
1932         if (!pModule) break;
1933         if (!pModule->fileinfo) continue;
1934         if (pModule->flags & NE_FFLAGS_WIN32) continue;
1935
1936         ofs = (OFSTRUCT*)((BYTE *)pModule + pModule->fileinfo);
1937         loadedfn = ((char*)ofs->szPathName) + strlen(ofs->szPathName);
1938         /* basename: search backwards in pathname to \ / or : */
1939         while (loadedfn > (char*)ofs->szPathName)
1940         {
1941             if (loadedfn[-1]=='/' || loadedfn[-1]=='\\' || loadedfn[-1]==':')
1942                     break;
1943             loadedfn--;
1944         }
1945         /* case insensitive compare ... */
1946         if (!FILE_strcasecmp(loadedfn, s))
1947             return hModule;
1948     }
1949     /* If basename (without ext) matches the module name of a module:
1950      * Return its handle.
1951      */
1952
1953     if ( (p = strrchr( s, '.' )) != NULL ) *p = '\0';
1954     len = strlen(s);
1955
1956     for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1957     {
1958         pModule = NE_GetPtr( hModule );
1959         if (!pModule) break;
1960         if (pModule->flags & NE_FFLAGS_WIN32) continue;
1961
1962         name_table = (BYTE *)pModule + pModule->name_table;
1963         if ((*name_table == len) && !FILE_strncasecmp(s, name_table+1, len))
1964             return hModule;
1965     }
1966
1967     return 0;
1968 }
1969
1970 /***********************************************************************
1971  *           GetProcAddress16   (KERNEL32.37)
1972  * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1973  */
1974 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hModule, LPCSTR name )
1975 {
1976     if (!hModule) return 0;
1977     if (HIWORD(hModule))
1978     {
1979         WARN("hModule is Win32 handle (%p)\n", hModule );
1980         return 0;
1981     }
1982     return GetProcAddress16( LOWORD(hModule), name );
1983 }
1984
1985 /**********************************************************************
1986  *          ModuleFirst    (TOOLHELP.59)
1987  */
1988 BOOL16 WINAPI ModuleFirst16( MODULEENTRY *lpme )
1989 {
1990     lpme->wNext = hFirstModule;
1991     return ModuleNext16( lpme );
1992 }
1993
1994
1995 /**********************************************************************
1996  *          ModuleNext    (TOOLHELP.60)
1997  */
1998 BOOL16 WINAPI ModuleNext16( MODULEENTRY *lpme )
1999 {
2000     NE_MODULE *pModule;
2001     char *name;
2002
2003     if (!lpme->wNext) return FALSE;
2004     if (!(pModule = NE_GetPtr( lpme->wNext ))) return FALSE;
2005     name = (char *)pModule + pModule->name_table;
2006     memcpy( lpme->szModule, name + 1, min(*name, MAX_MODULE_NAME) );
2007     lpme->szModule[min(*name, MAX_MODULE_NAME)] = '\0';
2008     lpme->hModule = lpme->wNext;
2009     lpme->wcUsage = pModule->count;
2010     lstrcpynA( lpme->szExePath, NE_MODULE_NAME(pModule), sizeof(lpme->szExePath) );
2011     lpme->wNext = pModule->next;
2012     return TRUE;
2013 }
2014
2015
2016 /**********************************************************************
2017  *          ModuleFindName    (TOOLHELP.61)
2018  */
2019 BOOL16 WINAPI ModuleFindName16( MODULEENTRY *lpme, LPCSTR name )
2020 {
2021     lpme->wNext = GetModuleHandle16( name );
2022     return ModuleNext16( lpme );
2023 }
2024
2025
2026 /**********************************************************************
2027  *          ModuleFindHandle    (TOOLHELP.62)
2028  */
2029 BOOL16 WINAPI ModuleFindHandle16( MODULEENTRY *lpme, HMODULE16 hModule )
2030 {
2031     hModule = GetExePtr( hModule );
2032     lpme->wNext = hModule;
2033     return ModuleNext16( lpme );
2034 }
2035
2036
2037 /***************************************************************************
2038  *          IsRomModule    (KERNEL.323)
2039  */
2040 BOOL16 WINAPI IsRomModule16( HMODULE16 unused )
2041 {
2042     return FALSE;
2043 }
2044
2045 /***************************************************************************
2046  *          IsRomFile    (KERNEL.326)
2047  */
2048 BOOL16 WINAPI IsRomFile16( HFILE16 unused )
2049 {
2050     return FALSE;
2051 }
2052
2053 /***********************************************************************
2054  *           create_dummy_module
2055  *
2056  * Create a dummy NE module for Win32 or Winelib.
2057  */
2058 static HMODULE16 create_dummy_module( HMODULE module32 )
2059 {
2060     HMODULE16 hModule;
2061     NE_MODULE *pModule;
2062     SEGTABLEENTRY *pSegment;
2063     char *pStr,*s;
2064     unsigned int len;
2065     const char* basename;
2066     OFSTRUCT *ofs;
2067     int of_size, size;
2068     char filename[MAX_PATH];
2069     IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module32 );
2070
2071     if (!nt) return (HMODULE16)11;  /* invalid exe */
2072
2073     /* Extract base filename */
2074     GetModuleFileNameA( module32, filename, sizeof(filename) );
2075     basename = strrchr(filename, '\\');
2076     if (!basename) basename = filename;
2077     else basename++;
2078     len = strlen(basename);
2079     if ((s = strchr(basename, '.'))) len = s - basename;
2080
2081     /* Allocate module */
2082     of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
2083                     + strlen(filename) + 1;
2084     size = sizeof(NE_MODULE) +
2085                  /* loaded file info */
2086                  ((of_size + 3) & ~3) +
2087                  /* segment table: DS,CS */
2088                  2 * sizeof(SEGTABLEENTRY) +
2089                  /* name table */
2090                  len + 2 +
2091                  /* several empty tables */
2092                  8;
2093
2094     hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
2095     if (!hModule) return (HMODULE16)11;  /* invalid exe */
2096
2097     FarSetOwner16( hModule, hModule );
2098     pModule = (NE_MODULE *)GlobalLock16( hModule );
2099
2100     /* Set all used entries */
2101     pModule->magic            = IMAGE_OS2_SIGNATURE;
2102     pModule->count            = 1;
2103     pModule->next             = 0;
2104     pModule->flags            = NE_FFLAGS_WIN32;
2105     pModule->dgroup           = 0;
2106     pModule->ss               = 1;
2107     pModule->cs               = 2;
2108     pModule->heap_size        = 0;
2109     pModule->stack_size       = 0;
2110     pModule->seg_count        = 2;
2111     pModule->modref_count     = 0;
2112     pModule->nrname_size      = 0;
2113     pModule->fileinfo         = sizeof(NE_MODULE);
2114     pModule->os_flags         = NE_OSFLAGS_WINDOWS;
2115     pModule->self             = hModule;
2116     pModule->module32         = module32;
2117
2118     /* Set version and flags */
2119     pModule->expected_version = ((nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 ) |
2120                                 (nt->OptionalHeader.MinorSubsystemVersion & 0xff);
2121     if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)
2122         pModule->flags |= NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA;
2123
2124     /* Set loaded file information */
2125     ofs = (OFSTRUCT *)(pModule + 1);
2126     memset( ofs, 0, of_size );
2127     ofs->cBytes = of_size < 256 ? of_size : 255;   /* FIXME */
2128     strcpy( ofs->szPathName, filename );
2129
2130     pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + ((of_size + 3) & ~3));
2131     pModule->seg_table = (int)pSegment - (int)pModule;
2132     /* Data segment */
2133     pSegment->size    = 0;
2134     pSegment->flags   = NE_SEGFLAGS_DATA;
2135     pSegment->minsize = 0x1000;
2136     pSegment++;
2137     /* Code segment */
2138     pSegment->flags   = 0;
2139     pSegment++;
2140
2141     /* Module name */
2142     pStr = (char *)pSegment;
2143     pModule->name_table = (int)pStr - (int)pModule;
2144     assert(len<256);
2145     *pStr = len;
2146     lstrcpynA( pStr+1, basename, len+1 );
2147     pStr += len+2;
2148
2149     /* All tables zero terminated */
2150     pModule->res_table = pModule->import_table = pModule->entry_table = (int)pStr - (int)pModule;
2151
2152     NE_RegisterModule( pModule );
2153     LoadLibraryA( filename );  /* increment the ref count of the 32-bit module */
2154     return hModule;
2155 }
2156
2157 /***********************************************************************
2158  *           PrivateLoadLibrary       (KERNEL32.@)
2159  *
2160  * FIXME: rough guesswork, don't know what "Private" means
2161  */
2162 HINSTANCE16 WINAPI PrivateLoadLibrary(LPCSTR libname)
2163 {
2164     return LoadLibrary16(libname);
2165 }
2166
2167 /***********************************************************************
2168  *           PrivateFreeLibrary       (KERNEL32.@)
2169  *
2170  * FIXME: rough guesswork, don't know what "Private" means
2171  */
2172 void WINAPI PrivateFreeLibrary(HINSTANCE16 handle)
2173 {
2174     FreeLibrary16(handle);
2175 }
2176
2177 /***********************************************************************
2178  *           LoadLibrary32        (KERNEL.452)
2179  *           LoadSystemLibrary32  (KERNEL.482)
2180  */
2181 HMODULE WINAPI LoadLibrary32_16( LPCSTR libname )
2182 {
2183     HMODULE hModule;
2184     DWORD count;
2185
2186     ReleaseThunkLock( &count );
2187     hModule = LoadLibraryA( libname );
2188     RestoreThunkLock( count );
2189     return hModule;
2190 }
2191
2192 /***************************************************************************
2193  *              MapHModuleLS                    (KERNEL32.@)
2194  */
2195 HMODULE16 WINAPI MapHModuleLS(HMODULE hmod)
2196 {
2197     HMODULE16 ret;
2198     NE_MODULE *pModule;
2199
2200     if (!hmod)
2201         return TASK_GetCurrent()->hInstance;
2202     if (!HIWORD(hmod))
2203         return LOWORD(hmod); /* we already have a 16 bit module handle */
2204     pModule = (NE_MODULE*)GlobalLock16(hFirstModule);
2205     while (pModule)  {
2206         if (pModule->module32 == hmod)
2207             return pModule->self;
2208         pModule = (NE_MODULE*)GlobalLock16(pModule->next);
2209     }
2210     if ((ret = create_dummy_module( hmod )) < 32)
2211     {
2212         SetLastError(ret);
2213         ret = 0;
2214     }
2215     return ret;
2216 }
2217
2218 /***************************************************************************
2219  *              MapHModuleSL                    (KERNEL32.@)
2220  */
2221 HMODULE WINAPI MapHModuleSL(HMODULE16 hmod)
2222 {
2223     NE_MODULE *pModule;
2224
2225     if (!hmod) {
2226         TDB *pTask = TASK_GetCurrent();
2227         hmod = pTask->hModule;
2228     }
2229     pModule = (NE_MODULE*)GlobalLock16(hmod);
2230     if ((pModule->magic!=IMAGE_OS2_SIGNATURE) || !(pModule->flags & NE_FFLAGS_WIN32))
2231         return 0;
2232     return pModule->module32;
2233 }
2234
2235 /***************************************************************************
2236  *              MapHInstLS                      (KERNEL32.@)
2237  *              MapHInstLS                      (KERNEL.472)
2238  */
2239 void WINAPI MapHInstLS( CONTEXT86 *context )
2240 {
2241     context->Eax = MapHModuleLS( (HMODULE)context->Eax );
2242 }
2243
2244 /***************************************************************************
2245  *              MapHInstSL                      (KERNEL32.@)
2246  *              MapHInstSL                      (KERNEL.473)
2247  */
2248 void WINAPI MapHInstSL( CONTEXT86 *context )
2249 {
2250     context->Eax = (DWORD)MapHModuleSL( context->Eax );
2251 }
2252
2253 /***************************************************************************
2254  *              MapHInstLS_PN                   (KERNEL32.@)
2255  */
2256 void WINAPI MapHInstLS_PN( CONTEXT86 *context )
2257 {
2258     if (context->Eax) context->Eax = MapHModuleLS( (HMODULE)context->Eax );
2259 }
2260
2261 /***************************************************************************
2262  *              MapHInstSL_PN                   (KERNEL32.@)
2263  */
2264 void WINAPI MapHInstSL_PN( CONTEXT86 *context )
2265 {
2266     if (context->Eax) context->Eax = (DWORD)MapHModuleSL( context->Eax );
2267 }