blob: e0474155f40d6501723c0fa5e2f3b69497588e39 [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 Julliard2787be81995-05-22 18:23:01 +000022#include "stackframe.h"
23#include "task.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000024#include "toolhelp.h"
25#include "stddebug.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000026#include "debug.h"
27
Alexandre Julliardff8331e1995-09-18 11:19:54 +000028#include "callback.h"
Alexandre Julliard902da691995-11-05 14:39:02 +000029#include "wine.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000030
Alexandre Julliard02ed4c21996-03-02 19:34:10 +000031extern HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
32
Alexandre Julliard594997c1995-04-30 10:05:20 +000033static HMODULE hFirstModule = 0;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +000034static HMODULE hCachedModule = 0; /* Module cached by MODULE_OpenFile */
Alexandre Julliard594997c1995-04-30 10:05:20 +000035
Alexandre Julliardade697e1995-11-26 13:59:11 +000036#ifndef WINELIB
Alexandre Julliard902da691995-11-05 14:39:02 +000037static HANDLE hInitialStack32 = 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +000038#endif
Alexandre Julliard594997c1995-04-30 10:05:20 +000039
40
41/***********************************************************************
Alexandre Julliard329f0681996-04-14 13:21:20 +000042 * MODULE_GetPtr
43 */
44NE_MODULE *MODULE_GetPtr( HMODULE hModule )
45{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000046 NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +000047 if (!pModule || (pModule->magic != NE_SIGNATURE) ||
48 (pModule->self != hModule)) return NULL;
49 return pModule;
50}
51
52
53/***********************************************************************
Alexandre Julliard8664b891996-04-05 14:58:24 +000054 * MODULE_DumpModule
Alexandre Julliard594997c1995-04-30 10:05:20 +000055 */
Alexandre Julliard8664b891996-04-05 14:58:24 +000056void MODULE_DumpModule( HMODULE hmodule )
Alexandre Julliard594997c1995-04-30 10:05:20 +000057{
58 int i, ordinal;
59 SEGTABLEENTRY *pSeg;
60 BYTE *pstr;
61 WORD *pword;
Alexandre Julliard329f0681996-04-14 13:21:20 +000062 NE_MODULE *pModule;
Alexandre Julliard594997c1995-04-30 10:05:20 +000063
Alexandre Julliard329f0681996-04-14 13:21:20 +000064 if (!(pModule = MODULE_GetPtr( hmodule )))
Alexandre Julliard8664b891996-04-05 14:58:24 +000065 {
66 fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
67 return;
68 }
69
Alexandre Julliard594997c1995-04-30 10:05:20 +000070 /* Dump the module info */
71
Alexandre Julliard59730ae1996-03-24 16:20:51 +000072 printf( "Module %04x:\n", hmodule );
Alexandre Julliard594997c1995-04-30 10:05:20 +000073 printf( "count=%d flags=%04x heap=%d stack=%d\n",
74 pModule->count, pModule->flags,
75 pModule->heap_size, pModule->stack_size );
76 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
77 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
78 pModule->seg_count, pModule->modref_count );
79 printf( "os_flags=%d swap_area=%d version=%04x\n",
80 pModule->os_flags, pModule->min_swap_area,
81 pModule->expected_version );
Alexandre Julliard8664b891996-04-05 14:58:24 +000082 if (pModule->flags & NE_FFLAGS_WIN32)
Alexandre Julliard329f0681996-04-14 13:21:20 +000083 printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
Alexandre Julliard594997c1995-04-30 10:05:20 +000084
85 /* Dump the file info */
86
Alexandre Julliard02ed4c21996-03-02 19:34:10 +000087 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
Alexandre Julliard594997c1995-04-30 10:05:20 +000088
89 /* Dump the segment table */
90
91 printf( "\nSegment table:\n" );
92 pSeg = NE_SEG_TABLE( pModule );
93 for (i = 0; i < pModule->seg_count; i++, pSeg++)
Alexandre Julliard59730ae1996-03-24 16:20:51 +000094 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +000095 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
96 pSeg->minsize, pSeg->selector );
97
98 /* Dump the resource table */
99
100 printf( "\nResource table:\n" );
101 if (pModule->res_table)
102 {
103 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
104 printf( "Alignment: %d\n", *pword++ );
105 while (*pword)
106 {
107 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
108 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
109 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
110 for (i = 0; i < ptr->count; i++, pname++)
111 printf( "offset=%d len=%d id=%04x\n",
112 pname->offset, pname->length, pname->id );
113 pword = (WORD *)pname;
114 }
115 }
116 else printf( "None\n" );
117
118 /* Dump the resident name table */
119
120 printf( "\nResident-name table:\n" );
121 pstr = (char *)pModule + pModule->name_table;
122 while (*pstr)
123 {
124 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
125 *(WORD *)(pstr + *pstr + 1) );
126 pstr += *pstr + 1 + sizeof(WORD);
127 }
128
129 /* Dump the module reference table */
130
131 printf( "\nModule ref table:\n" );
132 if (pModule->modref_table)
133 {
134 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
135 for (i = 0; i < pModule->modref_count; i++, pword++)
136 {
137 char *name = (char *)pModule + pModule->import_table + *pword;
138 printf( "%d: %04x -> '%*.*s'\n",
139 i, *pword, *name, *name, name + 1 );
140 }
141 }
142 else printf( "None\n" );
143
144 /* Dump the entry table */
145
146 printf( "\nEntry table:\n" );
147 pstr = (char *)pModule + pModule->entry_table;
148 ordinal = 1;
149 while (*pstr)
150 {
151 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
152 if (!pstr[1])
153 {
154 ordinal += *pstr;
155 pstr += 2;
156 }
157 else if ((BYTE)pstr[1] == 0xff) /* moveable */
158 {
159 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
160 for (i = 0; i < *pstr; i++, pe++)
161 printf( "%d: %02x:%04x (moveable)\n",
162 ordinal++, pe->seg_number, pe->offset );
163 pstr = (char *)pe;
164 }
165 else /* fixed */
166 {
167 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
168 for (i = 0; i < *pstr; i++, pe++)
169 printf( "%d: %04x (fixed)\n",
170 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
171 pstr = (char *)pe;
172 }
173 }
174
175 /* Dump the non-resident names table */
176
177 printf( "\nNon-resident names table:\n" );
178 if (pModule->nrname_handle)
179 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000180 pstr = (char *)GlobalLock16( pModule->nrname_handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000181 while (*pstr)
182 {
183 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
184 *(WORD *)(pstr + *pstr + 1) );
185 pstr += *pstr + 1 + sizeof(WORD);
186 }
187 }
188 printf( "\n" );
189}
190
191
192/***********************************************************************
Alexandre Julliard8664b891996-04-05 14:58:24 +0000193 * MODULE_WalkModules
194 *
195 * Walk the module list and print the modules.
196 */
197void MODULE_WalkModules(void)
198{
199 HMODULE hModule = hFirstModule;
200 fprintf( stderr, "Module Flags Name\n" );
201 while (hModule)
202 {
Alexandre Julliard329f0681996-04-14 13:21:20 +0000203 NE_MODULE *pModule = MODULE_GetPtr( hModule );
204 if (!pModule)
Alexandre Julliard8664b891996-04-05 14:58:24 +0000205 {
206 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
207 return;
208 }
209 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
210 *((char *)pModule + pModule->name_table),
211 (char *)pModule + pModule->name_table + 1 );
212 hModule = pModule->next;
213 }
214}
215
216
217/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000218 * MODULE_OpenFile
219 */
220int MODULE_OpenFile( HMODULE hModule )
221{
222 NE_MODULE *pModule;
223 char *name;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000224 const char *unixName;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000225
Alexandre Julliard594997c1995-04-30 10:05:20 +0000226 static int cachedfd = -1;
227
228 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000229 dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +0000230 hModule, hCachedModule, cachedfd );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000231 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000232 if (hCachedModule == hModule) return cachedfd;
233 close( cachedfd );
234 hCachedModule = hModule;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +0000235 name = NE_MODULE_NAME( pModule );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000236 if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
237 (cachedfd = open( unixName, O_RDONLY )) == -1)
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000238 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000239 name, hModule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000240 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
241 name, cachedfd );
242 return cachedfd;
243}
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000244
245
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000246/***********************************************************************
247 * MODULE_Ne2MemFlags
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000248 *
249 * This function translates NE segment flags to GlobalAlloc flags
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000250 */
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000251static WORD MODULE_Ne2MemFlags(WORD flags)
252{
253 WORD memflags = 0;
254#if 0
255 if (flags & NE_SEGFLAGS_DISCARDABLE)
256 memflags |= GMEM_DISCARDABLE;
257 if (flags & NE_SEGFLAGS_MOVEABLE ||
258 ( ! (flags & NE_SEGFLAGS_DATA) &&
259 ! (flags & NE_SEGFLAGS_LOADED) &&
260 ! (flags & NE_SEGFLAGS_ALLOCATED)
261 )
262 )
263 memflags |= GMEM_MOVEABLE;
264 memflags |= GMEM_ZEROINIT;
265#else
266 memflags = GMEM_ZEROINIT | GMEM_FIXED;
267 return memflags;
268#endif
269}
270
271/***********************************************************************
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000272 * MODULE_AllocateSegment (WPROCS.26)
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000273 */
274
275DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
276{
277 WORD size = wSize << wElem;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000278 HANDLE hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
279#ifdef WINELIB
280 return (DWORD)GlobalLock16(hMem);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000281#else
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000282 WORD selector = HIWORD(WIN16_GlobalLock16(hMem));
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000283 return MAKELONG(hMem, selector);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000284#endif
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000285}
Alexandre Julliard594997c1995-04-30 10:05:20 +0000286
287/***********************************************************************
288 * MODULE_CreateSegments
289 */
Alexandre Julliard902da691995-11-05 14:39:02 +0000290#ifndef WINELIB32
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000291static BOOL MODULE_CreateSegments( HMODULE hModule )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000292{
293 SEGTABLEENTRY *pSegment;
294 NE_MODULE *pModule;
295 int i, minsize;
296
Alexandre Julliard329f0681996-04-14 13:21:20 +0000297 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000298 pSegment = NE_SEG_TABLE( pModule );
299 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
300 {
301 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
302 if (i == pModule->ss) minsize += pModule->stack_size;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000303 /* The DGROUP is allocated by MODULE_CreateInstance */
304 if (i == pModule->dgroup) continue;
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000305 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
Alexandre Julliard594997c1995-04-30 10:05:20 +0000306 minsize, hModule,
307 !(pSegment->flags & NE_SEGFLAGS_DATA),
308 FALSE,
309 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
310 if (!pSegment->selector) return FALSE;
311 }
312
313 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
314 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
315 return TRUE;
316}
Alexandre Julliard902da691995-11-05 14:39:02 +0000317#endif
Alexandre Julliard594997c1995-04-30 10:05:20 +0000318
319
320/***********************************************************************
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000321 * MODULE_GetInstance
322 */
Alexandre Julliard902da691995-11-05 14:39:02 +0000323#ifndef WINELIB32
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000324HINSTANCE MODULE_GetInstance( HMODULE hModule )
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000325{
326 SEGTABLEENTRY *pSegment;
327 NE_MODULE *pModule;
328
Alexandre Julliard329f0681996-04-14 13:21:20 +0000329 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000330 if (pModule->dgroup == 0) return hModule;
331
332 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
333
334 return pSegment->selector;
335}
Alexandre Julliard902da691995-11-05 14:39:02 +0000336#endif
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000337
338
339/***********************************************************************
340 * MODULE_CreateInstance
341 */
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000342HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000343{
344 SEGTABLEENTRY *pSegment;
345 NE_MODULE *pModule;
346 int minsize;
347 HINSTANCE hNewInstance, hPrevInstance;
348
Alexandre Julliard329f0681996-04-14 13:21:20 +0000349 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000350 if (pModule->dgroup == 0) return hModule;
351
352 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
353 hPrevInstance = pSegment->selector;
354
355 /* if it's a library, create a new instance only the first time */
356 if (hPrevInstance)
357 {
358 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
359 if (params == (LOADPARAMS*)-1) return hPrevInstance;
360 }
361
362 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
363 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
364 minsize += pModule->heap_size;
365 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
366 minsize, hModule, FALSE, FALSE, FALSE );
367 if (!hNewInstance) return 0;
368 pSegment->selector = hNewInstance;
369 return hNewInstance;
370}
371
372
373/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000374 * MODULE_LoadExeHeader
375 */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000376static HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000377{
378 struct mz_header_s mz_header;
379 struct ne_header_s ne_header;
380 int size;
381 HMODULE hModule;
382 NE_MODULE *pModule;
383 BYTE *pData;
384 char *buffer, *fastload = NULL;
385 int fastload_offset = 0, fastload_length = 0;
386
387 /* Read a block from either the file or the fast-load area. */
388#define READ(offset,size,buffer) \
389 ((fastload && ((offset) >= fastload_offset) && \
390 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
391 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000392 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
393 FILE_Read( hFile, (buffer), (size) ) == (size)))
Alexandre Julliard594997c1995-04-30 10:05:20 +0000394
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000395 _llseek( hFile, 0, SEEK_SET );
396 if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000397 (mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000398
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000399 _llseek( hFile, mz_header.ne_offset, SEEK_SET );
400 if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000401 return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000402
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000403 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21; /* win32 exe */
404 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000405
406 /* We now have a valid NE header */
407
408 size = sizeof(NE_MODULE) +
409 /* loaded file info */
Alexandre Julliard02ed4c21996-03-02 19:34:10 +0000410 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
Alexandre Julliard594997c1995-04-30 10:05:20 +0000411 /* segment table */
412 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
413 /* resource table */
414 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
415 /* resident names table */
416 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
417 /* module ref table */
418 ne_header.n_mod_ref_tab * sizeof(WORD) +
419 /* imported names table */
420 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
421 /* entry table length */
422 ne_header.entry_tab_length;
423
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000424 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000425 if (!hModule) return (HMODULE)11; /* invalid exe */
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000426 FarSetOwner( hModule, hModule );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000427 pModule = (NE_MODULE *)GlobalLock16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000428 memcpy( pModule, &ne_header, sizeof(ne_header) );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000429 pModule->count = 0;
Alexandre Julliard329f0681996-04-14 13:21:20 +0000430 pModule->pe_module = NULL;
431 pModule->self = hModule;
432 pModule->self_loading_sel = 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000433 pData = (BYTE *)(pModule + 1);
434
Alexandre Julliard329f0681996-04-14 13:21:20 +0000435 /* Clear internal Wine flags in case they are set in the EXE file */
436
437 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
438
Alexandre Julliard594997c1995-04-30 10:05:20 +0000439 /* Read the fast-load area */
440
441 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
442 {
443 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
444 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
445 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
446 fastload_offset, fastload_length );
447 if ((fastload = (char *)malloc( fastload_length )) != NULL)
448 {
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000449 _llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET );
450 if (FILE_Read( hFile, fastload, fastload_length ) != fastload_length)
Alexandre Julliard594997c1995-04-30 10:05:20 +0000451 {
452 free( fastload );
453 fastload = NULL;
454 }
455 }
456 }
457
458 /* Store the filename information */
459
460 pModule->fileinfo = (int)pData - (int)pModule;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +0000461 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
462 memcpy( pData, ofs, size );
463 ((OFSTRUCT *)pData)->cBytes = size - 1;
464 pData += size;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000465
466 /* Get the segment table */
467
468 pModule->seg_table = (int)pData - (int)pModule;
469 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
470 if (buffer)
471 {
472 int i;
473 struct ne_segment_table_entry_s *pSeg;
474
475 if (!READ( ne_header.segment_tab_offset,
476 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000477 buffer )) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000478 pSeg = (struct ne_segment_table_entry_s *)buffer;
479 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
480 {
481 memcpy( pData, pSeg, sizeof(*pSeg) );
482 pData += sizeof(SEGTABLEENTRY);
483 }
484 free( buffer );
485 }
Alexandre Julliard329f0681996-04-14 13:21:20 +0000486 else
487 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000488 GlobalFree16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000489 return (HMODULE)11; /* invalid exe */
490 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000491
492 /* Get the resource table */
493
494 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
495 {
496 pModule->res_table = (int)pData - (int)pModule;
497 if (!READ(ne_header.resource_tab_offset,
498 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000499 pData )) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000500 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
501 }
502 else pModule->res_table = 0; /* No resource table */
503
504 /* Get the resident names table */
505
506 pModule->name_table = (int)pData - (int)pModule;
507 if (!READ( ne_header.rname_tab_offset,
508 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
Alexandre Julliard329f0681996-04-14 13:21:20 +0000509 pData ))
510 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000511 GlobalFree16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000512 return (HMODULE)11; /* invalid exe */
513 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000514 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
515
516 /* Get the module references table */
517
518 if (ne_header.n_mod_ref_tab > 0)
519 {
520 pModule->modref_table = (int)pData - (int)pModule;
521 if (!READ( ne_header.moduleref_tab_offset,
522 ne_header.n_mod_ref_tab * sizeof(WORD),
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000523 pData )) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000524 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
525 }
526 else pModule->modref_table = 0; /* No module references */
527
528 /* Get the imported names table */
529
530 pModule->import_table = (int)pData - (int)pModule;
531 if (!READ( ne_header.iname_tab_offset,
532 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
Alexandre Julliard329f0681996-04-14 13:21:20 +0000533 pData ))
534 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000535 GlobalFree16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000536 return (HMODULE)11; /* invalid exe */
537 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000538 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
539
540 /* Get the entry table */
541
542 pModule->entry_table = (int)pData - (int)pModule;
543 if (!READ( ne_header.entry_tab_offset,
544 ne_header.entry_tab_length,
Alexandre Julliard329f0681996-04-14 13:21:20 +0000545 pData ))
546 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000547 GlobalFree16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000548 return (HMODULE)11; /* invalid exe */
549 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000550 pData += ne_header.entry_tab_length;
551
552 /* Get the non-resident names table */
553
554 if (ne_header.nrname_tab_length)
555 {
556 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
557 hModule, FALSE, FALSE, FALSE );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000558 if (!pModule->nrname_handle)
559 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000560 GlobalFree16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000561 return (HMODULE)11; /* invalid exe */
562 }
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000563 buffer = GlobalLock16( pModule->nrname_handle );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000564 _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
565 if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length )
Alexandre Julliard329f0681996-04-14 13:21:20 +0000566 != ne_header.nrname_tab_length)
567 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000568 GlobalFree16( pModule->nrname_handle );
569 GlobalFree16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000570 return (HMODULE)11; /* invalid exe */
571 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000572 }
573 else pModule->nrname_handle = 0;
574
Alexandre Julliard2787be81995-05-22 18:23:01 +0000575 /* Allocate a segment for the implicitly-loaded DLLs */
576
577 if (pModule->modref_count)
578 {
579 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
580 (pModule->modref_count+1)*sizeof(HMODULE),
581 hModule, FALSE, FALSE, FALSE );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000582 if (!pModule->dlls_to_init)
583 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000584 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
585 GlobalFree16( hModule );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000586 return (HMODULE)11; /* invalid exe */
587 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000588 }
589 else pModule->dlls_to_init = 0;
590
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000591 MODULE_RegisterModule( pModule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000592 return hModule;
Alexandre Julliard329f0681996-04-14 13:21:20 +0000593#undef READ
Alexandre Julliard594997c1995-04-30 10:05:20 +0000594}
595
596
597/***********************************************************************
598 * MODULE_GetOrdinal
599 *
600 * Lookup the ordinal for a given name.
601 */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000602WORD MODULE_GetOrdinal( HMODULE hModule, const char *name )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000603{
604 char buffer[256], *cpnt;
605 BYTE len;
606 NE_MODULE *pModule;
607
Alexandre Julliard329f0681996-04-14 13:21:20 +0000608 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000609
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000610 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +0000611 hModule, name );
612
613 /* First handle names of the form '#xxxx' */
614
615 if (name[0] == '#') return atoi( name + 1 );
616
617 /* Now copy and uppercase the string */
618
619 strcpy( buffer, name );
620 AnsiUpper( buffer );
621 len = strlen( buffer );
622
623 /* First search the resident names */
624
625 cpnt = (char *)pModule + pModule->name_table;
626
627 /* Skip the first entry (module name) */
628 cpnt += *cpnt + 1 + sizeof(WORD);
629 while (*cpnt)
630 {
Alexandre Julliard594997c1995-04-30 10:05:20 +0000631 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
632 {
633 dprintf_module( stddeb, " Found: ordinal=%d\n",
634 *(WORD *)(cpnt + *cpnt + 1) );
635 return *(WORD *)(cpnt + *cpnt + 1);
636 }
637 cpnt += *cpnt + 1 + sizeof(WORD);
638 }
639
640 /* Now search the non-resident names table */
641
642 if (!pModule->nrname_handle) return 0; /* No non-resident table */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000643 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000644
645 /* Skip the first entry (module description string) */
646 cpnt += *cpnt + 1 + sizeof(WORD);
647 while (*cpnt)
648 {
Alexandre Julliard594997c1995-04-30 10:05:20 +0000649 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
650 {
651 dprintf_module( stddeb, " Found: ordinal=%d\n",
652 *(WORD *)(cpnt + *cpnt + 1) );
653 return *(WORD *)(cpnt + *cpnt + 1);
654 }
655 cpnt += *cpnt + 1 + sizeof(WORD);
656 }
657 return 0;
658}
659
660
661/***********************************************************************
662 * MODULE_GetEntryPoint
663 *
664 * Return the entry point for a given ordinal.
665 */
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000666SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000667{
668 NE_MODULE *pModule;
669 WORD curOrdinal = 1;
670 BYTE *p;
671 WORD sel, offset;
672
Alexandre Julliard329f0681996-04-14 13:21:20 +0000673 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000674
Alexandre Julliard594997c1995-04-30 10:05:20 +0000675 p = (BYTE *)pModule + pModule->entry_table;
676 while (*p && (curOrdinal + *p <= ordinal))
677 {
678 /* Skipping this bundle */
679 curOrdinal += *p;
680 switch(p[1])
681 {
682 case 0: p += 2; break; /* unused */
683 case 0xff: p += 2 + *p * 6; break; /* moveable */
684 default: p += 2 + *p * 3; break; /* fixed */
685 }
686 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000687 if (!*p) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000688
689 switch(p[1])
690 {
691 case 0: /* unused */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000692 return 0;
693 case 0xff: /* moveable */
694 p += 2 + 6 * (ordinal - curOrdinal);
695 sel = p[3];
696 offset = *(WORD *)(p + 4);
697 break;
698 default: /* fixed */
699 sel = p[1];
700 p += 2 + 3 * (ordinal - curOrdinal);
701 offset = *(WORD *)(p + 1);
702 break;
703 }
704
Alexandre Julliard594997c1995-04-30 10:05:20 +0000705 if (sel == 0xfe) sel = 0xffff; /* constant entry */
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000706 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000707 return PTR_SEG_OFF_TO_SEGPTR( sel, offset );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000708}
709
710
711/***********************************************************************
Alexandre Julliard2787be81995-05-22 18:23:01 +0000712 * MODULE_SetEntryPoint
713 *
714 * Change the value of an entry point. Use with caution!
715 * It can only change the offset value, not the selector.
716 */
717BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset )
718{
719 NE_MODULE *pModule;
720 WORD curOrdinal = 1;
721 BYTE *p;
722
Alexandre Julliard329f0681996-04-14 13:21:20 +0000723 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000724
725 p = (BYTE *)pModule + pModule->entry_table;
726 while (*p && (curOrdinal + *p <= ordinal))
727 {
728 /* Skipping this bundle */
729 curOrdinal += *p;
730 switch(p[1])
731 {
732 case 0: p += 2; break; /* unused */
733 case 0xff: p += 2 + *p * 6; break; /* moveable */
734 default: p += 2 + *p * 3; break; /* fixed */
735 }
736 }
737 if (!*p) return FALSE;
738
739 switch(p[1])
740 {
741 case 0: /* unused */
742 return FALSE;
743 case 0xff: /* moveable */
744 p += 2 + 6 * (ordinal - curOrdinal);
745 *(WORD *)(p + 4) = offset;
746 break;
747 default: /* fixed */
748 p += 2 + 3 * (ordinal - curOrdinal);
749 *(WORD *)(p + 1) = offset;
750 break;
751 }
752 return TRUE;
753}
754
755
756/***********************************************************************
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000757 * MODULE_GetWndProcEntry16 (not a Windows API function)
758 *
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000759 * Return an entry point from the WPROCS dll.
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000760 */
761#ifndef WINELIB
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000762FARPROC16 MODULE_GetWndProcEntry16( const char *name )
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000763{
764 WORD ordinal;
765 static HMODULE hModule = 0;
766
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 );
769 return MODULE_GetEntryPoint( hModule, ordinal );
770}
771#endif
772
773
774/***********************************************************************
775 * MODULE_GetWndProcEntry32 (not a Windows API function)
776 *
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000777 * Return an entry point from the WPROCS32 dll.
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000778 */
779#ifndef WINELIB
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000780FARPROC32 MODULE_GetWndProcEntry32( const char *name )
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000781{
782 static HMODULE hModule = 0;
783
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000784 if (!hModule) hModule = GetModuleHandle( "WPROCS32" );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000785 return PE_GetProcAddress( hModule, name );
786}
787#endif
788
789
790/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000791 * MODULE_GetModuleName
792 */
793LPSTR MODULE_GetModuleName( HMODULE hModule )
794{
795 NE_MODULE *pModule;
796 BYTE *p, len;
797 static char buffer[10];
798
Alexandre Julliard329f0681996-04-14 13:21:20 +0000799 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000800 p = (BYTE *)pModule + pModule->name_table;
Alexandre Julliard902da691995-11-05 14:39:02 +0000801 len = MIN( *p, 8 );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000802 memcpy( buffer, p + 1, len );
803 buffer[len] = '\0';
804 return buffer;
805}
806
807
808/**********************************************************************
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000809 * MODULE_RegisterModule
810 */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000811void MODULE_RegisterModule( NE_MODULE *pModule )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000812{
Alexandre Julliard329f0681996-04-14 13:21:20 +0000813 pModule->next = hFirstModule;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000814 hFirstModule = pModule->self;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000815}
816
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000817
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000818/**********************************************************************
Alexandre Julliard2787be81995-05-22 18:23:01 +0000819 * MODULE_FindModule
820 *
821 * Find a module from a path name.
822 */
823HMODULE MODULE_FindModule( LPCSTR path )
824{
825 HMODULE hModule = hFirstModule;
826 LPCSTR filename, dotptr, modulepath, modulename;
827 BYTE len, *name_table;
828
829 if (!(filename = strrchr( path, '\\' ))) filename = path;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000830 else filename++;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000831 if ((dotptr = strrchr( filename, '.' )) != NULL)
832 len = (BYTE)(dotptr - filename);
833 else len = strlen( filename );
834
835 while(hModule)
836 {
Alexandre Julliard329f0681996-04-14 13:21:20 +0000837 NE_MODULE *pModule = MODULE_GetPtr( hModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000838 if (!pModule) break;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +0000839 modulepath = NE_MODULE_NAME(pModule);
Alexandre Julliard2787be81995-05-22 18:23:01 +0000840 if (!(modulename = strrchr( modulepath, '\\' )))
841 modulename = modulepath;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000842 else modulename++;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000843 if (!lstrcmpi( modulename, filename )) return hModule;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000844
845 name_table = (BYTE *)pModule + pModule->name_table;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000846 if ((*name_table == len) && !lstrncmpi(filename, name_table+1, len))
Alexandre Julliard2787be81995-05-22 18:23:01 +0000847 return hModule;
848 hModule = pModule->next;
849 }
850 return 0;
851}
852
853
854/**********************************************************************
855 * MODULE_FreeModule
856 *
857 * Remove a module from memory.
858 */
859static void MODULE_FreeModule( HMODULE hModule )
860{
861 HMODULE *hPrevModule;
862 NE_MODULE *pModule;
863 SEGTABLEENTRY *pSegment;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000864 HMODULE *pModRef;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000865 int i;
866
Alexandre Julliard329f0681996-04-14 13:21:20 +0000867 if (!(pModule = MODULE_GetPtr( hModule ))) return;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000868 if (pModule->flags & NE_FFLAGS_BUILTIN)
869 return; /* Can't free built-in module */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000870
871 /* FIXME: should call the exit code for the library here */
872
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000873 /* Free the objects owned by the module */
874
875 HOOK_FreeModuleHooks( hModule );
876 CLASS_FreeModuleClasses( hModule );
877
Alexandre Julliard329f0681996-04-14 13:21:20 +0000878 /* Clear magic number just in case */
879
880 pModule->magic = pModule->self = 0;
881
Alexandre Julliard2787be81995-05-22 18:23:01 +0000882 /* Remove it from the linked list */
883
884 hPrevModule = &hFirstModule;
885 while (*hPrevModule && (*hPrevModule != hModule))
886 {
Alexandre Julliard329f0681996-04-14 13:21:20 +0000887 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000888 }
889 if (*hPrevModule) *hPrevModule = pModule->next;
890
891 /* Free all the segments */
892
893 pSegment = NE_SEG_TABLE( pModule );
894 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
895 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000896 GlobalFree16( pSegment->selector );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000897 }
898
899 /* Free the referenced modules */
900
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000901 pModRef = (HMODULE*)NE_MODULE_TABLE( pModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000902 for (i = 0; i < pModule->modref_count; i++, pModRef++)
903 {
904 FreeModule( *pModRef );
905 }
906
907 /* Free the module storage */
908
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000909 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
910 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
911 GlobalFree16( hModule );
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000912
913 /* Remove module from cache */
914
915 if (hCachedModule == hModule) hCachedModule = 0;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000916}
917
918
919/**********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000920 * LoadModule (KERNEL.45)
921 */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000922HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000923{
Alexandre Julliard2787be81995-05-22 18:23:01 +0000924 HMODULE hModule;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000925 HANDLE hInstance, hPrevInstance;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000926 NE_MODULE *pModule;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000927 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
Alexandre Julliardade697e1995-11-26 13:59:11 +0000928#ifndef WINELIB
Alexandre Julliard2787be81995-05-22 18:23:01 +0000929 WORD *pModRef, *pDLLs;
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000930 HFILE hFile;
931 int i;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000932
933 hModule = MODULE_FindModule( name );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000934
Alexandre Julliard2787be81995-05-22 18:23:01 +0000935 if (!hModule) /* We have to load the module */
936 {
937 OFSTRUCT ofs;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000938
939 /* Try to load the built-in first if not disabled */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000940 if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000941
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000942 if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000943 {
944 /* Now try the built-in even if disabled */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000945 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000946 {
947 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
948 return hModule;
949 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000950 return 2; /* File not found */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000951 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000952
953 /* Create the module structure */
954
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000955 hModule = MODULE_LoadExeHeader( hFile, &ofs );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000956 if (hModule < 32)
Alexandre Julliard2787be81995-05-22 18:23:01 +0000957 {
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000958 /* FIXME: Hack because PE_LoadModule is recursive */
959 int fd = dup( FILE_GetUnixHandle(hFile) );
960 _lclose( hFile );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000961 if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000962 close( fd );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000963 if (hModule < 32)
964 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
965 name, hModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000966 return hModule;
967 }
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +0000968 _lclose( hFile );
Alexandre Julliard329f0681996-04-14 13:21:20 +0000969 pModule = MODULE_GetPtr( hModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000970
971 /* Allocate the segments for this module */
972
973 MODULE_CreateSegments( hModule );
974
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000975 hPrevInstance = 0;
976 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
977
Alexandre Julliard2787be81995-05-22 18:23:01 +0000978 /* Load the referenced DLLs */
979
980 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000981 pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000982 for (i = 0; i < pModule->modref_count; i++, pModRef++)
983 {
984 char buffer[256];
985 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
986 memcpy( buffer, pstr + 1, *pstr );
987 strcpy( buffer + *pstr, ".dll" );
988 dprintf_module( stddeb, "Loading '%s'\n", buffer );
989 if (!(*pModRef = MODULE_FindModule( buffer )))
990 {
991 /* If the DLL is not loaded yet, load it and store */
992 /* its handle in the list of DLLs to initialize. */
993 HMODULE hDLL;
994
995 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
996 {
997 char *p;
998
999 /* Try with prepending the path of the current module */
1000 GetModuleFileName( hModule, buffer, 256 );
1001 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1002 memcpy( p + 1, pstr + 1, *pstr );
1003 strcpy( p + 1 + *pstr, ".dll" );
1004 hDLL = LoadModule( buffer, (LPVOID)-1 );
1005 }
1006 if (hDLL < 32)
1007 {
1008 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1009 buffer, name, hDLL );
1010 return 2; /* file not found */
1011 }
1012 *pModRef = GetExePtr( hDLL );
1013 *pDLLs++ = *pModRef;
1014 }
1015 else /* Increment the reference count of the DLL */
1016 {
Alexandre Julliard329f0681996-04-14 13:21:20 +00001017 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001018 if (pOldDLL) pOldDLL->count++;
1019 }
1020 }
1021
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001022 /* Load the segments */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001023
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001024 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1025 {
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +00001026 int fd;
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001027 /* Handle self loading modules */
1028 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1029 SELFLOADHEADER *selfloadheader;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001030 HMODULE hselfload = GetModuleHandle("WPROCS");
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001031 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1032 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1033 "Support for self-loading modules is very experimental\n",
1034 *((BYTE*)pModule + pModule->name_table),
1035 *((BYTE*)pModule + pModule->name_table),
1036 (char *)pModule + pModule->name_table + 1);
1037 NE_LoadSegment( hModule, 1 );
1038 selfloadheader = (SELFLOADHEADER *)
1039 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1040 selfloadheader->EntryAddrProc =
1041 MODULE_GetEntryPoint(hselfload,27);
1042 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1043 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1044 pModule->self_loading_sel = GlobalHandleToSel(
1045 GLOBAL_Alloc (GMEM_ZEROINIT,
1046 0xFF00, hModule, FALSE, FALSE, FALSE)
1047 );
1048 oldss = IF1632_Saved16_ss;
1049 oldsp = IF1632_Saved16_sp;
1050 IF1632_Saved16_ss = pModule->self_loading_sel;
1051 IF1632_Saved16_sp = 0xFF00;
Alexandre Julliard902da691995-11-05 14:39:02 +00001052 if (!IF1632_Stack32_base) {
1053 STACK32FRAME* frame32;
1054 char *stack32Top;
1055 /* Setup an initial 32 bit stack frame */
1056 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1057 hModule, FALSE, FALSE,
1058 FALSE );
1059
1060 /* Create the 32-bit stack frame */
1061
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001062 *(DWORD *)GlobalLock16(hInitialStack32) = 0xDEADBEEF;
1063 stack32Top = (char*)GlobalLock16(hInitialStack32) +
Alexandre Julliard902da691995-11-05 14:39:02 +00001064 0x10000;
1065 frame32 = (STACK32FRAME *)stack32Top - 1;
1066 frame32->saved_esp = (DWORD)stack32Top;
1067 frame32->edi = 0;
1068 frame32->esi = 0;
1069 frame32->edx = 0;
1070 frame32->ecx = 0;
1071 frame32->ebx = 0;
1072 frame32->ebp = 0;
1073 frame32->retaddr = 0;
1074 frame32->codeselector = WINE_CODE_SELECTOR;
1075 /* pTask->esp = (DWORD)frame32; */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001076 IF1632_Stack32_base = WIN16_GlobalLock16(hInitialStack32);
Alexandre Julliard902da691995-11-05 14:39:02 +00001077
1078 }
Alexandre Julliardd2e1c1a1996-03-09 16:12:43 +00001079 /* FIXME: we probably need a DOS handle here */
1080 fd = MODULE_OpenFile( hModule );
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001081 CallTo16_word_ww (selfloadheader->BootApp,
1082 pModule->self_loading_sel, hModule, fd);
1083 /* some BootApp procs overwrite the selector of dgroup */
1084 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1085 IF1632_Saved16_ss = oldss;
1086 IF1632_Saved16_sp = oldsp;
1087 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
Alexandre Julliard902da691995-11-05 14:39:02 +00001088 if (hInitialStack32){
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001089 GlobalFree16(hInitialStack32);
Alexandre Julliard902da691995-11-05 14:39:02 +00001090 IF1632_Stack32_base = hInitialStack32 = 0;
1091 }
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001092 }
1093 else
1094 {
1095 for (i = 1; i <= pModule->seg_count; i++)
1096 NE_LoadSegment( hModule, i );
1097 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001098
1099 /* Fixup the functions prologs */
1100
Alexandre Julliard329f0681996-04-14 13:21:20 +00001101 NE_FixupPrologs( pModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001102
1103 /* Make sure the usage count is 1 on the first loading of */
1104 /* the module, even if it contains circular DLL references */
1105
1106 pModule->count = 1;
1107 }
1108 else
1109 {
Alexandre Julliard329f0681996-04-14 13:21:20 +00001110 pModule = MODULE_GetPtr( hModule );
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001111 hPrevInstance = MODULE_GetInstance( hModule );
1112 hInstance = MODULE_CreateInstance( hModule, params );
1113 if (hInstance != hPrevInstance) /* not a library */
1114 NE_LoadSegment( hModule, pModule->dgroup );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001115 pModule->count++;
1116 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001117#else
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001118 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE));
1119 pModule = (NE_MODULE *)GlobalLock16( hModule );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001120 pModule->count = 1;
Alexandre Julliard329f0681996-04-14 13:21:20 +00001121 pModule->magic = NE_SIGNATURE;
1122 pModule->self = hModule;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001123 hPrevInstance = 0;
1124 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1125#endif /* WINELIB */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001126
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001127 /* Create a task for this instance */
1128
1129 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1130 {
1131 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1132 params->hEnvironment,
1133 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1134 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1135 }
1136
Alexandre Julliard2787be81995-05-22 18:23:01 +00001137 return hInstance;
1138}
1139
1140
1141/**********************************************************************
1142 * FreeModule (KERNEL.46)
1143 */
1144BOOL FreeModule( HANDLE hModule )
1145{
1146 NE_MODULE *pModule;
1147
1148 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard329f0681996-04-14 13:21:20 +00001149 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001150
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001151 dprintf_module( stddeb, "FreeModule: %s count %d\n",
1152 MODULE_GetModuleName(hModule), pModule->count );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001153 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1154 return TRUE;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001155}
1156
1157
1158/**********************************************************************
1159 * GetModuleHandle (KERNEL.47)
1160 */
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00001161HMODULE WIN16_GetModuleHandle( SEGPTR name )
1162{
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001163 if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00001164 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1165}
1166
Alexandre Julliard594997c1995-04-30 10:05:20 +00001167HMODULE GetModuleHandle( LPCSTR name )
1168{
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001169 return MODULE_FindModule( name );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001170}
1171
1172
1173/**********************************************************************
1174 * GetModuleUsage (KERNEL.48)
1175 */
1176int GetModuleUsage( HANDLE hModule )
1177{
1178 NE_MODULE *pModule;
1179
1180 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard329f0681996-04-14 13:21:20 +00001181 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001182 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +00001183 hModule, pModule->count );
1184 return pModule->count;
1185}
1186
1187
1188/**********************************************************************
1189 * GetModuleFileName (KERNEL.49)
1190 */
1191int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1192{
1193 NE_MODULE *pModule;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001194
1195 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard329f0681996-04-14 13:21:20 +00001196 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +00001197 lstrcpyn( lpFileName, NE_MODULE_NAME(pModule), nSize );
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001198 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001199 return strlen(lpFileName);
1200}
1201
1202
Alexandre Julliard2787be81995-05-22 18:23:01 +00001203/***********************************************************************
1204 * LoadLibrary (KERNEL.95)
1205 */
1206HANDLE LoadLibrary( LPCSTR libname )
1207{
Alexandre Julliardade697e1995-11-26 13:59:11 +00001208#ifdef WINELIB
1209 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1210 WINELIB_UNIMP("LoadLibrary()");
1211 return (HANDLE)0;
1212#else
Alexandre Julliard2787be81995-05-22 18:23:01 +00001213 HANDLE handle;
1214
1215 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
Alexandre Julliardade697e1995-11-26 13:59:11 +00001216
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001217 /* This does not increment the module reference count, and will
1218 * therefore cause crashes on FreeLibrary calls.
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001219 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001220 */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001221 handle = LoadModule( libname, (LPVOID)-1 );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001222 if (handle == (HANDLE)2) /* file not found */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001223 {
1224 char buffer[256];
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001225 lstrcpyn( buffer, libname, 252 );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001226 strcat( buffer, ".dll" );
1227 handle = LoadModule( buffer, (LPVOID)-1 );
1228 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001229 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001230 return handle;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001231#endif
Alexandre Julliard2787be81995-05-22 18:23:01 +00001232}
1233
1234
1235/***********************************************************************
1236 * FreeLibrary (KERNEL.96)
1237 */
1238void FreeLibrary( HANDLE handle )
1239{
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001240 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001241 FreeModule( handle );
1242}
1243
1244
1245/***********************************************************************
1246 * WinExec (KERNEL.166)
1247 */
1248HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1249{
1250 LOADPARAMS params;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001251 HGLOBAL16 cmdShowHandle, cmdLineHandle;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001252 HANDLE handle;
1253 WORD *cmdShowPtr;
1254 char *p, *cmdline, filename[256];
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001255 static int use_load_module = 1;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001256
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001257 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) ))) return 0;
1258 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 ))) return 0;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001259
1260 /* Store nCmdShow */
1261
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001262 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001263 cmdShowPtr[0] = 2;
1264 cmdShowPtr[1] = nCmdShow;
1265
1266 /* Build the filename and command-line */
1267
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001268 cmdline = (char *)GlobalLock16( cmdLineHandle );
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001269 lstrcpyn( filename, lpCmdLine, sizeof(filename) - 4 /* for extension */ );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001270 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001271 if (*p) lstrcpyn( cmdline, p + 1, 128 );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001272 else cmdline[0] = '\0';
1273 *p = '\0';
1274
1275 /* Now load the executable file */
1276
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001277 if (use_load_module)
Alexandre Julliard2787be81995-05-22 18:23:01 +00001278 {
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001279#ifdef WINELIB
1280 /* WINELIB: Use LoadModule() only for the program itself */
1281 use_load_module = 0;
1282 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1283#else
1284 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1285#endif /* WINELIB */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001286 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1287 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001288 params.reserved = 0;
1289 handle = LoadModule( filename, &params );
1290 if (handle == 2) /* file not found */
1291 {
1292 /* Check that the original file name did not have a suffix */
1293 p = strrchr(filename, '.');
1294 if (!p || (strchr(p, '/') && strchr(p, '\\')))
1295 {
1296 p = filename + strlen(filename);
1297 strcpy( p, ".exe" );
1298 handle = LoadModule( filename, &params );
1299 *p = '\0'; /* Remove extension */
1300 }
1301 }
1302 }
1303 else handle = 2;
1304
1305 if (handle < 32)
1306 {
1307 /* Try to start it as a unix program */
1308 if (!fork())
1309 {
1310 /* Child process */
1311 const char *unixfilename;
1312 const char *argv[256], **argptr;
1313 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1314 nCmdShow == SW_SHOWMINNOACTIVE);
1315
1316 /* get unixfilename */
1317 if (strchr(filename, '/') ||
1318 strchr(filename, ':') ||
1319 strchr(filename, '\\'))
1320 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1321 else unixfilename = filename;
1322
1323 if (unixfilename)
1324 {
1325 /* build argv */
1326 argptr = argv;
1327 if (iconic) *argptr++ = "-iconic";
1328 *argptr++ = unixfilename;
1329 p = cmdline;
1330 while (1)
1331 {
1332 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1333 if (!*p) break;
1334 *argptr++ = p;
1335 while (*p && *p != ' ' && *p != '\t') p++;
1336 }
1337 *argptr++ = 0;
1338
1339 /* Execute */
1340 execvp(argv[0], (char**)argv);
1341 }
1342
1343 /* Failed ! */
1344#ifdef WINELIB
1345 /* build argv */
1346 argptr = argv;
1347 *argptr++ = "wine";
1348 if (iconic) *argptr++ = "-iconic";
1349 *argptr++ = lpCmdLine;
1350 *argptr++ = 0;
1351
1352 /* Execute */
1353 execvp(argv[0] , (char**)argv);
1354
1355 /* Failed ! */
1356 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1357#endif
1358 exit(1);
1359 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001360 }
1361
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001362 GlobalFree16( cmdShowHandle );
1363 GlobalFree16( cmdLineHandle );
Alexandre Julliard902da691995-11-05 14:39:02 +00001364
1365#if 0
1366 if (handle < (HANDLE)32) /* Error? */
1367 return handle;
1368
1369/* FIXME: Yield never returns!
1370 We may want to run more applications or start the debugger
1371 before calling Yield. If we don't Yield will be called immdiately
1372 after returning. Why is it needed for Word anyway? */
1373 Yield(); /* program is executed immediately ....needed for word */
1374
1375#endif
Alexandre Julliard2787be81995-05-22 18:23:01 +00001376 return handle;
1377}
1378
1379
1380/***********************************************************************
1381 * GetProcAddress (KERNEL.50)
1382 */
1383FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
1384{
1385 WORD ordinal;
1386 SEGPTR ret;
1387
1388 if (!hModule) hModule = GetCurrentTask();
1389 hModule = GetExePtr( hModule );
1390
1391 if (HIWORD(name) != 0)
1392 {
1393 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001394 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
Alexandre Julliard2787be81995-05-22 18:23:01 +00001395 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1396 }
1397 else
1398 {
1399 ordinal = LOWORD(name);
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001400 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
Alexandre Julliard2787be81995-05-22 18:23:01 +00001401 hModule, ordinal );
1402 }
1403 if (!ordinal) return (FARPROC)0;
1404
1405 ret = MODULE_GetEntryPoint( hModule, ordinal );
1406
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001407 dprintf_module( stddeb, "GetProcAddress: returning %08lx\n", (DWORD)ret );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001408 return (FARPROC)ret;
1409}
1410
1411
Alexandre Julliardade697e1995-11-26 13:59:11 +00001412/**********************************************************************
1413 * GetExpWinVer (KERNEL.167)
1414 */
1415WORD GetExpWinVer( HMODULE hModule )
1416{
Alexandre Julliard329f0681996-04-14 13:21:20 +00001417 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1418 return pModule ? pModule->expected_version : 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001419}
1420
1421
Alexandre Julliard594997c1995-04-30 10:05:20 +00001422/**********************************************************************
1423 * ModuleFirst (TOOLHELP.59)
1424 */
1425BOOL ModuleFirst( MODULEENTRY *lpme )
1426{
1427 lpme->wNext = hFirstModule;
1428 return ModuleNext( lpme );
1429}
1430
1431
1432/**********************************************************************
1433 * ModuleNext (TOOLHELP.60)
1434 */
1435BOOL ModuleNext( MODULEENTRY *lpme )
1436{
1437 NE_MODULE *pModule;
1438
1439 if (!lpme->wNext) return FALSE;
Alexandre Julliard329f0681996-04-14 13:21:20 +00001440 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001441 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1442 MAX_MODULE_NAME );
1443 lpme->szModule[MAX_MODULE_NAME] = '\0';
1444 lpme->hModule = lpme->wNext;
1445 lpme->wcUsage = pModule->count;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +00001446 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001447 lpme->szExePath[MAX_PATH] = '\0';
1448 lpme->wNext = pModule->next;
1449 return TRUE;
1450}
1451
1452
1453/**********************************************************************
1454 * ModuleFindName (TOOLHELP.61)
1455 */
1456BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1457{
1458 lpme->wNext = GetModuleHandle( name );
1459 return ModuleNext( lpme );
1460}
1461
1462
1463/**********************************************************************
1464 * ModuleFindHandle (TOOLHELP.62)
1465 */
1466BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
1467{
1468 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1469 lpme->wNext = hModule;
1470 return ModuleNext( lpme );
1471}