blob: 63c44e297ec14e61cf9d484a1e6ca92e8836a0a9 [file] [log] [blame]
Alexandre Julliard594997c1995-04-30 10:05:20 +00001/*
2 * Modules
3 *
4 * Copyright 1995 Alexandre Julliard
5 */
6
7#include <fcntl.h>
8#include <stdlib.h>
9#include <stdio.h>
10#include <string.h>
11#include <sys/types.h>
12#include <unistd.h>
13#include "windows.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000014#include "class.h"
Alexandre Julliard2787be81995-05-22 18:23:01 +000015#include "dos_fs.h"
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000016#include "file.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000017#include "global.h"
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000018#include "hook.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000019#include "ldt.h"
20#include "module.h"
21#include "neexe.h"
Alexandre Julliardca22b331996-07-12 19:02:39 +000022#include "registers.h"
Alexandre Julliard2787be81995-05-22 18:23:01 +000023#include "stackframe.h"
24#include "task.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000025#include "toolhelp.h"
26#include "stddebug.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000027#include "debug.h"
Alexandre Julliardff8331e1995-09-18 11:19:54 +000028#include "callback.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000029
Alexandre Julliard02ed4c21996-03-02 19:34:10 +000030extern HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
31
Alexandre Julliard3051b641996-07-05 17:14:13 +000032static HMODULE16 hFirstModule = 0;
33static HMODULE16 hCachedModule = 0; /* Module cached by MODULE_OpenFile */
Alexandre Julliard594997c1995-04-30 10:05:20 +000034
Alexandre Julliardade697e1995-11-26 13:59:11 +000035#ifndef WINELIB
Alexandre Julliard902da691995-11-05 14:39:02 +000036static HANDLE hInitialStack32 = 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +000037#endif
Alexandre Julliard594997c1995-04-30 10:05:20 +000038
39
40/***********************************************************************
Alexandre Julliard329f0681996-04-14 13:21:20 +000041 * MODULE_GetPtr
42 */
Alexandre Julliard3051b641996-07-05 17:14:13 +000043NE_MODULE *MODULE_GetPtr( HMODULE16 hModule )
Alexandre Julliard329f0681996-04-14 13:21:20 +000044{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000045 NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +000046 if (!pModule || (pModule->magic != NE_SIGNATURE) ||
47 (pModule->self != hModule)) return NULL;
48 return pModule;
49}
50
51
52/***********************************************************************
Alexandre Julliard8664b891996-04-05 14:58:24 +000053 * MODULE_DumpModule
Alexandre Julliard594997c1995-04-30 10:05:20 +000054 */
Alexandre Julliard3051b641996-07-05 17:14:13 +000055void MODULE_DumpModule( HMODULE16 hmodule )
Alexandre Julliard594997c1995-04-30 10:05:20 +000056{
57 int i, ordinal;
58 SEGTABLEENTRY *pSeg;
59 BYTE *pstr;
60 WORD *pword;
Alexandre Julliard329f0681996-04-14 13:21:20 +000061 NE_MODULE *pModule;
Alexandre Julliard594997c1995-04-30 10:05:20 +000062
Alexandre Julliard329f0681996-04-14 13:21:20 +000063 if (!(pModule = MODULE_GetPtr( hmodule )))
Alexandre Julliard8664b891996-04-05 14:58:24 +000064 {
65 fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
66 return;
67 }
68
Alexandre Julliard594997c1995-04-30 10:05:20 +000069 /* Dump the module info */
70
Alexandre Julliard59730ae1996-03-24 16:20:51 +000071 printf( "Module %04x:\n", hmodule );
Alexandre Julliard594997c1995-04-30 10:05:20 +000072 printf( "count=%d flags=%04x heap=%d stack=%d\n",
73 pModule->count, pModule->flags,
74 pModule->heap_size, pModule->stack_size );
75 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
76 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
77 pModule->seg_count, pModule->modref_count );
78 printf( "os_flags=%d swap_area=%d version=%04x\n",
79 pModule->os_flags, pModule->min_swap_area,
80 pModule->expected_version );
Alexandre Julliard8664b891996-04-05 14:58:24 +000081 if (pModule->flags & NE_FFLAGS_WIN32)
Alexandre Julliard329f0681996-04-14 13:21:20 +000082 printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
Alexandre Julliard594997c1995-04-30 10:05:20 +000083
84 /* Dump the file info */
85
Alexandre Julliard02ed4c21996-03-02 19:34:10 +000086 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
Alexandre Julliard594997c1995-04-30 10:05:20 +000087
88 /* Dump the segment table */
89
90 printf( "\nSegment table:\n" );
91 pSeg = NE_SEG_TABLE( pModule );
92 for (i = 0; i < pModule->seg_count; i++, pSeg++)
Alexandre Julliard59730ae1996-03-24 16:20:51 +000093 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +000094 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
95 pSeg->minsize, pSeg->selector );
96
97 /* Dump the resource table */
98
99 printf( "\nResource table:\n" );
100 if (pModule->res_table)
101 {
102 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
103 printf( "Alignment: %d\n", *pword++ );
104 while (*pword)
105 {
106 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
107 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
108 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
109 for (i = 0; i < ptr->count; i++, pname++)
110 printf( "offset=%d len=%d id=%04x\n",
111 pname->offset, pname->length, pname->id );
112 pword = (WORD *)pname;
113 }
114 }
115 else printf( "None\n" );
116
117 /* Dump the resident name table */
118
119 printf( "\nResident-name table:\n" );
120 pstr = (char *)pModule + pModule->name_table;
121 while (*pstr)
122 {
123 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
124 *(WORD *)(pstr + *pstr + 1) );
125 pstr += *pstr + 1 + sizeof(WORD);
126 }
127
128 /* Dump the module reference table */
129
130 printf( "\nModule ref table:\n" );
131 if (pModule->modref_table)
132 {
133 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
134 for (i = 0; i < pModule->modref_count; i++, pword++)
135 {
Alexandre Julliard3051b641996-07-05 17:14:13 +0000136 printf( "%d: %04x -> '%s'\n", i, *pword,
137 MODULE_GetModuleName(*pword));
Alexandre Julliard594997c1995-04-30 10:05:20 +0000138 }
139 }
140 else printf( "None\n" );
141
142 /* Dump the entry table */
143
144 printf( "\nEntry table:\n" );
145 pstr = (char *)pModule + pModule->entry_table;
146 ordinal = 1;
147 while (*pstr)
148 {
149 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
150 if (!pstr[1])
151 {
152 ordinal += *pstr;
153 pstr += 2;
154 }
155 else if ((BYTE)pstr[1] == 0xff) /* moveable */
156 {
157 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
158 for (i = 0; i < *pstr; i++, pe++)
159 printf( "%d: %02x:%04x (moveable)\n",
160 ordinal++, pe->seg_number, pe->offset );
161 pstr = (char *)pe;
162 }
163 else /* fixed */
164 {
165 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
166 for (i = 0; i < *pstr; i++, pe++)
167 printf( "%d: %04x (fixed)\n",
168 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
169 pstr = (char *)pe;
170 }
171 }
172
173 /* Dump the non-resident names table */
174
175 printf( "\nNon-resident names table:\n" );
176 if (pModule->nrname_handle)
177 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000178 pstr = (char *)GlobalLock16( pModule->nrname_handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000179 while (*pstr)
180 {
181 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
182 *(WORD *)(pstr + *pstr + 1) );
183 pstr += *pstr + 1 + sizeof(WORD);
184 }
185 }
186 printf( "\n" );
187}
188
189
190/***********************************************************************
Alexandre Julliard8664b891996-04-05 14:58:24 +0000191 * MODULE_WalkModules
192 *
193 * Walk the module list and print the modules.
194 */
195void MODULE_WalkModules(void)
196{
197 HMODULE hModule = hFirstModule;
198 fprintf( stderr, "Module Flags Name\n" );
199 while (hModule)
200 {
Alexandre Julliard329f0681996-04-14 13:21:20 +0000201 NE_MODULE *pModule = MODULE_GetPtr( hModule );
202 if (!pModule)
Alexandre Julliard8664b891996-04-05 14:58:24 +0000203 {
204 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
205 return;
206 }
207 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
208 *((char *)pModule + pModule->name_table),
209 (char *)pModule + pModule->name_table + 1 );
210 hModule = pModule->next;
211 }
212}
213
214
215/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000216 * MODULE_OpenFile
217 */
Alexandre Julliard3051b641996-07-05 17:14:13 +0000218int MODULE_OpenFile( HMODULE16 hModule )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000219{
220 NE_MODULE *pModule;
221 char *name;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000222 const char *unixName;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000223
Alexandre Julliard594997c1995-04-30 10:05:20 +0000224 static int cachedfd = -1;
225
226 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000227 dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +0000228 hModule, hCachedModule, cachedfd );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000229 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000230 if (hCachedModule == hModule) return cachedfd;
231 close( cachedfd );
232 hCachedModule = hModule;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +0000233 name = NE_MODULE_NAME( pModule );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000234 if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
235 (cachedfd = open( unixName, O_RDONLY )) == -1)
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000236 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000237 name, hModule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000238 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
239 name, cachedfd );
240 return cachedfd;
241}
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000242
243
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000244/***********************************************************************
245 * MODULE_Ne2MemFlags
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000246 *
247 * This function translates NE segment flags to GlobalAlloc flags
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000248 */
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000249static WORD MODULE_Ne2MemFlags(WORD flags)
250{
251 WORD memflags = 0;
252#if 0
253 if (flags & NE_SEGFLAGS_DISCARDABLE)
254 memflags |= GMEM_DISCARDABLE;
255 if (flags & NE_SEGFLAGS_MOVEABLE ||
256 ( ! (flags & NE_SEGFLAGS_DATA) &&
257 ! (flags & NE_SEGFLAGS_LOADED) &&
258 ! (flags & NE_SEGFLAGS_ALLOCATED)
259 )
260 )
261 memflags |= GMEM_MOVEABLE;
262 memflags |= GMEM_ZEROINIT;
263#else
264 memflags = GMEM_ZEROINIT | GMEM_FIXED;
265 return memflags;
266#endif
267}
268
269/***********************************************************************
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000270 * MODULE_AllocateSegment (WPROCS.26)
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000271 */
272
273DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
274{
275 WORD size = wSize << wElem;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000276 HANDLE hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
277#ifdef WINELIB
278 return (DWORD)GlobalLock16(hMem);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000279#else
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000280 WORD selector = HIWORD(WIN16_GlobalLock16(hMem));
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000281 return MAKELONG(hMem, selector);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000282#endif
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000283}
Alexandre Julliard594997c1995-04-30 10:05:20 +0000284
285/***********************************************************************
286 * MODULE_CreateSegments
287 */
Alexandre Julliard902da691995-11-05 14:39:02 +0000288#ifndef WINELIB32
Alexandre Julliard3051b641996-07-05 17:14:13 +0000289static BOOL MODULE_CreateSegments( HMODULE16 hModule )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000290{
291 SEGTABLEENTRY *pSegment;
292 NE_MODULE *pModule;
293 int i, minsize;
294
Alexandre Julliard329f0681996-04-14 13:21:20 +0000295 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000296 pSegment = NE_SEG_TABLE( pModule );
297 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
298 {
299 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
300 if (i == pModule->ss) minsize += pModule->stack_size;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000301 /* The DGROUP is allocated by MODULE_CreateInstance */
302 if (i == pModule->dgroup) continue;
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000303 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
Alexandre Julliard594997c1995-04-30 10:05:20 +0000304 minsize, hModule,
305 !(pSegment->flags & NE_SEGFLAGS_DATA),
306 FALSE,
307 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
308 if (!pSegment->selector) return FALSE;
309 }
310
311 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
312 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
313 return TRUE;
314}
Alexandre Julliard902da691995-11-05 14:39:02 +0000315#endif
Alexandre Julliard594997c1995-04-30 10:05:20 +0000316
317
318/***********************************************************************
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000319 * MODULE_GetInstance
320 */
Alexandre Julliard902da691995-11-05 14:39:02 +0000321#ifndef WINELIB32
Alexandre Julliard3051b641996-07-05 17:14:13 +0000322HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule )
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000323{
324 SEGTABLEENTRY *pSegment;
325 NE_MODULE *pModule;
326
Alexandre Julliard329f0681996-04-14 13:21:20 +0000327 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000328 if (pModule->dgroup == 0) return hModule;
329
330 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
331
332 return pSegment->selector;
333}
Alexandre Julliard902da691995-11-05 14:39:02 +0000334#endif
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000335
336
337/***********************************************************************
338 * MODULE_CreateInstance
339 */
Alexandre Julliard3051b641996-07-05 17:14:13 +0000340HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000341{
342 SEGTABLEENTRY *pSegment;
343 NE_MODULE *pModule;
344 int minsize;
345 HINSTANCE hNewInstance, hPrevInstance;
346
Alexandre Julliard329f0681996-04-14 13:21:20 +0000347 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000348 if (pModule->dgroup == 0) return hModule;
349
350 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
351 hPrevInstance = pSegment->selector;
352
353 /* if it's a library, create a new instance only the first time */
354 if (hPrevInstance)
355 {
356 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
357 if (params == (LOADPARAMS*)-1) return hPrevInstance;
358 }
359
360 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
361 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
362 minsize += pModule->heap_size;
363 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
364 minsize, hModule, FALSE, FALSE, FALSE );
365 if (!hNewInstance) return 0;
366 pSegment->selector = hNewInstance;
367 return hNewInstance;
368}
369
370
371/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000372 * MODULE_LoadExeHeader
373 */
Alexandre Julliard3051b641996-07-05 17:14:13 +0000374static HMODULE16 MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000375{
376 struct mz_header_s mz_header;
377 struct ne_header_s ne_header;
378 int size;
Alexandre Julliard3051b641996-07-05 17:14:13 +0000379 HMODULE16 hModule;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000380 NE_MODULE *pModule;
381 BYTE *pData;
382 char *buffer, *fastload = NULL;
383 int fastload_offset = 0, fastload_length = 0;
384
385 /* Read a block from either the file or the fast-load area. */
386#define READ(offset,size,buffer) \
387 ((fastload && ((offset) >= fastload_offset) && \
388 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
389 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000390 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
391 FILE_Read( hFile, (buffer), (size) ) == (size)))
Alexandre Julliard594997c1995-04-30 10:05:20 +0000392
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000393 _llseek( hFile, 0, SEEK_SET );
394 if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
Alexandre Julliard3051b641996-07-05 17:14:13 +0000395 (mz_header.mz_magic != MZ_SIGNATURE))
396 return (HMODULE16)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000397
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000398 _llseek( hFile, mz_header.ne_offset, SEEK_SET );
399 if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
Alexandre Julliard3051b641996-07-05 17:14:13 +0000400 return (HMODULE16)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000401
Alexandre Julliard3051b641996-07-05 17:14:13 +0000402 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE16)21; /* win32 exe */
403 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE16)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000404
405 /* We now have a valid NE header */
406
407 size = sizeof(NE_MODULE) +
408 /* loaded file info */
Alexandre Julliard02ed4c21996-03-02 19:34:10 +0000409 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
Alexandre Julliard594997c1995-04-30 10:05:20 +0000410 /* segment table */
411 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
412 /* resource table */
413 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
414 /* resident names table */
415 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
416 /* module ref table */
417 ne_header.n_mod_ref_tab * sizeof(WORD) +
418 /* imported names table */
419 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
420 /* entry table length */
421 ne_header.entry_tab_length;
422
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000423 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000424 if (!hModule) return (HMODULE16)11; /* invalid exe */
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000425 FarSetOwner( hModule, hModule );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000426 pModule = (NE_MODULE *)GlobalLock16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000427 memcpy( pModule, &ne_header, sizeof(ne_header) );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000428 pModule->count = 0;
Alexandre Julliard329f0681996-04-14 13:21:20 +0000429 pModule->pe_module = NULL;
430 pModule->self = hModule;
431 pModule->self_loading_sel = 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000432 pData = (BYTE *)(pModule + 1);
433
Alexandre Julliard329f0681996-04-14 13:21:20 +0000434 /* Clear internal Wine flags in case they are set in the EXE file */
435
436 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
437
Alexandre Julliard594997c1995-04-30 10:05:20 +0000438 /* Read the fast-load area */
439
440 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
441 {
442 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
443 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
444 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
445 fastload_offset, fastload_length );
446 if ((fastload = (char *)malloc( fastload_length )) != NULL)
447 {
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000448 _llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET );
449 if (FILE_Read( hFile, fastload, fastload_length ) != fastload_length)
Alexandre Julliard594997c1995-04-30 10:05:20 +0000450 {
451 free( fastload );
452 fastload = NULL;
453 }
454 }
455 }
456
457 /* Store the filename information */
458
459 pModule->fileinfo = (int)pData - (int)pModule;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +0000460 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
461 memcpy( pData, ofs, size );
462 ((OFSTRUCT *)pData)->cBytes = size - 1;
463 pData += size;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000464
465 /* Get the segment table */
466
467 pModule->seg_table = (int)pData - (int)pModule;
468 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
469 if (buffer)
470 {
471 int i;
472 struct ne_segment_table_entry_s *pSeg;
473
474 if (!READ( ne_header.segment_tab_offset,
475 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
Alexandre Julliard3051b641996-07-05 17:14:13 +0000476 buffer )) return (HMODULE16)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000477 pSeg = (struct ne_segment_table_entry_s *)buffer;
478 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
479 {
480 memcpy( pData, pSeg, sizeof(*pSeg) );
481 pData += sizeof(SEGTABLEENTRY);
482 }
483 free( buffer );
484 }
Alexandre Julliard329f0681996-04-14 13:21:20 +0000485 else
486 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000487 GlobalFree16( hModule );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000488 return (HMODULE16)11; /* invalid exe */
Alexandre Julliard329f0681996-04-14 13:21:20 +0000489 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000490
491 /* Get the resource table */
492
493 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
494 {
495 pModule->res_table = (int)pData - (int)pModule;
496 if (!READ(ne_header.resource_tab_offset,
497 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
Alexandre Julliard3051b641996-07-05 17:14:13 +0000498 pData )) return (HMODULE16)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000499 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
500 }
501 else pModule->res_table = 0; /* No resource table */
502
503 /* Get the resident names table */
504
505 pModule->name_table = (int)pData - (int)pModule;
506 if (!READ( ne_header.rname_tab_offset,
507 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
Alexandre Julliard329f0681996-04-14 13:21:20 +0000508 pData ))
509 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000510 GlobalFree16( hModule );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000511 return (HMODULE16)11; /* invalid exe */
Alexandre Julliard329f0681996-04-14 13:21:20 +0000512 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000513 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
514
515 /* Get the module references table */
516
517 if (ne_header.n_mod_ref_tab > 0)
518 {
519 pModule->modref_table = (int)pData - (int)pModule;
520 if (!READ( ne_header.moduleref_tab_offset,
521 ne_header.n_mod_ref_tab * sizeof(WORD),
Alexandre Julliard3051b641996-07-05 17:14:13 +0000522 pData )) return (HMODULE16)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000523 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
524 }
525 else pModule->modref_table = 0; /* No module references */
526
527 /* Get the imported names table */
528
529 pModule->import_table = (int)pData - (int)pModule;
530 if (!READ( ne_header.iname_tab_offset,
531 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
Alexandre Julliard329f0681996-04-14 13:21:20 +0000532 pData ))
533 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000534 GlobalFree16( hModule );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000535 return (HMODULE16)11; /* invalid exe */
Alexandre Julliard329f0681996-04-14 13:21:20 +0000536 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000537 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
538
539 /* Get the entry table */
540
541 pModule->entry_table = (int)pData - (int)pModule;
542 if (!READ( ne_header.entry_tab_offset,
543 ne_header.entry_tab_length,
Alexandre Julliard329f0681996-04-14 13:21:20 +0000544 pData ))
545 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000546 GlobalFree16( hModule );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000547 return (HMODULE16)11; /* invalid exe */
Alexandre Julliard329f0681996-04-14 13:21:20 +0000548 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000549 pData += ne_header.entry_tab_length;
550
551 /* Get the non-resident names table */
552
553 if (ne_header.nrname_tab_length)
554 {
555 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
556 hModule, FALSE, FALSE, FALSE );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000557 if (!pModule->nrname_handle)
558 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000559 GlobalFree16( hModule );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000560 return (HMODULE16)11; /* invalid exe */
Alexandre Julliard329f0681996-04-14 13:21:20 +0000561 }
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000562 buffer = GlobalLock16( pModule->nrname_handle );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000563 _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
564 if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length )
Alexandre Julliard329f0681996-04-14 13:21:20 +0000565 != ne_header.nrname_tab_length)
566 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000567 GlobalFree16( pModule->nrname_handle );
568 GlobalFree16( hModule );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000569 return (HMODULE16)11; /* invalid exe */
Alexandre Julliard329f0681996-04-14 13:21:20 +0000570 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000571 }
572 else pModule->nrname_handle = 0;
573
Alexandre Julliard2787be81995-05-22 18:23:01 +0000574 /* Allocate a segment for the implicitly-loaded DLLs */
575
576 if (pModule->modref_count)
577 {
578 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
Alexandre Julliard3051b641996-07-05 17:14:13 +0000579 (pModule->modref_count+1)*sizeof(HMODULE16),
Alexandre Julliard2787be81995-05-22 18:23:01 +0000580 hModule, FALSE, FALSE, FALSE );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000581 if (!pModule->dlls_to_init)
582 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000583 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
584 GlobalFree16( hModule );
Alexandre Julliard3051b641996-07-05 17:14:13 +0000585 return (HMODULE16)11; /* invalid exe */
Alexandre Julliard329f0681996-04-14 13:21:20 +0000586 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000587 }
588 else pModule->dlls_to_init = 0;
589
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000590 MODULE_RegisterModule( pModule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000591 return hModule;
Alexandre Julliard329f0681996-04-14 13:21:20 +0000592#undef READ
Alexandre Julliard594997c1995-04-30 10:05:20 +0000593}
594
595
596/***********************************************************************
597 * MODULE_GetOrdinal
598 *
599 * Lookup the ordinal for a given name.
600 */
Alexandre Julliard3051b641996-07-05 17:14:13 +0000601WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000602{
603 char buffer[256], *cpnt;
604 BYTE len;
605 NE_MODULE *pModule;
606
Alexandre Julliard329f0681996-04-14 13:21:20 +0000607 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000608
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000609 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +0000610 hModule, name );
611
612 /* First handle names of the form '#xxxx' */
613
614 if (name[0] == '#') return atoi( name + 1 );
615
616 /* Now copy and uppercase the string */
617
618 strcpy( buffer, name );
619 AnsiUpper( buffer );
620 len = strlen( buffer );
621
622 /* First search the resident names */
623
624 cpnt = (char *)pModule + pModule->name_table;
625
626 /* Skip the first entry (module name) */
627 cpnt += *cpnt + 1 + sizeof(WORD);
628 while (*cpnt)
629 {
Alexandre Julliard594997c1995-04-30 10:05:20 +0000630 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
631 {
632 dprintf_module( stddeb, " Found: ordinal=%d\n",
633 *(WORD *)(cpnt + *cpnt + 1) );
634 return *(WORD *)(cpnt + *cpnt + 1);
635 }
636 cpnt += *cpnt + 1 + sizeof(WORD);
637 }
638
639 /* Now search the non-resident names table */
640
641 if (!pModule->nrname_handle) return 0; /* No non-resident table */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000642 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000643
644 /* Skip the first entry (module description string) */
645 cpnt += *cpnt + 1 + sizeof(WORD);
646 while (*cpnt)
647 {
Alexandre Julliard594997c1995-04-30 10:05:20 +0000648 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
649 {
650 dprintf_module( stddeb, " Found: ordinal=%d\n",
651 *(WORD *)(cpnt + *cpnt + 1) );
652 return *(WORD *)(cpnt + *cpnt + 1);
653 }
654 cpnt += *cpnt + 1 + sizeof(WORD);
655 }
656 return 0;
657}
658
659
660/***********************************************************************
661 * MODULE_GetEntryPoint
662 *
663 * Return the entry point for a given ordinal.
664 */
Alexandre Julliardca22b331996-07-12 19:02:39 +0000665FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000666{
667 NE_MODULE *pModule;
668 WORD curOrdinal = 1;
669 BYTE *p;
670 WORD sel, offset;
671
Alexandre Julliard329f0681996-04-14 13:21:20 +0000672 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000673
Alexandre Julliard594997c1995-04-30 10:05:20 +0000674 p = (BYTE *)pModule + pModule->entry_table;
675 while (*p && (curOrdinal + *p <= ordinal))
676 {
677 /* Skipping this bundle */
678 curOrdinal += *p;
679 switch(p[1])
680 {
681 case 0: p += 2; break; /* unused */
682 case 0xff: p += 2 + *p * 6; break; /* moveable */
683 default: p += 2 + *p * 3; break; /* fixed */
684 }
685 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000686 if (!*p) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000687
688 switch(p[1])
689 {
690 case 0: /* unused */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000691 return 0;
692 case 0xff: /* moveable */
693 p += 2 + 6 * (ordinal - curOrdinal);
694 sel = p[3];
695 offset = *(WORD *)(p + 4);
696 break;
697 default: /* fixed */
698 sel = p[1];
699 p += 2 + 3 * (ordinal - curOrdinal);
700 offset = *(WORD *)(p + 1);
701 break;
702 }
703
Alexandre Julliard594997c1995-04-30 10:05:20 +0000704 if (sel == 0xfe) sel = 0xffff; /* constant entry */
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000705 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
Alexandre Julliardca22b331996-07-12 19:02:39 +0000706 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000707}
708
709
710/***********************************************************************
Alexandre Julliard2787be81995-05-22 18:23:01 +0000711 * MODULE_SetEntryPoint
712 *
713 * Change the value of an entry point. Use with caution!
714 * It can only change the offset value, not the selector.
715 */
Alexandre Julliard3051b641996-07-05 17:14:13 +0000716BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000717{
718 NE_MODULE *pModule;
719 WORD curOrdinal = 1;
720 BYTE *p;
721
Alexandre Julliard329f0681996-04-14 13:21:20 +0000722 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000723
724 p = (BYTE *)pModule + pModule->entry_table;
725 while (*p && (curOrdinal + *p <= ordinal))
726 {
727 /* Skipping this bundle */
728 curOrdinal += *p;
729 switch(p[1])
730 {
731 case 0: p += 2; break; /* unused */
732 case 0xff: p += 2 + *p * 6; break; /* moveable */
733 default: p += 2 + *p * 3; break; /* fixed */
734 }
735 }
736 if (!*p) return FALSE;
737
738 switch(p[1])
739 {
740 case 0: /* unused */
741 return FALSE;
742 case 0xff: /* moveable */
743 p += 2 + 6 * (ordinal - curOrdinal);
744 *(WORD *)(p + 4) = offset;
745 break;
746 default: /* fixed */
747 p += 2 + 3 * (ordinal - curOrdinal);
748 *(WORD *)(p + 1) = offset;
749 break;
750 }
751 return TRUE;
752}
753
754
755/***********************************************************************
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000756 * MODULE_GetWndProcEntry16 (not a Windows API function)
757 *
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000758 * Return an entry point from the WPROCS dll.
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000759 */
760#ifndef WINELIB
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000761FARPROC16 MODULE_GetWndProcEntry16( const char *name )
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000762{
763 WORD ordinal;
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000764 FARPROC16 ret;
Alexandre Julliard3051b641996-07-05 17:14:13 +0000765 static HMODULE16 hModule = 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000766
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000767 if (!hModule) hModule = GetModuleHandle( "WPROCS" );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000768 ordinal = MODULE_GetOrdinal( hModule, name );
Alexandre Julliard2d93d001996-05-21 15:01:41 +0000769 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
770 fprintf( stderr, "GetWndProc16: %s not found, please report\n", name );
771 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000772}
773#endif
774
775
776/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000777 * MODULE_GetModuleName
778 */
Alexandre Julliard3051b641996-07-05 17:14:13 +0000779LPSTR MODULE_GetModuleName( HMODULE16 hModule )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000780{
781 NE_MODULE *pModule;
782 BYTE *p, len;
783 static char buffer[10];
784
Alexandre Julliard329f0681996-04-14 13:21:20 +0000785 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000786 p = (BYTE *)pModule + pModule->name_table;
Alexandre Julliard902da691995-11-05 14:39:02 +0000787 len = MIN( *p, 8 );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000788 memcpy( buffer, p + 1, len );
789 buffer[len] = '\0';
790 return buffer;
791}
792
793
794/**********************************************************************
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000795 * MODULE_RegisterModule
796 */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000797void MODULE_RegisterModule( NE_MODULE *pModule )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000798{
Alexandre Julliard329f0681996-04-14 13:21:20 +0000799 pModule->next = hFirstModule;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000800 hFirstModule = pModule->self;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000801}
802
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000803
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000804/**********************************************************************
Alexandre Julliard2787be81995-05-22 18:23:01 +0000805 * MODULE_FindModule
806 *
807 * Find a module from a path name.
808 */
Alexandre Julliard3051b641996-07-05 17:14:13 +0000809HMODULE16 MODULE_FindModule( LPCSTR path )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000810{
Alexandre Julliard3051b641996-07-05 17:14:13 +0000811 HMODULE16 hModule = hFirstModule;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000812 LPCSTR filename, dotptr, modulepath, modulename;
813 BYTE len, *name_table;
814
815 if (!(filename = strrchr( path, '\\' ))) filename = path;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000816 else filename++;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000817 if ((dotptr = strrchr( filename, '.' )) != NULL)
818 len = (BYTE)(dotptr - filename);
819 else len = strlen( filename );
820
821 while(hModule)
822 {
Alexandre Julliard329f0681996-04-14 13:21:20 +0000823 NE_MODULE *pModule = MODULE_GetPtr( hModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000824 if (!pModule) break;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +0000825 modulepath = NE_MODULE_NAME(pModule);
Alexandre Julliard2787be81995-05-22 18:23:01 +0000826 if (!(modulename = strrchr( modulepath, '\\' )))
827 modulename = modulepath;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000828 else modulename++;
Alexandre Julliardd90840e1996-06-11 16:02:08 +0000829 if (!lstrcmpi32A( modulename, filename )) return hModule;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000830
831 name_table = (BYTE *)pModule + pModule->name_table;
Alexandre Julliardd90840e1996-06-11 16:02:08 +0000832 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
Alexandre Julliard2787be81995-05-22 18:23:01 +0000833 return hModule;
834 hModule = pModule->next;
835 }
836 return 0;
837}
838
839
840/**********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +0000841 * MODULE_CallWEP
842 *
843 * Call a DLL's WEP, allowing it to shut down.
844 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
845 */
846static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
847{
848 FARPROC16 WEP = (FARPROC16)0;
849 WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
850
851 if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
852 if (!WEP)
853 {
854 dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
855 return FALSE;
856 }
857 return CallWindowsExitProc( WEP, WEP_FREE_DLL );
858}
859
860
861/**********************************************************************
Alexandre Julliard2787be81995-05-22 18:23:01 +0000862 * MODULE_FreeModule
863 *
864 * Remove a module from memory.
865 */
Alexandre Julliard3051b641996-07-05 17:14:13 +0000866static void MODULE_FreeModule( HMODULE16 hModule )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000867{
Alexandre Julliard3051b641996-07-05 17:14:13 +0000868 HMODULE16 *hPrevModule;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000869 NE_MODULE *pModule;
870 SEGTABLEENTRY *pSegment;
Alexandre Julliard3051b641996-07-05 17:14:13 +0000871 HMODULE16 *pModRef;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000872 int i;
873
Alexandre Julliard329f0681996-04-14 13:21:20 +0000874 if (!(pModule = MODULE_GetPtr( hModule ))) return;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000875 if (pModule->flags & NE_FFLAGS_BUILTIN)
876 return; /* Can't free built-in module */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000877
Alexandre Julliard3051b641996-07-05 17:14:13 +0000878 if (pModule->flags & NE_FFLAGS_LIBMODULE) MODULE_CallWEP( hModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000879
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000880 /* Free the objects owned by the module */
881
882 HOOK_FreeModuleHooks( hModule );
883 CLASS_FreeModuleClasses( hModule );
884
Alexandre Julliard329f0681996-04-14 13:21:20 +0000885 /* Clear magic number just in case */
886
887 pModule->magic = pModule->self = 0;
888
Alexandre Julliard2787be81995-05-22 18:23:01 +0000889 /* Remove it from the linked list */
890
891 hPrevModule = &hFirstModule;
892 while (*hPrevModule && (*hPrevModule != hModule))
893 {
Alexandre Julliard329f0681996-04-14 13:21:20 +0000894 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000895 }
896 if (*hPrevModule) *hPrevModule = pModule->next;
897
898 /* Free all the segments */
899
900 pSegment = NE_SEG_TABLE( pModule );
901 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
902 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000903 GlobalFree16( pSegment->selector );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000904 }
905
906 /* Free the referenced modules */
907
Alexandre Julliard3051b641996-07-05 17:14:13 +0000908 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000909 for (i = 0; i < pModule->modref_count; i++, pModRef++)
910 {
Alexandre Julliard3051b641996-07-05 17:14:13 +0000911 FreeModule16( *pModRef );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000912 }
913
914 /* Free the module storage */
915
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000916 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
917 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
918 GlobalFree16( hModule );
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000919
920 /* Remove module from cache */
921
922 if (hCachedModule == hModule) hCachedModule = 0;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000923}
924
925
926/**********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000927 * LoadModule (KERNEL.45)
928 */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000929HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000930{
Alexandre Julliard3051b641996-07-05 17:14:13 +0000931 HMODULE16 hModule;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000932 HANDLE hInstance, hPrevInstance;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000933 NE_MODULE *pModule;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000934 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
Alexandre Julliardade697e1995-11-26 13:59:11 +0000935#ifndef WINELIB
Alexandre Julliard2787be81995-05-22 18:23:01 +0000936 WORD *pModRef, *pDLLs;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000937 HFILE hFile;
938 int i;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000939
940 hModule = MODULE_FindModule( name );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000941
Alexandre Julliard2787be81995-05-22 18:23:01 +0000942 if (!hModule) /* We have to load the module */
943 {
944 OFSTRUCT ofs;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000945
946 /* Try to load the built-in first if not disabled */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000947 if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000948
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000949 if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000950 {
951 /* Now try the built-in even if disabled */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000952 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000953 {
954 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
955 return hModule;
956 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000957 return 2; /* File not found */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000958 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000959
960 /* Create the module structure */
961
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000962 hModule = MODULE_LoadExeHeader( hFile, &ofs );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000963 if (hModule < 32)
Alexandre Julliard2787be81995-05-22 18:23:01 +0000964 {
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000965 /* FIXME: Hack because PE_LoadModule is recursive */
966 int fd = dup( FILE_GetUnixHandle(hFile) );
967 _lclose( hFile );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000968 if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000969 close( fd );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000970 if (hModule < 32)
971 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
972 name, hModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000973 return hModule;
974 }
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000975 _lclose( hFile );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000976 pModule = MODULE_GetPtr( hModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000977
978 /* Allocate the segments for this module */
979
980 MODULE_CreateSegments( hModule );
981
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000982 hPrevInstance = 0;
983 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
984
Alexandre Julliard2787be81995-05-22 18:23:01 +0000985 /* Load the referenced DLLs */
986
987 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000988 pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000989 for (i = 0; i < pModule->modref_count; i++, pModRef++)
990 {
991 char buffer[256];
992 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
993 memcpy( buffer, pstr + 1, *pstr );
994 strcpy( buffer + *pstr, ".dll" );
995 dprintf_module( stddeb, "Loading '%s'\n", buffer );
996 if (!(*pModRef = MODULE_FindModule( buffer )))
997 {
998 /* If the DLL is not loaded yet, load it and store */
999 /* its handle in the list of DLLs to initialize. */
Alexandre Julliard3051b641996-07-05 17:14:13 +00001000 HMODULE16 hDLL;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001001
1002 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
1003 {
1004 char *p;
1005
1006 /* Try with prepending the path of the current module */
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001007 GetModuleFileName( hModule, buffer, sizeof(buffer) );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001008 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1009 memcpy( p + 1, pstr + 1, *pstr );
1010 strcpy( p + 1 + *pstr, ".dll" );
1011 hDLL = LoadModule( buffer, (LPVOID)-1 );
1012 }
1013 if (hDLL < 32)
1014 {
1015 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1016 buffer, name, hDLL );
1017 return 2; /* file not found */
1018 }
1019 *pModRef = GetExePtr( hDLL );
1020 *pDLLs++ = *pModRef;
1021 }
1022 else /* Increment the reference count of the DLL */
1023 {
Alexandre Julliard329f0681996-04-14 13:21:20 +00001024 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001025 if (pOldDLL) pOldDLL->count++;
1026 }
1027 }
1028
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001029 /* Load the segments */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001030
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001031 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1032 {
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +00001033 int fd;
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001034 /* Handle self loading modules */
1035 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1036 SELFLOADHEADER *selfloadheader;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001037 STACK16FRAME *stack16Top;
Alexandre Julliard3051b641996-07-05 17:14:13 +00001038 HMODULE16 hselfload = GetModuleHandle("WPROCS");
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001039 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1040 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1041 "Support for self-loading modules is very experimental\n",
1042 *((BYTE*)pModule + pModule->name_table),
1043 *((BYTE*)pModule + pModule->name_table),
1044 (char *)pModule + pModule->name_table + 1);
1045 NE_LoadSegment( hModule, 1 );
1046 selfloadheader = (SELFLOADHEADER *)
1047 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1048 selfloadheader->EntryAddrProc =
1049 MODULE_GetEntryPoint(hselfload,27);
1050 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1051 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1052 pModule->self_loading_sel = GlobalHandleToSel(
1053 GLOBAL_Alloc (GMEM_ZEROINIT,
1054 0xFF00, hModule, FALSE, FALSE, FALSE)
1055 );
1056 oldss = IF1632_Saved16_ss;
1057 oldsp = IF1632_Saved16_sp;
1058 IF1632_Saved16_ss = pModule->self_loading_sel;
Alexandre Julliard1e9ac791996-06-06 18:38:27 +00001059 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
1060 stack16Top = CURRENT_STACK16;
1061 stack16Top->saved_ss = 0;
1062 stack16Top->saved_sp = 0;
1063 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
1064 stack16Top->entry_point = 0;
1065 stack16Top->entry_ip = 0;
1066 stack16Top->entry_cs = 0;
1067 stack16Top->bp = 0;
1068 stack16Top->ip = 0;
1069 stack16Top->cs = 0;
1070
Alexandre Julliard902da691995-11-05 14:39:02 +00001071 if (!IF1632_Stack32_base) {
1072 STACK32FRAME* frame32;
1073 char *stack32Top;
1074 /* Setup an initial 32 bit stack frame */
1075 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1076 hModule, FALSE, FALSE,
1077 FALSE );
1078
1079 /* Create the 32-bit stack frame */
1080
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001081 *(DWORD *)GlobalLock16(hInitialStack32) = 0xDEADBEEF;
1082 stack32Top = (char*)GlobalLock16(hInitialStack32) +
Alexandre Julliard902da691995-11-05 14:39:02 +00001083 0x10000;
1084 frame32 = (STACK32FRAME *)stack32Top - 1;
1085 frame32->saved_esp = (DWORD)stack32Top;
1086 frame32->edi = 0;
1087 frame32->esi = 0;
1088 frame32->edx = 0;
1089 frame32->ecx = 0;
1090 frame32->ebx = 0;
1091 frame32->ebp = 0;
1092 frame32->retaddr = 0;
1093 frame32->codeselector = WINE_CODE_SELECTOR;
1094 /* pTask->esp = (DWORD)frame32; */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001095 IF1632_Stack32_base = WIN16_GlobalLock16(hInitialStack32);
Alexandre Julliard902da691995-11-05 14:39:02 +00001096
1097 }
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +00001098 /* FIXME: we probably need a DOS handle here */
1099 fd = MODULE_OpenFile( hModule );
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001100 CallTo16_word_ww (selfloadheader->BootApp,
1101 pModule->self_loading_sel, hModule, fd);
1102 /* some BootApp procs overwrite the selector of dgroup */
1103 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1104 IF1632_Saved16_ss = oldss;
1105 IF1632_Saved16_sp = oldsp;
1106 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
Alexandre Julliard902da691995-11-05 14:39:02 +00001107 if (hInitialStack32){
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001108 GlobalFree16(hInitialStack32);
Alexandre Julliard902da691995-11-05 14:39:02 +00001109 IF1632_Stack32_base = hInitialStack32 = 0;
1110 }
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001111 }
1112 else
1113 {
1114 for (i = 1; i <= pModule->seg_count; i++)
1115 NE_LoadSegment( hModule, i );
1116 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001117
1118 /* Fixup the functions prologs */
1119
Alexandre Julliard329f0681996-04-14 13:21:20 +00001120 NE_FixupPrologs( pModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001121
1122 /* Make sure the usage count is 1 on the first loading of */
1123 /* the module, even if it contains circular DLL references */
1124
1125 pModule->count = 1;
1126 }
1127 else
1128 {
Alexandre Julliard329f0681996-04-14 13:21:20 +00001129 pModule = MODULE_GetPtr( hModule );
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001130 hPrevInstance = MODULE_GetInstance( hModule );
1131 hInstance = MODULE_CreateInstance( hModule, params );
1132 if (hInstance != hPrevInstance) /* not a library */
1133 NE_LoadSegment( hModule, pModule->dgroup );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001134 pModule->count++;
1135 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001136#else
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001137 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE));
1138 pModule = (NE_MODULE *)GlobalLock16( hModule );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001139 pModule->count = 1;
Alexandre Julliard329f0681996-04-14 13:21:20 +00001140 pModule->magic = NE_SIGNATURE;
1141 pModule->self = hModule;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001142 hPrevInstance = 0;
1143 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1144#endif /* WINELIB */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001145
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001146 /* Create a task for this instance */
1147
1148 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1149 {
1150 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1151 params->hEnvironment,
1152 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1153 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1154 }
1155
Alexandre Julliard2787be81995-05-22 18:23:01 +00001156 return hInstance;
1157}
1158
1159
1160/**********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +00001161 * FreeModule16 (KERNEL.46)
Alexandre Julliard2787be81995-05-22 18:23:01 +00001162 */
Alexandre Julliard3051b641996-07-05 17:14:13 +00001163BOOL16 FreeModule16( HMODULE16 hModule )
Alexandre Julliard2787be81995-05-22 18:23:01 +00001164{
1165 NE_MODULE *pModule;
1166
1167 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard329f0681996-04-14 13:21:20 +00001168 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001169
Alexandre Julliard3051b641996-07-05 17:14:13 +00001170 dprintf_module( stddeb, "FreeModule16: %s count %d\n",
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001171 MODULE_GetModuleName(hModule), pModule->count );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001172 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1173 return TRUE;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001174}
1175
1176
1177/**********************************************************************
1178 * GetModuleHandle (KERNEL.47)
1179 */
Alexandre Julliard3051b641996-07-05 17:14:13 +00001180HMODULE16 WIN16_GetModuleHandle( SEGPTR name )
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00001181{
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001182 if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00001183 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1184}
1185
Alexandre Julliard3051b641996-07-05 17:14:13 +00001186HMODULE16 GetModuleHandle( LPCSTR name )
Alexandre Julliard594997c1995-04-30 10:05:20 +00001187{
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001188 return MODULE_FindModule( name );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001189}
1190
1191
1192/**********************************************************************
1193 * GetModuleUsage (KERNEL.48)
1194 */
1195int GetModuleUsage( HANDLE hModule )
1196{
1197 NE_MODULE *pModule;
1198
1199 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard329f0681996-04-14 13:21:20 +00001200 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001201 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +00001202 hModule, pModule->count );
1203 return pModule->count;
1204}
1205
1206
1207/**********************************************************************
1208 * GetModuleFileName (KERNEL.49)
1209 */
1210int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1211{
1212 NE_MODULE *pModule;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001213
1214 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard329f0681996-04-14 13:21:20 +00001215 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliardd90840e1996-06-11 16:02:08 +00001216 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001217 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001218 return strlen(lpFileName);
1219}
1220
1221
Alexandre Julliard2787be81995-05-22 18:23:01 +00001222/***********************************************************************
1223 * LoadLibrary (KERNEL.95)
1224 */
1225HANDLE LoadLibrary( LPCSTR libname )
1226{
Alexandre Julliardade697e1995-11-26 13:59:11 +00001227#ifdef WINELIB
1228 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1229 WINELIB_UNIMP("LoadLibrary()");
1230 return (HANDLE)0;
1231#else
Alexandre Julliard2787be81995-05-22 18:23:01 +00001232 HANDLE handle;
1233
1234 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
Alexandre Julliardade697e1995-11-26 13:59:11 +00001235
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001236 /* This does not increment the module reference count, and will
1237 * therefore cause crashes on FreeLibrary calls.
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001238 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001239 */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001240 handle = LoadModule( libname, (LPVOID)-1 );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001241 if (handle == (HANDLE)2) /* file not found */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001242 {
1243 char buffer[256];
Alexandre Julliardd90840e1996-06-11 16:02:08 +00001244 lstrcpyn32A( buffer, libname, 252 );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001245 strcat( buffer, ".dll" );
1246 handle = LoadModule( buffer, (LPVOID)-1 );
1247 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001248 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001249 return handle;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001250#endif
Alexandre Julliard2787be81995-05-22 18:23:01 +00001251}
1252
1253
1254/***********************************************************************
1255 * FreeLibrary (KERNEL.96)
1256 */
1257void FreeLibrary( HANDLE handle )
1258{
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001259 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
Alexandre Julliard3051b641996-07-05 17:14:13 +00001260 FreeModule16( handle );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001261}
1262
1263
1264/***********************************************************************
1265 * WinExec (KERNEL.166)
1266 */
1267HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1268{
1269 LOADPARAMS params;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001270 HGLOBAL16 cmdShowHandle, cmdLineHandle;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001271 HANDLE handle;
1272 WORD *cmdShowPtr;
1273 char *p, *cmdline, filename[256];
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001274 static int use_load_module = 1;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001275
Alexandre Julliardd90840e1996-06-11 16:02:08 +00001276 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1277 return 8; /* Out of memory */
1278 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 )))
1279 {
1280 GlobalFree16( cmdShowHandle );
1281 return 8; /* Out of memory */
1282 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001283
1284 /* Store nCmdShow */
1285
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001286 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001287 cmdShowPtr[0] = 2;
1288 cmdShowPtr[1] = nCmdShow;
1289
1290 /* Build the filename and command-line */
1291
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001292 cmdline = (char *)GlobalLock16( cmdLineHandle );
Alexandre Julliardd90840e1996-06-11 16:02:08 +00001293 lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */);
Alexandre Julliard2787be81995-05-22 18:23:01 +00001294 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
Alexandre Julliardd90840e1996-06-11 16:02:08 +00001295 if (*p) lstrcpyn32A( cmdline, p + 1, 128 );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001296 else cmdline[0] = '\0';
1297 *p = '\0';
1298
1299 /* Now load the executable file */
1300
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001301 if (use_load_module)
Alexandre Julliard2787be81995-05-22 18:23:01 +00001302 {
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001303#ifdef WINELIB
1304 /* WINELIB: Use LoadModule() only for the program itself */
1305 use_load_module = 0;
1306 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1307#else
1308 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1309#endif /* WINELIB */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001310 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1311 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001312 params.reserved = 0;
1313 handle = LoadModule( filename, &params );
1314 if (handle == 2) /* file not found */
1315 {
1316 /* Check that the original file name did not have a suffix */
1317 p = strrchr(filename, '.');
1318 if (!p || (strchr(p, '/') && strchr(p, '\\')))
1319 {
1320 p = filename + strlen(filename);
1321 strcpy( p, ".exe" );
1322 handle = LoadModule( filename, &params );
1323 *p = '\0'; /* Remove extension */
1324 }
1325 }
1326 }
1327 else handle = 2;
1328
1329 if (handle < 32)
1330 {
1331 /* Try to start it as a unix program */
1332 if (!fork())
1333 {
1334 /* Child process */
1335 const char *unixfilename;
1336 const char *argv[256], **argptr;
1337 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1338 nCmdShow == SW_SHOWMINNOACTIVE);
1339
1340 /* get unixfilename */
1341 if (strchr(filename, '/') ||
1342 strchr(filename, ':') ||
1343 strchr(filename, '\\'))
1344 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1345 else unixfilename = filename;
1346
1347 if (unixfilename)
1348 {
1349 /* build argv */
1350 argptr = argv;
1351 if (iconic) *argptr++ = "-iconic";
1352 *argptr++ = unixfilename;
1353 p = cmdline;
1354 while (1)
1355 {
1356 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1357 if (!*p) break;
1358 *argptr++ = p;
1359 while (*p && *p != ' ' && *p != '\t') p++;
1360 }
1361 *argptr++ = 0;
1362
1363 /* Execute */
1364 execvp(argv[0], (char**)argv);
1365 }
1366
1367 /* Failed ! */
1368#ifdef WINELIB
1369 /* build argv */
1370 argptr = argv;
1371 *argptr++ = "wine";
1372 if (iconic) *argptr++ = "-iconic";
1373 *argptr++ = lpCmdLine;
1374 *argptr++ = 0;
1375
1376 /* Execute */
1377 execvp(argv[0] , (char**)argv);
1378
1379 /* Failed ! */
1380 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1381#endif
1382 exit(1);
1383 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001384 }
1385
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001386 GlobalFree16( cmdShowHandle );
1387 GlobalFree16( cmdLineHandle );
Alexandre Julliard902da691995-11-05 14:39:02 +00001388
1389#if 0
1390 if (handle < (HANDLE)32) /* Error? */
1391 return handle;
1392
1393/* FIXME: Yield never returns!
1394 We may want to run more applications or start the debugger
1395 before calling Yield. If we don't Yield will be called immdiately
1396 after returning. Why is it needed for Word anyway? */
1397 Yield(); /* program is executed immediately ....needed for word */
1398
1399#endif
Alexandre Julliard2787be81995-05-22 18:23:01 +00001400 return handle;
1401}
1402
1403
1404/***********************************************************************
Alexandre Julliardca22b331996-07-12 19:02:39 +00001405 * GetProcAddress16 (KERNEL.50)
Alexandre Julliard2787be81995-05-22 18:23:01 +00001406 */
Alexandre Julliardca22b331996-07-12 19:02:39 +00001407FARPROC16 GetProcAddress16( HMODULE16 hModule, SEGPTR name )
Alexandre Julliard2787be81995-05-22 18:23:01 +00001408{
1409 WORD ordinal;
Alexandre Julliardca22b331996-07-12 19:02:39 +00001410 FARPROC16 ret;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001411
1412 if (!hModule) hModule = GetCurrentTask();
1413 hModule = GetExePtr( hModule );
1414
1415 if (HIWORD(name) != 0)
1416 {
1417 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001418 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
Alexandre Julliard2787be81995-05-22 18:23:01 +00001419 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1420 }
1421 else
1422 {
1423 ordinal = LOWORD(name);
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001424 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
Alexandre Julliard2787be81995-05-22 18:23:01 +00001425 hModule, ordinal );
1426 }
Alexandre Julliardca22b331996-07-12 19:02:39 +00001427 if (!ordinal) return (FARPROC16)0;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001428
1429 ret = MODULE_GetEntryPoint( hModule, ordinal );
1430
Alexandre Julliardca22b331996-07-12 19:02:39 +00001431 dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1432 return ret;
1433}
1434
1435
1436/***********************************************************************
1437 * GetProcAddress32 (KERNEL32.257)
1438 */
1439FARPROC32 GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1440{
1441#ifndef WINELIB
1442 NE_MODULE *pModule;
1443
1444 hModule = GetExePtr( hModule );
1445 if (!(pModule = MODULE_GetPtr( hModule )))
1446 return (FARPROC32)0;
1447 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1448 return (FARPROC32)0;
1449 if (pModule->flags & NE_FFLAGS_BUILTIN)
1450 return BUILTIN_GetProcAddress32( pModule, function );
1451 return PE_FindExportedFunction( pModule->pe_module, function );
1452#else
1453 return NULL;
1454#endif
Alexandre Julliard2787be81995-05-22 18:23:01 +00001455}
1456
1457
Alexandre Julliardade697e1995-11-26 13:59:11 +00001458/**********************************************************************
1459 * GetExpWinVer (KERNEL.167)
1460 */
Alexandre Julliard3051b641996-07-05 17:14:13 +00001461WORD GetExpWinVer( HMODULE16 hModule )
Alexandre Julliardade697e1995-11-26 13:59:11 +00001462{
Alexandre Julliard329f0681996-04-14 13:21:20 +00001463 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1464 return pModule ? pModule->expected_version : 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001465}
1466
1467
Alexandre Julliard594997c1995-04-30 10:05:20 +00001468/**********************************************************************
1469 * ModuleFirst (TOOLHELP.59)
1470 */
Alexandre Julliard3051b641996-07-05 17:14:13 +00001471BOOL16 ModuleFirst( MODULEENTRY *lpme )
Alexandre Julliard594997c1995-04-30 10:05:20 +00001472{
1473 lpme->wNext = hFirstModule;
1474 return ModuleNext( lpme );
1475}
1476
1477
1478/**********************************************************************
1479 * ModuleNext (TOOLHELP.60)
1480 */
Alexandre Julliard3051b641996-07-05 17:14:13 +00001481BOOL16 ModuleNext( MODULEENTRY *lpme )
Alexandre Julliard594997c1995-04-30 10:05:20 +00001482{
1483 NE_MODULE *pModule;
1484
1485 if (!lpme->wNext) return FALSE;
Alexandre Julliard329f0681996-04-14 13:21:20 +00001486 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001487 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1488 MAX_MODULE_NAME );
1489 lpme->szModule[MAX_MODULE_NAME] = '\0';
1490 lpme->hModule = lpme->wNext;
1491 lpme->wcUsage = pModule->count;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +00001492 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001493 lpme->szExePath[MAX_PATH] = '\0';
1494 lpme->wNext = pModule->next;
1495 return TRUE;
1496}
1497
1498
1499/**********************************************************************
1500 * ModuleFindName (TOOLHELP.61)
1501 */
Alexandre Julliard3051b641996-07-05 17:14:13 +00001502BOOL16 ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
Alexandre Julliard594997c1995-04-30 10:05:20 +00001503{
1504 lpme->wNext = GetModuleHandle( name );
1505 return ModuleNext( lpme );
1506}
1507
1508
1509/**********************************************************************
1510 * ModuleFindHandle (TOOLHELP.62)
1511 */
Alexandre Julliard3051b641996-07-05 17:14:13 +00001512BOOL16 ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
Alexandre Julliard594997c1995-04-30 10:05:20 +00001513{
1514 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1515 lpme->wNext = hModule;
1516 return ModuleNext( lpme );
1517}