blob: a3f46154928e20be2155b61f82926444f204df78 [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{
46 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
47 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 {
180 pstr = (char *)GlobalLock( pModule->nrname_handle );
181 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 Julliardaf0bae51995-10-03 17:06:08 +0000278 HANDLE hMem = GlobalAlloc( MODULE_Ne2MemFlags(wFlags), size);
279#ifdef WINELIB32
280 return (DWORD)GlobalLock(hMem);
281#else
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000282 WORD selector = HIWORD(GlobalLock(hMem));
283 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
424 hModule = GlobalAlloc( 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 Julliard594997c1995-04-30 10:05:20 +0000427 pModule = (NE_MODULE *)GlobalLock( 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 {
488 GlobalFree( hModule );
489 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 {
511 GlobalFree( hModule );
512 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 {
535 GlobalFree( hModule );
536 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 {
547 GlobalFree( hModule );
548 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 {
560 GlobalFree( hModule );
561 return (HMODULE)11; /* invalid exe */
562 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000563 buffer = GlobalLock( 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 {
568 GlobalFree( pModule->nrname_handle );
569 GlobalFree( hModule );
570 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 {
584 if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
585 GlobalFree( hModule );
586 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 */
643 cpnt = (char *)GlobalLock( pModule->nrname_handle );
644
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;
707 return (SEGPTR)MAKELONG( offset, sel );
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
762WNDPROC MODULE_GetWndProcEntry16( const char *name )
763{
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
780WNDPROC MODULE_GetWndProcEntry32( const char *name )
781{
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 {
896 GlobalFree( pSegment->selector );
897 }
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
909 if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
910 if (pModule->dlls_to_init) GlobalFree( pModule->dlls_to_init );
911 GlobalFree( 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);
981 pDLLs = (WORD *)GlobalLock( pModule->dlls_to_init );
982 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
1062 *(DWORD *)GlobalLock(hInitialStack32) = 0xDEADBEEF;
1063 stack32Top = (char*)GlobalLock(hInitialStack32) +
1064 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; */
1076 IF1632_Stack32_base = WIN16_GlobalLock(hInitialStack32);
1077
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){
1089 GlobalUnlock (hInitialStack32);
1090 GlobalFree (hInitialStack32);
1091 IF1632_Stack32_base = hInitialStack32 = 0;
1092 }
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001093 }
1094 else
1095 {
1096 for (i = 1; i <= pModule->seg_count; i++)
1097 NE_LoadSegment( hModule, i );
1098 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001099
1100 /* Fixup the functions prologs */
1101
Alexandre Julliard329f0681996-04-14 13:21:20 +00001102 NE_FixupPrologs( pModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001103
1104 /* Make sure the usage count is 1 on the first loading of */
1105 /* the module, even if it contains circular DLL references */
1106
1107 pModule->count = 1;
1108 }
1109 else
1110 {
Alexandre Julliard329f0681996-04-14 13:21:20 +00001111 pModule = MODULE_GetPtr( hModule );
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001112 hPrevInstance = MODULE_GetInstance( hModule );
1113 hInstance = MODULE_CreateInstance( hModule, params );
1114 if (hInstance != hPrevInstance) /* not a library */
1115 NE_LoadSegment( hModule, pModule->dgroup );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001116 pModule->count++;
1117 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001118#else
1119 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE) );
1120 pModule = (NE_MODULE *)GlobalLock( hModule );
1121 pModule->count = 1;
Alexandre Julliard329f0681996-04-14 13:21:20 +00001122 pModule->magic = NE_SIGNATURE;
1123 pModule->self = hModule;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001124 hPrevInstance = 0;
1125 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1126#endif /* WINELIB */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001127
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001128 /* Create a task for this instance */
1129
1130 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1131 {
1132 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1133 params->hEnvironment,
1134 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1135 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1136 }
1137
Alexandre Julliard2787be81995-05-22 18:23:01 +00001138 return hInstance;
1139}
1140
1141
1142/**********************************************************************
1143 * FreeModule (KERNEL.46)
1144 */
1145BOOL FreeModule( HANDLE hModule )
1146{
1147 NE_MODULE *pModule;
1148
1149 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard329f0681996-04-14 13:21:20 +00001150 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001151
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001152 dprintf_module( stddeb, "FreeModule: %s count %d\n",
1153 MODULE_GetModuleName(hModule), pModule->count );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001154 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1155 return TRUE;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001156}
1157
1158
1159/**********************************************************************
1160 * GetModuleHandle (KERNEL.47)
1161 */
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00001162HMODULE WIN16_GetModuleHandle( SEGPTR name )
1163{
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001164 if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00001165 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1166}
1167
Alexandre Julliard594997c1995-04-30 10:05:20 +00001168HMODULE GetModuleHandle( LPCSTR name )
1169{
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001170 return MODULE_FindModule( name );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001171}
1172
1173
1174/**********************************************************************
1175 * GetModuleUsage (KERNEL.48)
1176 */
1177int GetModuleUsage( HANDLE hModule )
1178{
1179 NE_MODULE *pModule;
1180
1181 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard329f0681996-04-14 13:21:20 +00001182 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001183 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +00001184 hModule, pModule->count );
1185 return pModule->count;
1186}
1187
1188
1189/**********************************************************************
1190 * GetModuleFileName (KERNEL.49)
1191 */
1192int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1193{
1194 NE_MODULE *pModule;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001195
1196 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliard329f0681996-04-14 13:21:20 +00001197 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +00001198 lstrcpyn( lpFileName, NE_MODULE_NAME(pModule), nSize );
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001199 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001200 return strlen(lpFileName);
1201}
1202
1203
Alexandre Julliard2787be81995-05-22 18:23:01 +00001204/***********************************************************************
1205 * LoadLibrary (KERNEL.95)
1206 */
1207HANDLE LoadLibrary( LPCSTR libname )
1208{
Alexandre Julliardade697e1995-11-26 13:59:11 +00001209#ifdef WINELIB
1210 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1211 WINELIB_UNIMP("LoadLibrary()");
1212 return (HANDLE)0;
1213#else
Alexandre Julliard2787be81995-05-22 18:23:01 +00001214 HANDLE handle;
1215
1216 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
Alexandre Julliardade697e1995-11-26 13:59:11 +00001217
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001218 /* This does not increment the module reference count, and will
1219 * therefore cause crashes on FreeLibrary calls.
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001220 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001221 */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001222 handle = LoadModule( libname, (LPVOID)-1 );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001223 if (handle == (HANDLE)2) /* file not found */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001224 {
1225 char buffer[256];
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001226 lstrcpyn( buffer, libname, 252 );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001227 strcat( buffer, ".dll" );
1228 handle = LoadModule( buffer, (LPVOID)-1 );
1229 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001230 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001231 return handle;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001232#endif
Alexandre Julliard2787be81995-05-22 18:23:01 +00001233}
1234
1235
1236/***********************************************************************
1237 * FreeLibrary (KERNEL.96)
1238 */
1239void FreeLibrary( HANDLE handle )
1240{
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001241 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001242 FreeModule( handle );
1243}
1244
1245
1246/***********************************************************************
1247 * WinExec (KERNEL.166)
1248 */
1249HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1250{
1251 LOADPARAMS params;
1252 HLOCAL cmdShowHandle, cmdLineHandle;
1253 HANDLE handle;
1254 WORD *cmdShowPtr;
1255 char *p, *cmdline, filename[256];
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001256 static int use_load_module = 1;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001257
1258 if (!(cmdShowHandle = GlobalAlloc( 0, 2 * sizeof(WORD) ))) return 0;
1259 if (!(cmdLineHandle = GlobalAlloc( 0, 256 ))) return 0;
1260
1261 /* Store nCmdShow */
1262
1263 cmdShowPtr = (WORD *)GlobalLock( cmdShowHandle );
1264 cmdShowPtr[0] = 2;
1265 cmdShowPtr[1] = nCmdShow;
1266
1267 /* Build the filename and command-line */
1268
1269 cmdline = (char *)GlobalLock( cmdLineHandle );
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001270 lstrcpyn( filename, lpCmdLine, sizeof(filename) - 4 /* for extension */ );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001271 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001272 if (*p) lstrcpyn( cmdline, p + 1, 128 );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001273 else cmdline[0] = '\0';
1274 *p = '\0';
1275
1276 /* Now load the executable file */
1277
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001278 if (use_load_module)
Alexandre Julliard2787be81995-05-22 18:23:01 +00001279 {
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001280#ifdef WINELIB
1281 /* WINELIB: Use LoadModule() only for the program itself */
1282 use_load_module = 0;
1283 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1284#else
1285 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1286#endif /* WINELIB */
1287 params.cmdLine = (SEGPTR)WIN16_GlobalLock( cmdLineHandle );
1288 params.showCmd = (SEGPTR)WIN16_GlobalLock( cmdShowHandle );
1289 params.reserved = 0;
1290 handle = LoadModule( filename, &params );
1291 if (handle == 2) /* file not found */
1292 {
1293 /* Check that the original file name did not have a suffix */
1294 p = strrchr(filename, '.');
1295 if (!p || (strchr(p, '/') && strchr(p, '\\')))
1296 {
1297 p = filename + strlen(filename);
1298 strcpy( p, ".exe" );
1299 handle = LoadModule( filename, &params );
1300 *p = '\0'; /* Remove extension */
1301 }
1302 }
1303 }
1304 else handle = 2;
1305
1306 if (handle < 32)
1307 {
1308 /* Try to start it as a unix program */
1309 if (!fork())
1310 {
1311 /* Child process */
1312 const char *unixfilename;
1313 const char *argv[256], **argptr;
1314 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1315 nCmdShow == SW_SHOWMINNOACTIVE);
1316
1317 /* get unixfilename */
1318 if (strchr(filename, '/') ||
1319 strchr(filename, ':') ||
1320 strchr(filename, '\\'))
1321 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1322 else unixfilename = filename;
1323
1324 if (unixfilename)
1325 {
1326 /* build argv */
1327 argptr = argv;
1328 if (iconic) *argptr++ = "-iconic";
1329 *argptr++ = unixfilename;
1330 p = cmdline;
1331 while (1)
1332 {
1333 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1334 if (!*p) break;
1335 *argptr++ = p;
1336 while (*p && *p != ' ' && *p != '\t') p++;
1337 }
1338 *argptr++ = 0;
1339
1340 /* Execute */
1341 execvp(argv[0], (char**)argv);
1342 }
1343
1344 /* Failed ! */
1345#ifdef WINELIB
1346 /* build argv */
1347 argptr = argv;
1348 *argptr++ = "wine";
1349 if (iconic) *argptr++ = "-iconic";
1350 *argptr++ = lpCmdLine;
1351 *argptr++ = 0;
1352
1353 /* Execute */
1354 execvp(argv[0] , (char**)argv);
1355
1356 /* Failed ! */
1357 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1358#endif
1359 exit(1);
1360 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001361 }
1362
1363 GlobalFree( cmdShowHandle );
1364 GlobalFree( cmdLineHandle );
Alexandre Julliard902da691995-11-05 14:39:02 +00001365
1366#if 0
1367 if (handle < (HANDLE)32) /* Error? */
1368 return handle;
1369
1370/* FIXME: Yield never returns!
1371 We may want to run more applications or start the debugger
1372 before calling Yield. If we don't Yield will be called immdiately
1373 after returning. Why is it needed for Word anyway? */
1374 Yield(); /* program is executed immediately ....needed for word */
1375
1376#endif
Alexandre Julliard2787be81995-05-22 18:23:01 +00001377 return handle;
1378}
1379
1380
1381/***********************************************************************
1382 * GetProcAddress (KERNEL.50)
1383 */
1384FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
1385{
1386 WORD ordinal;
1387 SEGPTR ret;
1388
1389 if (!hModule) hModule = GetCurrentTask();
1390 hModule = GetExePtr( hModule );
1391
1392 if (HIWORD(name) != 0)
1393 {
1394 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001395 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
Alexandre Julliard2787be81995-05-22 18:23:01 +00001396 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1397 }
1398 else
1399 {
1400 ordinal = LOWORD(name);
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001401 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
Alexandre Julliard2787be81995-05-22 18:23:01 +00001402 hModule, ordinal );
1403 }
1404 if (!ordinal) return (FARPROC)0;
1405
1406 ret = MODULE_GetEntryPoint( hModule, ordinal );
1407
Alexandre Julliard59730ae1996-03-24 16:20:51 +00001408 dprintf_module( stddeb, "GetProcAddress: returning %08lx\n", (DWORD)ret );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001409 return (FARPROC)ret;
1410}
1411
1412
Alexandre Julliardade697e1995-11-26 13:59:11 +00001413/**********************************************************************
1414 * GetExpWinVer (KERNEL.167)
1415 */
1416WORD GetExpWinVer( HMODULE hModule )
1417{
Alexandre Julliard329f0681996-04-14 13:21:20 +00001418 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1419 return pModule ? pModule->expected_version : 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001420}
1421
1422
Alexandre Julliard594997c1995-04-30 10:05:20 +00001423/**********************************************************************
1424 * ModuleFirst (TOOLHELP.59)
1425 */
1426BOOL ModuleFirst( MODULEENTRY *lpme )
1427{
1428 lpme->wNext = hFirstModule;
1429 return ModuleNext( lpme );
1430}
1431
1432
1433/**********************************************************************
1434 * ModuleNext (TOOLHELP.60)
1435 */
1436BOOL ModuleNext( MODULEENTRY *lpme )
1437{
1438 NE_MODULE *pModule;
1439
1440 if (!lpme->wNext) return FALSE;
Alexandre Julliard329f0681996-04-14 13:21:20 +00001441 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001442 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1443 MAX_MODULE_NAME );
1444 lpme->szModule[MAX_MODULE_NAME] = '\0';
1445 lpme->hModule = lpme->wNext;
1446 lpme->wcUsage = pModule->count;
Alexandre Julliard02ed4c21996-03-02 19:34:10 +00001447 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001448 lpme->szExePath[MAX_PATH] = '\0';
1449 lpme->wNext = pModule->next;
1450 return TRUE;
1451}
1452
1453
1454/**********************************************************************
1455 * ModuleFindName (TOOLHELP.61)
1456 */
1457BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1458{
1459 lpme->wNext = GetModuleHandle( name );
1460 return ModuleNext( lpme );
1461}
1462
1463
1464/**********************************************************************
1465 * ModuleFindHandle (TOOLHELP.62)
1466 */
1467BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
1468{
1469 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1470 lpme->wNext = hModule;
1471 return ModuleNext( lpme );
1472}