blob: d46529dee6f2d00b14d4719458af0fbb6af702b4 [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"
14#include "dlls.h"
Alexandre Julliard2787be81995-05-22 18:23:01 +000015#include "dos_fs.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000016#include "global.h"
17#include "ldt.h"
18#include "module.h"
19#include "neexe.h"
Alexandre Julliard2787be81995-05-22 18:23:01 +000020#include "stackframe.h"
21#include "task.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000022#include "toolhelp.h"
23#include "stddebug.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000024#include "debug.h"
25
Alexandre Julliardff8331e1995-09-18 11:19:54 +000026#include "callback.h"
Alexandre Julliard902da691995-11-05 14:39:02 +000027#include "wine.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000028
Alexandre Julliard594997c1995-04-30 10:05:20 +000029static HMODULE hFirstModule = 0;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +000030static HMODULE hCachedModule = 0; /* Module cached by MODULE_OpenFile */
Alexandre Julliard594997c1995-04-30 10:05:20 +000031
Alexandre Julliardade697e1995-11-26 13:59:11 +000032#ifndef WINELIB
Alexandre Julliard902da691995-11-05 14:39:02 +000033static HANDLE hInitialStack32 = 0;
Alexandre Julliardade697e1995-11-26 13:59:11 +000034#endif
Alexandre Julliard594997c1995-04-30 10:05:20 +000035/***********************************************************************
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000036 * MODULE_LoadBuiltin
37 *
38 * Load a built-in module. If the 'force' parameter is FALSE, we only
39 * load the module if it has not been disabled via the -dll option.
40 */
Alexandre Julliardade697e1995-11-26 13:59:11 +000041#ifndef WINELIB
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000042static HMODULE MODULE_LoadBuiltin( LPCSTR name, BOOL force )
43{
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000044 HMODULE hModule;
45 NE_MODULE *pModule;
46 SEGTABLEENTRY *pSegTable;
47 struct dll_table_s *table;
48 int i;
49 char dllname[16], *p;
50
51 /* Fix the name in case we have a full path and extension */
52
53 if ((p = strrchr( name, '\\' ))) name = p + 1;
54 strncpy( dllname, name, 15 );
55 dllname[15] = '\0';
56 if ((p = strrchr( dllname, '.' ))) *p = '\0';
57
58 for (i = 0, table = dll_builtin_table; i < N_BUILTINS; i++, table++)
59 if (!strcasecmp( table->name, dllname )) break;
60 if (i >= N_BUILTINS) return 0;
61 if (!table->used && !force) return 0;
62
63 hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, table->module_start,
64 table->module_end - table->module_start,
65 0, FALSE, FALSE, FALSE, NULL );
66 if (!hModule) return 0;
67 FarSetOwner( hModule, hModule );
68
69 table->hModule = hModule;
70
71 dprintf_module( stddeb, "Built-in %s: hmodule=%04x\n",
72 table->name, hModule );
73
74 /* Allocate the code segment */
75
76 pModule = (NE_MODULE *)GlobalLock( hModule );
77 pSegTable = NE_SEG_TABLE( pModule );
78
79 pSegTable->selector = GLOBAL_CreateBlock( GMEM_FIXED, table->code_start,
80 pSegTable->minsize, hModule,
81 TRUE, TRUE, FALSE, NULL );
82 if (!pSegTable->selector) return 0;
83 pSegTable++;
84
85 /* Allocate the data segment */
86
87 pSegTable->selector = GLOBAL_Alloc( GMEM_FIXED, pSegTable->minsize,
88 hModule, FALSE, FALSE, FALSE );
89 if (!pSegTable->selector) return 0;
90 memcpy( GlobalLock( pSegTable->selector ),
91 table->data_start, pSegTable->minsize );
92
93 pModule->next = hFirstModule;
94 hFirstModule = hModule;
95 return hModule;
96}
Alexandre Julliard902da691995-11-05 14:39:02 +000097#endif
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000098
99/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000100 * MODULE_Init
101 *
102 * Create the built-in modules.
103 */
104BOOL MODULE_Init(void)
105{
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000106 /* For these, built-in modules are always used */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000107
Alexandre Julliard902da691995-11-05 14:39:02 +0000108#ifndef WINELIB32
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000109 if (!MODULE_LoadBuiltin( "KERNEL", TRUE ) ||
110 !MODULE_LoadBuiltin( "GDI", TRUE ) ||
111 !MODULE_LoadBuiltin( "USER", TRUE ) ||
112 !MODULE_LoadBuiltin( "WINPROCS", TRUE )) return FALSE;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000113
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000114#else
115 fprintf(stderr, "JBP: MODULE_Init() ignored.\n");
116#endif
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000117 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000118
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000119 MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000120 return TRUE;
121}
122
123
124/***********************************************************************
125 * MODULE_PrintModule
126 */
127void MODULE_PrintModule( HMODULE hmodule )
128{
129 int i, ordinal;
130 SEGTABLEENTRY *pSeg;
131 BYTE *pstr;
132 WORD *pword;
133 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hmodule );
134
135 /* Dump the module info */
136
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000137 printf( "Module "NPFMT":\n", hmodule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000138 printf( "count=%d flags=%04x heap=%d stack=%d\n",
139 pModule->count, pModule->flags,
140 pModule->heap_size, pModule->stack_size );
141 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
142 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
143 pModule->seg_count, pModule->modref_count );
144 printf( "os_flags=%d swap_area=%d version=%04x\n",
145 pModule->os_flags, pModule->min_swap_area,
146 pModule->expected_version );
147
148 /* Dump the file info */
149
150 printf( "Filename: '%s'\n",
151 ((LOADEDFILEINFO *)((BYTE *)pModule + pModule->fileinfo))->filename );
152
153 /* Dump the segment table */
154
155 printf( "\nSegment table:\n" );
156 pSeg = NE_SEG_TABLE( pModule );
157 for (i = 0; i < pModule->seg_count; i++, pSeg++)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000158 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel="NPFMT"\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +0000159 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
160 pSeg->minsize, pSeg->selector );
161
162 /* Dump the resource table */
163
164 printf( "\nResource table:\n" );
165 if (pModule->res_table)
166 {
167 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
168 printf( "Alignment: %d\n", *pword++ );
169 while (*pword)
170 {
171 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
172 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
173 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
174 for (i = 0; i < ptr->count; i++, pname++)
175 printf( "offset=%d len=%d id=%04x\n",
176 pname->offset, pname->length, pname->id );
177 pword = (WORD *)pname;
178 }
179 }
180 else printf( "None\n" );
181
182 /* Dump the resident name table */
183
184 printf( "\nResident-name table:\n" );
185 pstr = (char *)pModule + pModule->name_table;
186 while (*pstr)
187 {
188 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
189 *(WORD *)(pstr + *pstr + 1) );
190 pstr += *pstr + 1 + sizeof(WORD);
191 }
192
193 /* Dump the module reference table */
194
195 printf( "\nModule ref table:\n" );
196 if (pModule->modref_table)
197 {
198 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
199 for (i = 0; i < pModule->modref_count; i++, pword++)
200 {
201 char *name = (char *)pModule + pModule->import_table + *pword;
202 printf( "%d: %04x -> '%*.*s'\n",
203 i, *pword, *name, *name, name + 1 );
204 }
205 }
206 else printf( "None\n" );
207
208 /* Dump the entry table */
209
210 printf( "\nEntry table:\n" );
211 pstr = (char *)pModule + pModule->entry_table;
212 ordinal = 1;
213 while (*pstr)
214 {
215 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
216 if (!pstr[1])
217 {
218 ordinal += *pstr;
219 pstr += 2;
220 }
221 else if ((BYTE)pstr[1] == 0xff) /* moveable */
222 {
223 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
224 for (i = 0; i < *pstr; i++, pe++)
225 printf( "%d: %02x:%04x (moveable)\n",
226 ordinal++, pe->seg_number, pe->offset );
227 pstr = (char *)pe;
228 }
229 else /* fixed */
230 {
231 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
232 for (i = 0; i < *pstr; i++, pe++)
233 printf( "%d: %04x (fixed)\n",
234 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
235 pstr = (char *)pe;
236 }
237 }
238
239 /* Dump the non-resident names table */
240
241 printf( "\nNon-resident names table:\n" );
242 if (pModule->nrname_handle)
243 {
244 pstr = (char *)GlobalLock( pModule->nrname_handle );
245 while (*pstr)
246 {
247 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
248 *(WORD *)(pstr + *pstr + 1) );
249 pstr += *pstr + 1 + sizeof(WORD);
250 }
251 }
252 printf( "\n" );
253}
254
255
256/***********************************************************************
257 * MODULE_OpenFile
258 */
259int MODULE_OpenFile( HMODULE hModule )
260{
261 NE_MODULE *pModule;
262 char *name;
263
Alexandre Julliard594997c1995-04-30 10:05:20 +0000264 static int cachedfd = -1;
265
266 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000267 dprintf_module( stddeb, "MODULE_OpenFile("NPFMT") cache: mod="NPFMT" fd=%d\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +0000268 hModule, hCachedModule, cachedfd );
269 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return -1;
270 if (hCachedModule == hModule) return cachedfd;
271 close( cachedfd );
272 hCachedModule = hModule;
273 name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000274 if ((cachedfd = open( DOS_GetUnixFileName( name ), O_RDONLY )) == -1)
275 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module "NPFMT"\n",
276 name, hModule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000277 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
278 name, cachedfd );
279 return cachedfd;
280}
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000281/***********************************************************************
282 * MODULE_Ne2MemFlags
283 */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000284
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000285/* This function translates NE segment flags to GlobalAlloc flags */
286
287static WORD MODULE_Ne2MemFlags(WORD flags)
288{
289 WORD memflags = 0;
290#if 0
291 if (flags & NE_SEGFLAGS_DISCARDABLE)
292 memflags |= GMEM_DISCARDABLE;
293 if (flags & NE_SEGFLAGS_MOVEABLE ||
294 ( ! (flags & NE_SEGFLAGS_DATA) &&
295 ! (flags & NE_SEGFLAGS_LOADED) &&
296 ! (flags & NE_SEGFLAGS_ALLOCATED)
297 )
298 )
299 memflags |= GMEM_MOVEABLE;
300 memflags |= GMEM_ZEROINIT;
301#else
302 memflags = GMEM_ZEROINIT | GMEM_FIXED;
303 return memflags;
304#endif
305}
306
307/***********************************************************************
308 * MODULE_AllocateSegment (WINPROCS.26)
309 */
310
311DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
312{
313 WORD size = wSize << wElem;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000314 HANDLE hMem = GlobalAlloc( MODULE_Ne2MemFlags(wFlags), size);
315#ifdef WINELIB32
316 return (DWORD)GlobalLock(hMem);
317#else
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000318 WORD selector = HIWORD(GlobalLock(hMem));
319 return MAKELONG(hMem, selector);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000320#endif
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000321}
Alexandre Julliard594997c1995-04-30 10:05:20 +0000322
323/***********************************************************************
324 * MODULE_CreateSegments
325 */
Alexandre Julliard902da691995-11-05 14:39:02 +0000326#ifndef WINELIB32
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000327static BOOL MODULE_CreateSegments( HMODULE hModule )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000328{
329 SEGTABLEENTRY *pSegment;
330 NE_MODULE *pModule;
331 int i, minsize;
332
333 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
334 pSegment = NE_SEG_TABLE( pModule );
335 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
336 {
337 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
338 if (i == pModule->ss) minsize += pModule->stack_size;
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000339 /* The DGROUP is allocated by MODULE_CreateInstance */
340 if (i == pModule->dgroup) continue;
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000341 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
Alexandre Julliard594997c1995-04-30 10:05:20 +0000342 minsize, hModule,
343 !(pSegment->flags & NE_SEGFLAGS_DATA),
344 FALSE,
345 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
346 if (!pSegment->selector) return FALSE;
347 }
348
349 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
350 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
351 return TRUE;
352}
Alexandre Julliard902da691995-11-05 14:39:02 +0000353#endif
Alexandre Julliard594997c1995-04-30 10:05:20 +0000354
355
356/***********************************************************************
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000357 * MODULE_GetInstance
358 */
Alexandre Julliard902da691995-11-05 14:39:02 +0000359#ifndef WINELIB32
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000360static HINSTANCE MODULE_GetInstance( HMODULE hModule )
361{
362 SEGTABLEENTRY *pSegment;
363 NE_MODULE *pModule;
364
365 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
366 if (pModule->dgroup == 0) return hModule;
367
368 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
369
370 return pSegment->selector;
371}
Alexandre Julliard902da691995-11-05 14:39:02 +0000372#endif
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000373
374
375/***********************************************************************
376 * MODULE_CreateInstance
377 */
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000378HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000379{
380 SEGTABLEENTRY *pSegment;
381 NE_MODULE *pModule;
382 int minsize;
383 HINSTANCE hNewInstance, hPrevInstance;
384
385 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
386 if (pModule->dgroup == 0) return hModule;
387
388 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
389 hPrevInstance = pSegment->selector;
390
391 /* if it's a library, create a new instance only the first time */
392 if (hPrevInstance)
393 {
394 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
395 if (params == (LOADPARAMS*)-1) return hPrevInstance;
396 }
397
398 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
399 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
400 minsize += pModule->heap_size;
401 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
402 minsize, hModule, FALSE, FALSE, FALSE );
403 if (!hNewInstance) return 0;
404 pSegment->selector = hNewInstance;
405 return hNewInstance;
406}
407
408
409/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000410 * MODULE_LoadExeHeader
411 */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000412HMODULE MODULE_LoadExeHeader( int fd, OFSTRUCT *ofs )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000413{
414 struct mz_header_s mz_header;
415 struct ne_header_s ne_header;
416 int size;
417 HMODULE hModule;
418 NE_MODULE *pModule;
419 BYTE *pData;
420 char *buffer, *fastload = NULL;
421 int fastload_offset = 0, fastload_length = 0;
422
423 /* Read a block from either the file or the fast-load area. */
424#define READ(offset,size,buffer) \
425 ((fastload && ((offset) >= fastload_offset) && \
426 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
427 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
428 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
429 read( fd, (buffer), (size) ) == (size)))
430
431 lseek( fd, 0, SEEK_SET );
432 if ((read( fd, &mz_header, sizeof(mz_header) ) != sizeof(mz_header)) ||
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000433 (mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000434
435 lseek( fd, mz_header.ne_offset, SEEK_SET );
436 if (read( fd, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000437 return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000438
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000439 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21; /* win32 exe */
440 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000441
442 /* We now have a valid NE header */
443
444 size = sizeof(NE_MODULE) +
445 /* loaded file info */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000446 sizeof(LOADEDFILEINFO) + strlen(ofs->szPathName) +
Alexandre Julliard594997c1995-04-30 10:05:20 +0000447 /* segment table */
448 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
449 /* resource table */
450 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
451 /* resident names table */
452 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
453 /* module ref table */
454 ne_header.n_mod_ref_tab * sizeof(WORD) +
455 /* imported names table */
456 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
457 /* entry table length */
458 ne_header.entry_tab_length;
459
460 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000461 if (!hModule) return (HMODULE)11; /* invalid exe */
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000462 FarSetOwner( hModule, (WORD)(DWORD)hModule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000463 pModule = (NE_MODULE *)GlobalLock( hModule );
464 memcpy( pModule, &ne_header, sizeof(NE_MODULE) );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000465 pModule->count = 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000466 pData = (BYTE *)(pModule + 1);
467
468 /* Read the fast-load area */
469
470 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
471 {
472 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
473 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
474 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
475 fastload_offset, fastload_length );
476 if ((fastload = (char *)malloc( fastload_length )) != NULL)
477 {
478 lseek( fd, mz_header.ne_offset + fastload_offset, SEEK_SET );
479 if (read( fd, fastload, fastload_length ) != fastload_length)
480 {
481 free( fastload );
482 fastload = NULL;
483 }
484 }
485 }
486
487 /* Store the filename information */
488
489 pModule->fileinfo = (int)pData - (int)pModule;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000490 ((LOADEDFILEINFO*)pData)->length = sizeof(LOADEDFILEINFO)+strlen(ofs->szPathName);
Alexandre Julliard594997c1995-04-30 10:05:20 +0000491 ((LOADEDFILEINFO*)pData)->fixed_media = TRUE;
492 ((LOADEDFILEINFO*)pData)->error = 0;
493 ((LOADEDFILEINFO*)pData)->date = 0;
494 ((LOADEDFILEINFO*)pData)->time = 0;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000495 strcpy( ((LOADEDFILEINFO*)pData)->filename, ofs->szPathName );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000496 pData += ((LOADEDFILEINFO*)pData)->length--;
497
498 /* Get the segment table */
499
500 pModule->seg_table = (int)pData - (int)pModule;
501 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
502 if (buffer)
503 {
504 int i;
505 struct ne_segment_table_entry_s *pSeg;
506
507 if (!READ( ne_header.segment_tab_offset,
508 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000509 buffer )) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000510 pSeg = (struct ne_segment_table_entry_s *)buffer;
511 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
512 {
513 memcpy( pData, pSeg, sizeof(*pSeg) );
514 pData += sizeof(SEGTABLEENTRY);
515 }
516 free( buffer );
517 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000518 else return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000519
520 /* Get the resource table */
521
522 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
523 {
524 pModule->res_table = (int)pData - (int)pModule;
525 if (!READ(ne_header.resource_tab_offset,
526 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000527 pData )) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000528 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
529 }
530 else pModule->res_table = 0; /* No resource table */
531
532 /* Get the resident names table */
533
534 pModule->name_table = (int)pData - (int)pModule;
535 if (!READ( ne_header.rname_tab_offset,
536 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000537 pData )) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000538 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
539
540 /* Get the module references table */
541
542 if (ne_header.n_mod_ref_tab > 0)
543 {
544 pModule->modref_table = (int)pData - (int)pModule;
545 if (!READ( ne_header.moduleref_tab_offset,
546 ne_header.n_mod_ref_tab * sizeof(WORD),
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000547 pData )) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000548 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
549 }
550 else pModule->modref_table = 0; /* No module references */
551
552 /* Get the imported names table */
553
554 pModule->import_table = (int)pData - (int)pModule;
555 if (!READ( ne_header.iname_tab_offset,
556 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000557 pData )) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000558 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
559
560 /* Get the entry table */
561
562 pModule->entry_table = (int)pData - (int)pModule;
563 if (!READ( ne_header.entry_tab_offset,
564 ne_header.entry_tab_length,
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000565 pData )) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000566 pData += ne_header.entry_tab_length;
567
568 /* Get the non-resident names table */
569
570 if (ne_header.nrname_tab_length)
571 {
572 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
573 hModule, FALSE, FALSE, FALSE );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000574 if (!pModule->nrname_handle) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000575 buffer = GlobalLock( pModule->nrname_handle );
576 lseek( fd, ne_header.nrname_tab_offset, SEEK_SET );
577 if (read( fd, buffer, ne_header.nrname_tab_length )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000578 != ne_header.nrname_tab_length) return (HMODULE)11; /* invalid exe */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000579 }
580 else pModule->nrname_handle = 0;
581
Alexandre Julliard2787be81995-05-22 18:23:01 +0000582 /* Allocate a segment for the implicitly-loaded DLLs */
583
584 if (pModule->modref_count)
585 {
586 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
587 (pModule->modref_count+1)*sizeof(HMODULE),
588 hModule, FALSE, FALSE, FALSE );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000589 if (!pModule->dlls_to_init) return (HMODULE)11; /* invalid exe */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000590 }
591 else pModule->dlls_to_init = 0;
592
Alexandre Julliard594997c1995-04-30 10:05:20 +0000593 if (debugging_module) MODULE_PrintModule( hModule );
594 pModule->next = hFirstModule;
595 hFirstModule = hModule;
596 return hModule;
597}
598
599
600/***********************************************************************
601 * MODULE_GetOrdinal
602 *
603 * Lookup the ordinal for a given name.
604 */
605WORD MODULE_GetOrdinal( HMODULE hModule, char *name )
606{
607 char buffer[256], *cpnt;
608 BYTE len;
609 NE_MODULE *pModule;
610
611 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
612
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000613 dprintf_module( stddeb, "MODULE_GetOrdinal("NPFMT",'%s')\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +0000614 hModule, name );
615
616 /* First handle names of the form '#xxxx' */
617
618 if (name[0] == '#') return atoi( name + 1 );
619
620 /* Now copy and uppercase the string */
621
622 strcpy( buffer, name );
623 AnsiUpper( buffer );
624 len = strlen( buffer );
625
626 /* First search the resident names */
627
628 cpnt = (char *)pModule + pModule->name_table;
629
630 /* Skip the first entry (module name) */
631 cpnt += *cpnt + 1 + sizeof(WORD);
632 while (*cpnt)
633 {
634 dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
635 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
636 {
637 dprintf_module( stddeb, " Found: ordinal=%d\n",
638 *(WORD *)(cpnt + *cpnt + 1) );
639 return *(WORD *)(cpnt + *cpnt + 1);
640 }
641 cpnt += *cpnt + 1 + sizeof(WORD);
642 }
643
644 /* Now search the non-resident names table */
645
646 if (!pModule->nrname_handle) return 0; /* No non-resident table */
647 cpnt = (char *)GlobalLock( pModule->nrname_handle );
648
649 /* Skip the first entry (module description string) */
650 cpnt += *cpnt + 1 + sizeof(WORD);
651 while (*cpnt)
652 {
653 dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
654 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
655 {
656 dprintf_module( stddeb, " Found: ordinal=%d\n",
657 *(WORD *)(cpnt + *cpnt + 1) );
658 return *(WORD *)(cpnt + *cpnt + 1);
659 }
660 cpnt += *cpnt + 1 + sizeof(WORD);
661 }
662 return 0;
663}
664
665
666/***********************************************************************
667 * MODULE_GetEntryPoint
668 *
669 * Return the entry point for a given ordinal.
670 */
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000671SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000672{
673 NE_MODULE *pModule;
674 WORD curOrdinal = 1;
675 BYTE *p;
676 WORD sel, offset;
677
678 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
679
Alexandre Julliard594997c1995-04-30 10:05:20 +0000680 p = (BYTE *)pModule + pModule->entry_table;
681 while (*p && (curOrdinal + *p <= ordinal))
682 {
683 /* Skipping this bundle */
684 curOrdinal += *p;
685 switch(p[1])
686 {
687 case 0: p += 2; break; /* unused */
688 case 0xff: p += 2 + *p * 6; break; /* moveable */
689 default: p += 2 + *p * 3; break; /* fixed */
690 }
691 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000692 if (!*p) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000693
694 switch(p[1])
695 {
696 case 0: /* unused */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000697 return 0;
698 case 0xff: /* moveable */
699 p += 2 + 6 * (ordinal - curOrdinal);
700 sel = p[3];
701 offset = *(WORD *)(p + 4);
702 break;
703 default: /* fixed */
704 sel = p[1];
705 p += 2 + 3 * (ordinal - curOrdinal);
706 offset = *(WORD *)(p + 1);
707 break;
708 }
709
Alexandre Julliard594997c1995-04-30 10:05:20 +0000710 if (sel == 0xfe) sel = 0xffff; /* constant entry */
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000711 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
712 return (SEGPTR)MAKELONG( offset, sel );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000713}
714
715
716/***********************************************************************
Alexandre Julliard2787be81995-05-22 18:23:01 +0000717 * MODULE_SetEntryPoint
718 *
719 * Change the value of an entry point. Use with caution!
720 * It can only change the offset value, not the selector.
721 */
722BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset )
723{
724 NE_MODULE *pModule;
725 WORD curOrdinal = 1;
726 BYTE *p;
727
728 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
729
730 p = (BYTE *)pModule + pModule->entry_table;
731 while (*p && (curOrdinal + *p <= ordinal))
732 {
733 /* Skipping this bundle */
734 curOrdinal += *p;
735 switch(p[1])
736 {
737 case 0: p += 2; break; /* unused */
738 case 0xff: p += 2 + *p * 6; break; /* moveable */
739 default: p += 2 + *p * 3; break; /* fixed */
740 }
741 }
742 if (!*p) return FALSE;
743
744 switch(p[1])
745 {
746 case 0: /* unused */
747 return FALSE;
748 case 0xff: /* moveable */
749 p += 2 + 6 * (ordinal - curOrdinal);
750 *(WORD *)(p + 4) = offset;
751 break;
752 default: /* fixed */
753 p += 2 + 3 * (ordinal - curOrdinal);
754 *(WORD *)(p + 1) = offset;
755 break;
756 }
757 return TRUE;
758}
759
760
761/***********************************************************************
762 * MODULE_GetEntryPointName
763 *
764 * Return the entry point name for a given ordinal.
765 * Used only by relay debugging.
766 * Warning: returned pointer is to a Pascal-type string.
767 */
768LPSTR MODULE_GetEntryPointName( HMODULE hModule, WORD ordinal )
769{
770 register char *cpnt;
771 NE_MODULE *pModule;
772
773 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
774
775 /* First search the resident names */
776
777 cpnt = (char *)pModule + pModule->name_table;
778 while (*cpnt)
779 {
780 cpnt += *cpnt + 1 + sizeof(WORD);
781 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
782 }
783
784 /* Now search the non-resident names table */
785
786 if (!pModule->nrname_handle) return 0; /* No non-resident table */
787 cpnt = (char *)GlobalLock( pModule->nrname_handle );
788 while (*cpnt)
789 {
790 cpnt += *cpnt + 1 + sizeof(WORD);
791 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
792 }
793 return NULL;
794}
795
796
797/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000798 * MODULE_GetModuleName
799 */
800LPSTR MODULE_GetModuleName( HMODULE hModule )
801{
802 NE_MODULE *pModule;
803 BYTE *p, len;
804 static char buffer[10];
805
806 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return NULL;
807 p = (BYTE *)pModule + pModule->name_table;
Alexandre Julliard902da691995-11-05 14:39:02 +0000808 len = MIN( *p, 8 );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000809 memcpy( buffer, p + 1, len );
810 buffer[len] = '\0';
811 return buffer;
812}
813
814
815/**********************************************************************
Alexandre Julliard2787be81995-05-22 18:23:01 +0000816 * MODULE_FindModule
817 *
818 * Find a module from a path name.
819 */
820HMODULE MODULE_FindModule( LPCSTR path )
821{
822 HMODULE hModule = hFirstModule;
823 LPCSTR filename, dotptr, modulepath, modulename;
824 BYTE len, *name_table;
825
826 if (!(filename = strrchr( path, '\\' ))) filename = path;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000827 else filename++;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000828 if ((dotptr = strrchr( filename, '.' )) != NULL)
829 len = (BYTE)(dotptr - filename);
830 else len = strlen( filename );
831
832 while(hModule)
833 {
834 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
835 if (!pModule) break;
836 modulepath = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
837 if (!(modulename = strrchr( modulepath, '\\' )))
838 modulename = modulepath;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000839 else modulename++;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000840 if (!strcasecmp( modulename, filename )) return hModule;
841
842 name_table = (BYTE *)pModule + pModule->name_table;
843 if ((*name_table == len) && !strncasecmp(filename, name_table+1, len))
844 return hModule;
845 hModule = pModule->next;
846 }
847 return 0;
848}
849
850
851/**********************************************************************
852 * MODULE_FreeModule
853 *
854 * Remove a module from memory.
855 */
856static void MODULE_FreeModule( HMODULE hModule )
857{
858 HMODULE *hPrevModule;
859 NE_MODULE *pModule;
860 SEGTABLEENTRY *pSegment;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000861 HMODULE *pModRef;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000862 int i;
863
864 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000865 if (pModule->flags & NE_FFLAGS_BUILTIN)
866 return; /* Can't free built-in module */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000867
868 /* FIXME: should call the exit code for the library here */
869
870 /* Remove it from the linked list */
871
872 hPrevModule = &hFirstModule;
873 while (*hPrevModule && (*hPrevModule != hModule))
874 {
875 hPrevModule = &((NE_MODULE *)GlobalLock( *hPrevModule ))->next;
876 }
877 if (*hPrevModule) *hPrevModule = pModule->next;
878
879 /* Free all the segments */
880
881 pSegment = NE_SEG_TABLE( pModule );
882 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
883 {
884 GlobalFree( pSegment->selector );
885 }
886
887 /* Free the referenced modules */
888
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +0000889 pModRef = (HMODULE*)NE_MODULE_TABLE( pModule );
Alexandre Julliard2787be81995-05-22 18:23:01 +0000890 for (i = 0; i < pModule->modref_count; i++, pModRef++)
891 {
892 FreeModule( *pModRef );
893 }
894
895 /* Free the module storage */
896
897 if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
898 if (pModule->dlls_to_init) GlobalFree( pModule->dlls_to_init );
899 GlobalFree( hModule );
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000900
901 /* Remove module from cache */
902
903 if (hCachedModule == hModule) hCachedModule = 0;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000904}
905
906
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000907HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params);
908
Alexandre Julliard2787be81995-05-22 18:23:01 +0000909/**********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000910 * LoadModule (KERNEL.45)
911 */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000912HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000913{
Alexandre Julliard2787be81995-05-22 18:23:01 +0000914 HMODULE hModule;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000915 HANDLE hInstance, hPrevInstance;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000916 NE_MODULE *pModule;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000917 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
Alexandre Julliardade697e1995-11-26 13:59:11 +0000918#ifndef WINELIB
Alexandre Julliard2787be81995-05-22 18:23:01 +0000919 WORD *pModRef, *pDLLs;
920 int i, fd;
921
922 hModule = MODULE_FindModule( name );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000923
Alexandre Julliard2787be81995-05-22 18:23:01 +0000924 if (!hModule) /* We have to load the module */
925 {
926 OFSTRUCT ofs;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000927
928 /* Try to load the built-in first if not disabled */
929 if ((hModule = MODULE_LoadBuiltin( name, FALSE ))) return hModule;
930
Alexandre Julliard2787be81995-05-22 18:23:01 +0000931 if (strchr( name, '/' )) name = DOS_GetDosFileName( name );
932 if ((fd = OpenFile( name, &ofs, OF_READ )) == -1)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000933 {
934 /* Now try the built-in even if disabled */
935 if ((hModule = MODULE_LoadBuiltin( name, TRUE )))
936 {
937 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
938 return hModule;
939 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000940 return 2; /* File not found */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000941 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000942
943 /* Create the module structure */
944
945 if ((hModule = MODULE_LoadExeHeader( fd, &ofs )) < 32)
946 {
Alexandre Julliardff8331e1995-09-18 11:19:54 +0000947 if(hModule == 21)
948 return PE_LoadModule(fd,&ofs,paramBlock);
Alexandre Julliard2787be81995-05-22 18:23:01 +0000949 close( fd );
950 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
951 name, hModule );
952 return hModule;
953 }
954 pModule = (NE_MODULE *)GlobalLock( hModule );
955
956 /* Allocate the segments for this module */
957
958 MODULE_CreateSegments( hModule );
959
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000960 hPrevInstance = 0;
961 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
962
Alexandre Julliard2787be81995-05-22 18:23:01 +0000963 /* Load the referenced DLLs */
964
965 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
966 pDLLs = (WORD *)GlobalLock( pModule->dlls_to_init );
967 for (i = 0; i < pModule->modref_count; i++, pModRef++)
968 {
969 char buffer[256];
970 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
971 memcpy( buffer, pstr + 1, *pstr );
972 strcpy( buffer + *pstr, ".dll" );
973 dprintf_module( stddeb, "Loading '%s'\n", buffer );
974 if (!(*pModRef = MODULE_FindModule( buffer )))
975 {
976 /* If the DLL is not loaded yet, load it and store */
977 /* its handle in the list of DLLs to initialize. */
978 HMODULE hDLL;
979
980 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
981 {
982 char *p;
983
984 /* Try with prepending the path of the current module */
985 GetModuleFileName( hModule, buffer, 256 );
986 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
987 memcpy( p + 1, pstr + 1, *pstr );
988 strcpy( p + 1 + *pstr, ".dll" );
989 hDLL = LoadModule( buffer, (LPVOID)-1 );
990 }
991 if (hDLL < 32)
992 {
993 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
994 buffer, name, hDLL );
995 return 2; /* file not found */
996 }
997 *pModRef = GetExePtr( hDLL );
998 *pDLLs++ = *pModRef;
999 }
1000 else /* Increment the reference count of the DLL */
1001 {
1002 NE_MODULE *pOldDLL = (NE_MODULE *)GlobalLock( *pModRef );
1003 if (pOldDLL) pOldDLL->count++;
1004 }
1005 }
1006
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001007 /* Load the segments */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001008
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001009 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1010 {
1011 /* Handle self loading modules */
1012 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1013 SELFLOADHEADER *selfloadheader;
1014 HMODULE hselfload = GetModuleHandle("WINPROCS");
1015 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1016 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1017 "Support for self-loading modules is very experimental\n",
1018 *((BYTE*)pModule + pModule->name_table),
1019 *((BYTE*)pModule + pModule->name_table),
1020 (char *)pModule + pModule->name_table + 1);
1021 NE_LoadSegment( hModule, 1 );
1022 selfloadheader = (SELFLOADHEADER *)
1023 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1024 selfloadheader->EntryAddrProc =
1025 MODULE_GetEntryPoint(hselfload,27);
1026 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1027 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1028 pModule->self_loading_sel = GlobalHandleToSel(
1029 GLOBAL_Alloc (GMEM_ZEROINIT,
1030 0xFF00, hModule, FALSE, FALSE, FALSE)
1031 );
1032 oldss = IF1632_Saved16_ss;
1033 oldsp = IF1632_Saved16_sp;
1034 IF1632_Saved16_ss = pModule->self_loading_sel;
1035 IF1632_Saved16_sp = 0xFF00;
Alexandre Julliard902da691995-11-05 14:39:02 +00001036 if (!IF1632_Stack32_base) {
1037 STACK32FRAME* frame32;
1038 char *stack32Top;
1039 /* Setup an initial 32 bit stack frame */
1040 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1041 hModule, FALSE, FALSE,
1042 FALSE );
1043
1044 /* Create the 32-bit stack frame */
1045
1046 *(DWORD *)GlobalLock(hInitialStack32) = 0xDEADBEEF;
1047 stack32Top = (char*)GlobalLock(hInitialStack32) +
1048 0x10000;
1049 frame32 = (STACK32FRAME *)stack32Top - 1;
1050 frame32->saved_esp = (DWORD)stack32Top;
1051 frame32->edi = 0;
1052 frame32->esi = 0;
1053 frame32->edx = 0;
1054 frame32->ecx = 0;
1055 frame32->ebx = 0;
1056 frame32->ebp = 0;
1057 frame32->retaddr = 0;
1058 frame32->codeselector = WINE_CODE_SELECTOR;
1059 /* pTask->esp = (DWORD)frame32; */
1060 IF1632_Stack32_base = WIN16_GlobalLock(hInitialStack32);
1061
1062 }
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001063 CallTo16_word_ww (selfloadheader->BootApp,
1064 pModule->self_loading_sel, hModule, fd);
1065 /* some BootApp procs overwrite the selector of dgroup */
1066 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1067 IF1632_Saved16_ss = oldss;
1068 IF1632_Saved16_sp = oldsp;
1069 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
Alexandre Julliard902da691995-11-05 14:39:02 +00001070 if (hInitialStack32){
1071 GlobalUnlock (hInitialStack32);
1072 GlobalFree (hInitialStack32);
1073 IF1632_Stack32_base = hInitialStack32 = 0;
1074 }
Alexandre Julliardff8331e1995-09-18 11:19:54 +00001075 }
1076 else
1077 {
1078 for (i = 1; i <= pModule->seg_count; i++)
1079 NE_LoadSegment( hModule, i );
1080 }
Alexandre Julliard2787be81995-05-22 18:23:01 +00001081
1082 /* Fixup the functions prologs */
1083
1084 NE_FixupPrologs( hModule );
1085
1086 /* Make sure the usage count is 1 on the first loading of */
1087 /* the module, even if it contains circular DLL references */
1088
1089 pModule->count = 1;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001090
1091 /* Clear built-in flag in case it was set in the EXE file */
1092
1093 pModule->flags &= ~NE_FFLAGS_BUILTIN;
Alexandre Julliard2787be81995-05-22 18:23:01 +00001094 }
1095 else
1096 {
1097 pModule = (NE_MODULE *)GlobalLock( hModule );
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001098 hPrevInstance = MODULE_GetInstance( hModule );
1099 hInstance = MODULE_CreateInstance( hModule, params );
1100 if (hInstance != hPrevInstance) /* not a library */
1101 NE_LoadSegment( hModule, pModule->dgroup );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001102 pModule->count++;
1103 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001104#else
1105 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE) );
1106 pModule = (NE_MODULE *)GlobalLock( hModule );
1107 pModule->count = 1;
1108 pModule->magic = 0x454e;
1109 hPrevInstance = 0;
1110 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1111#endif /* WINELIB */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001112
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001113 /* Create a task for this instance */
1114
1115 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1116 {
1117 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1118 params->hEnvironment,
1119 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1120 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1121 }
1122
Alexandre Julliard2787be81995-05-22 18:23:01 +00001123 return hInstance;
1124}
1125
1126
1127/**********************************************************************
1128 * FreeModule (KERNEL.46)
1129 */
1130BOOL FreeModule( HANDLE hModule )
1131{
1132 NE_MODULE *pModule;
1133
1134 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1135 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
1136
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001137 dprintf_module( stddeb, "FreeModule: %s count %d\n",
1138 MODULE_GetModuleName(hModule), pModule->count );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001139 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1140 return TRUE;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001141}
1142
1143
1144/**********************************************************************
1145 * GetModuleHandle (KERNEL.47)
1146 */
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00001147HMODULE WIN16_GetModuleHandle( SEGPTR name )
1148{
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001149#ifdef WINELIB32
1150 if (HIWORD(name) == 0) return GetExePtr( name );
1151#else
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00001152 if (HIWORD(name) == 0) return GetExePtr( LOWORD(name) );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001153#endif
Alexandre Julliarde2991ea1995-07-29 13:09:43 +00001154 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1155}
1156
Alexandre Julliard594997c1995-04-30 10:05:20 +00001157HMODULE GetModuleHandle( LPCSTR name )
1158{
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001159 return MODULE_FindModule( name );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001160}
1161
1162
1163/**********************************************************************
1164 * GetModuleUsage (KERNEL.48)
1165 */
1166int GetModuleUsage( HANDLE hModule )
1167{
1168 NE_MODULE *pModule;
1169
1170 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1171 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001172 dprintf_module( stddeb, "GetModuleUsage("NPFMT"): returning %d\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +00001173 hModule, pModule->count );
1174 return pModule->count;
1175}
1176
1177
1178/**********************************************************************
1179 * GetModuleFileName (KERNEL.49)
1180 */
1181int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1182{
1183 NE_MODULE *pModule;
1184 char *name;
1185
1186 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1187 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
1188 name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
Alexandre Julliardd4719651995-12-12 18:49:11 +00001189 lstrcpyn( lpFileName, name, nSize );
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001190 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001191 return strlen(lpFileName);
1192}
1193
1194
Alexandre Julliard2787be81995-05-22 18:23:01 +00001195/***********************************************************************
1196 * LoadLibrary (KERNEL.95)
1197 */
1198HANDLE LoadLibrary( LPCSTR libname )
1199{
Alexandre Julliardade697e1995-11-26 13:59:11 +00001200#ifdef WINELIB
1201 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1202 WINELIB_UNIMP("LoadLibrary()");
1203 return (HANDLE)0;
1204#else
Alexandre Julliard2787be81995-05-22 18:23:01 +00001205 HANDLE handle;
1206
1207 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
Alexandre Julliardade697e1995-11-26 13:59:11 +00001208
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001209 /* This does not increment the module reference count, and will
1210 * therefore cause crashes on FreeLibrary calls.
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001211 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +00001212 */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001213 handle = LoadModule( libname, (LPVOID)-1 );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001214 if (handle == (HANDLE)2) /* file not found */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001215 {
1216 char buffer[256];
1217 strcpy( buffer, libname );
1218 strcat( buffer, ".dll" );
1219 handle = LoadModule( buffer, (LPVOID)-1 );
1220 }
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001221 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001222 return handle;
Alexandre Julliardade697e1995-11-26 13:59:11 +00001223#endif
Alexandre Julliard2787be81995-05-22 18:23:01 +00001224}
1225
1226
1227/***********************************************************************
1228 * FreeLibrary (KERNEL.96)
1229 */
1230void FreeLibrary( HANDLE handle )
1231{
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001232 dprintf_module( stddeb,"FreeLibrary: "NPFMT"\n", handle );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001233 FreeModule( handle );
1234}
1235
1236
1237/***********************************************************************
1238 * WinExec (KERNEL.166)
1239 */
1240HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1241{
1242 LOADPARAMS params;
1243 HLOCAL cmdShowHandle, cmdLineHandle;
1244 HANDLE handle;
1245 WORD *cmdShowPtr;
1246 char *p, *cmdline, filename[256];
1247
1248 if (!(cmdShowHandle = GlobalAlloc( 0, 2 * sizeof(WORD) ))) return 0;
1249 if (!(cmdLineHandle = GlobalAlloc( 0, 256 ))) return 0;
1250
1251 /* Store nCmdShow */
1252
1253 cmdShowPtr = (WORD *)GlobalLock( cmdShowHandle );
1254 cmdShowPtr[0] = 2;
1255 cmdShowPtr[1] = nCmdShow;
1256
1257 /* Build the filename and command-line */
1258
1259 cmdline = (char *)GlobalLock( cmdLineHandle );
1260 strncpy( filename, lpCmdLine, 256 );
1261 filename[255] = '\0';
1262 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1263 if (*p)
1264 {
1265 strncpy( cmdline, p + 1, 128 );
1266 cmdline[127] = '\0';
1267 }
1268 else cmdline[0] = '\0';
1269 *p = '\0';
1270
1271 /* Now load the executable file */
1272
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +00001273#ifdef WINELIB32
1274 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1275#else
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001276 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +00001277#endif
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001278 params.cmdLine = (SEGPTR)WIN16_GlobalLock( cmdLineHandle );
1279 params.showCmd = (SEGPTR)WIN16_GlobalLock( cmdShowHandle );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001280 params.reserved = 0;
1281 handle = LoadModule( filename, &params );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001282 if (handle == (HANDLE)2) /* file not found */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001283 {
Alexandre Julliard902da691995-11-05 14:39:02 +00001284 /* Check that the original file name did not have a suffix */
1285 p = strrchr(filename, '.');
1286 if (p && !(strchr(p, '/') || strchr(p, '\\')))
1287 return handle; /* filename already includes a suffix! */
Alexandre Julliard2787be81995-05-22 18:23:01 +00001288 strcat( filename, ".exe" );
1289 handle = LoadModule( filename, &params );
1290 }
1291
1292 GlobalFree( cmdShowHandle );
1293 GlobalFree( cmdLineHandle );
Alexandre Julliard902da691995-11-05 14:39:02 +00001294
1295#if 0
1296 if (handle < (HANDLE)32) /* Error? */
1297 return handle;
1298
1299/* FIXME: Yield never returns!
1300 We may want to run more applications or start the debugger
1301 before calling Yield. If we don't Yield will be called immdiately
1302 after returning. Why is it needed for Word anyway? */
1303 Yield(); /* program is executed immediately ....needed for word */
1304
1305#endif
Alexandre Julliard2787be81995-05-22 18:23:01 +00001306 return handle;
1307}
1308
1309
1310/***********************************************************************
1311 * GetProcAddress (KERNEL.50)
1312 */
1313FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
1314{
1315 WORD ordinal;
1316 SEGPTR ret;
1317
1318 if (!hModule) hModule = GetCurrentTask();
1319 hModule = GetExePtr( hModule );
1320
1321 if (HIWORD(name) != 0)
1322 {
1323 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001324 dprintf_module( stddeb, "GetProcAddress: "NPFMT" '%s'\n",
Alexandre Julliard2787be81995-05-22 18:23:01 +00001325 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1326 }
1327 else
1328 {
1329 ordinal = LOWORD(name);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001330 dprintf_module( stddeb, "GetProcAddress: "NPFMT" %04x\n",
Alexandre Julliard2787be81995-05-22 18:23:01 +00001331 hModule, ordinal );
1332 }
1333 if (!ordinal) return (FARPROC)0;
1334
1335 ret = MODULE_GetEntryPoint( hModule, ordinal );
1336
Alexandre Julliardd7d4fdf1995-12-26 15:05:24 +00001337 dprintf_module( stddeb, "GetProcAddress: returning "SPFMT"\n", ret );
Alexandre Julliard2787be81995-05-22 18:23:01 +00001338 return (FARPROC)ret;
1339}
1340
1341
Alexandre Julliardade697e1995-11-26 13:59:11 +00001342/**********************************************************************
1343 * GetExpWinVer (KERNEL.167)
1344 */
1345WORD GetExpWinVer( HMODULE hModule )
1346{
1347 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
1348
1349 return pModule->expected_version;
1350}
1351
1352
Alexandre Julliard808cb041995-08-17 17:11:36 +00001353/***********************************************************************
1354 * GetWndProcEntry16 (not a Windows API function)
1355 *
1356 * Return an entry point from the WINPROCS dll.
1357 */
Alexandre Julliardade697e1995-11-26 13:59:11 +00001358#ifndef WINELIB
Alexandre Julliard808cb041995-08-17 17:11:36 +00001359WNDPROC GetWndProcEntry16( char *name )
1360{
1361 WORD ordinal;
1362 static HMODULE hModule = 0;
1363
1364 if (!hModule) hModule = GetModuleHandle( "WINPROCS" );
1365 ordinal = MODULE_GetOrdinal( hModule, name );
1366 return MODULE_GetEntryPoint( hModule, ordinal );
1367}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001368#endif
Alexandre Julliard808cb041995-08-17 17:11:36 +00001369
1370
Alexandre Julliard594997c1995-04-30 10:05:20 +00001371/**********************************************************************
1372 * ModuleFirst (TOOLHELP.59)
1373 */
1374BOOL ModuleFirst( MODULEENTRY *lpme )
1375{
1376 lpme->wNext = hFirstModule;
1377 return ModuleNext( lpme );
1378}
1379
1380
1381/**********************************************************************
1382 * ModuleNext (TOOLHELP.60)
1383 */
1384BOOL ModuleNext( MODULEENTRY *lpme )
1385{
1386 NE_MODULE *pModule;
1387
1388 if (!lpme->wNext) return FALSE;
1389 if (!(pModule = (NE_MODULE *)GlobalLock( lpme->wNext ))) return FALSE;
1390 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1391 MAX_MODULE_NAME );
1392 lpme->szModule[MAX_MODULE_NAME] = '\0';
1393 lpme->hModule = lpme->wNext;
1394 lpme->wcUsage = pModule->count;
1395 strncpy( lpme->szExePath,
1396 ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename,
1397 MAX_PATH );
1398 lpme->szExePath[MAX_PATH] = '\0';
1399 lpme->wNext = pModule->next;
1400 return TRUE;
1401}
1402
1403
1404/**********************************************************************
1405 * ModuleFindName (TOOLHELP.61)
1406 */
1407BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1408{
1409 lpme->wNext = GetModuleHandle( name );
1410 return ModuleNext( lpme );
1411}
1412
1413
1414/**********************************************************************
1415 * ModuleFindHandle (TOOLHELP.62)
1416 */
1417BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
1418{
1419 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1420 lpme->wNext = hModule;
1421 return ModuleNext( lpme );
1422}