Release 960414
[wine.git] / loader / module.c
blob128c05a4b34695917a38cebce3fb05bfbf979c12
1 /*
2 * Modules
4 * Copyright 1995 Alexandre Julliard
5 */
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"
15 #include "dos_fs.h"
16 #include "file.h"
17 #include "global.h"
18 #include "ldt.h"
19 #include "module.h"
20 #include "neexe.h"
21 #include "stackframe.h"
22 #include "task.h"
23 #include "toolhelp.h"
24 #include "stddebug.h"
25 #include "debug.h"
27 #include "callback.h"
28 #include "wine.h"
30 extern HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
32 static HMODULE hFirstModule = 0;
33 static HMODULE hCachedModule = 0; /* Module cached by MODULE_OpenFile */
35 #ifndef WINELIB
36 static HANDLE hInitialStack32 = 0;
37 #endif
38 /***********************************************************************
39 * MODULE_LoadBuiltin
41 * Load a built-in module. If the 'force' parameter is FALSE, we only
42 * load the module if it has not been disabled via the -dll option.
44 #ifndef WINELIB
45 static HMODULE MODULE_LoadBuiltin( LPCSTR name, BOOL force )
47 HMODULE hModule;
48 NE_MODULE *pModule;
49 SEGTABLEENTRY *pSegTable;
50 BUILTIN_DLL *table;
51 char dllname[16], *p;
53 /* Fix the name in case we have a full path and extension */
55 if ((p = strrchr( name, '\\' ))) name = p + 1;
56 lstrcpyn( dllname, name, sizeof(dllname) );
57 if ((p = strrchr( dllname, '.' ))) *p = '\0';
59 for (table = dll_builtin_table; table->name; table++)
60 if (!lstrcmpi( table->name, dllname )) break;
61 if (!table->name) return 0;
62 if ((table->flags & DLL_FLAG_NOT_USED) && !force) return 0;
64 hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, table->module_start,
65 table->module_end - table->module_start,
66 0, FALSE, FALSE, FALSE, NULL );
67 if (!hModule) return 0;
68 FarSetOwner( hModule, hModule );
70 table->hModule = hModule;
72 dprintf_module( stddeb, "Built-in %s: hmodule=%04x\n",
73 table->name, hModule );
74 pModule = (NE_MODULE *)GlobalLock( hModule );
75 pModule->self = hModule;
77 if (pModule->flags & NE_FFLAGS_WIN32)
79 pModule->pe_module = (PE_MODULE *)table;
81 else /* Win16 module */
83 /* Allocate the code segment */
85 pSegTable = NE_SEG_TABLE( pModule );
86 pSegTable->selector = GLOBAL_CreateBlock(GMEM_FIXED, table->code_start,
87 pSegTable->minsize, hModule,
88 TRUE, TRUE, FALSE, NULL );
89 if (!pSegTable->selector) return 0;
90 pSegTable++;
92 /* Allocate the data segment */
94 pSegTable->selector = GLOBAL_Alloc( GMEM_FIXED, pSegTable->minsize,
95 hModule, FALSE, FALSE, FALSE );
96 if (!pSegTable->selector) return 0;
97 memcpy( GlobalLock( pSegTable->selector ),
98 table->data_start, pSegTable->minsize );
101 pModule->next = hFirstModule;
102 hFirstModule = hModule;
103 return hModule;
105 #endif
107 /***********************************************************************
108 * MODULE_Init
110 * Create the built-in modules.
112 BOOL MODULE_Init(void)
114 #ifndef WINELIB32
115 BUILTIN_DLL *dll;
117 /* Load all modules marked as always used */
119 for (dll = dll_builtin_table; dll->name; dll++)
120 if (dll->flags & DLL_FLAG_ALWAYS_USED)
121 if (!MODULE_LoadBuiltin(dll->name, TRUE)) return FALSE;
122 #endif
123 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
125 MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
126 return TRUE;
130 /***********************************************************************
131 * MODULE_GetPtr
133 NE_MODULE *MODULE_GetPtr( HMODULE hModule )
135 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
136 if (!pModule || (pModule->magic != NE_SIGNATURE) ||
137 (pModule->self != hModule)) return NULL;
138 return pModule;
142 /***********************************************************************
143 * MODULE_DumpModule
145 void MODULE_DumpModule( HMODULE hmodule )
147 int i, ordinal;
148 SEGTABLEENTRY *pSeg;
149 BYTE *pstr;
150 WORD *pword;
151 NE_MODULE *pModule;
153 if (!(pModule = MODULE_GetPtr( hmodule )))
155 fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
156 return;
159 /* Dump the module info */
161 printf( "Module %04x:\n", hmodule );
162 printf( "count=%d flags=%04x heap=%d stack=%d\n",
163 pModule->count, pModule->flags,
164 pModule->heap_size, pModule->stack_size );
165 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
166 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
167 pModule->seg_count, pModule->modref_count );
168 printf( "os_flags=%d swap_area=%d version=%04x\n",
169 pModule->os_flags, pModule->min_swap_area,
170 pModule->expected_version );
171 if (pModule->flags & NE_FFLAGS_WIN32)
172 printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
174 /* Dump the file info */
176 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
178 /* Dump the segment table */
180 printf( "\nSegment table:\n" );
181 pSeg = NE_SEG_TABLE( pModule );
182 for (i = 0; i < pModule->seg_count; i++, pSeg++)
183 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
184 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
185 pSeg->minsize, pSeg->selector );
187 /* Dump the resource table */
189 printf( "\nResource table:\n" );
190 if (pModule->res_table)
192 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
193 printf( "Alignment: %d\n", *pword++ );
194 while (*pword)
196 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
197 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
198 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
199 for (i = 0; i < ptr->count; i++, pname++)
200 printf( "offset=%d len=%d id=%04x\n",
201 pname->offset, pname->length, pname->id );
202 pword = (WORD *)pname;
205 else printf( "None\n" );
207 /* Dump the resident name table */
209 printf( "\nResident-name table:\n" );
210 pstr = (char *)pModule + pModule->name_table;
211 while (*pstr)
213 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
214 *(WORD *)(pstr + *pstr + 1) );
215 pstr += *pstr + 1 + sizeof(WORD);
218 /* Dump the module reference table */
220 printf( "\nModule ref table:\n" );
221 if (pModule->modref_table)
223 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
224 for (i = 0; i < pModule->modref_count; i++, pword++)
226 char *name = (char *)pModule + pModule->import_table + *pword;
227 printf( "%d: %04x -> '%*.*s'\n",
228 i, *pword, *name, *name, name + 1 );
231 else printf( "None\n" );
233 /* Dump the entry table */
235 printf( "\nEntry table:\n" );
236 pstr = (char *)pModule + pModule->entry_table;
237 ordinal = 1;
238 while (*pstr)
240 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
241 if (!pstr[1])
243 ordinal += *pstr;
244 pstr += 2;
246 else if ((BYTE)pstr[1] == 0xff) /* moveable */
248 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
249 for (i = 0; i < *pstr; i++, pe++)
250 printf( "%d: %02x:%04x (moveable)\n",
251 ordinal++, pe->seg_number, pe->offset );
252 pstr = (char *)pe;
254 else /* fixed */
256 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
257 for (i = 0; i < *pstr; i++, pe++)
258 printf( "%d: %04x (fixed)\n",
259 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
260 pstr = (char *)pe;
264 /* Dump the non-resident names table */
266 printf( "\nNon-resident names table:\n" );
267 if (pModule->nrname_handle)
269 pstr = (char *)GlobalLock( pModule->nrname_handle );
270 while (*pstr)
272 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
273 *(WORD *)(pstr + *pstr + 1) );
274 pstr += *pstr + 1 + sizeof(WORD);
277 printf( "\n" );
281 /***********************************************************************
282 * MODULE_WalkModules
284 * Walk the module list and print the modules.
286 void MODULE_WalkModules(void)
288 HMODULE hModule = hFirstModule;
289 fprintf( stderr, "Module Flags Name\n" );
290 while (hModule)
292 NE_MODULE *pModule = MODULE_GetPtr( hModule );
293 if (!pModule)
295 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
296 return;
298 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
299 *((char *)pModule + pModule->name_table),
300 (char *)pModule + pModule->name_table + 1 );
301 hModule = pModule->next;
306 /***********************************************************************
307 * MODULE_OpenFile
309 int MODULE_OpenFile( HMODULE hModule )
311 NE_MODULE *pModule;
312 char *name;
313 const char *unixName;
315 static int cachedfd = -1;
317 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
318 dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
319 hModule, hCachedModule, cachedfd );
320 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
321 if (hCachedModule == hModule) return cachedfd;
322 close( cachedfd );
323 hCachedModule = hModule;
324 name = NE_MODULE_NAME( pModule );
325 if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
326 (cachedfd = open( unixName, O_RDONLY )) == -1)
327 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
328 name, hModule );
329 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
330 name, cachedfd );
331 return cachedfd;
335 /***********************************************************************
336 * MODULE_Ne2MemFlags
338 * This function translates NE segment flags to GlobalAlloc flags
340 static WORD MODULE_Ne2MemFlags(WORD flags)
342 WORD memflags = 0;
343 #if 0
344 if (flags & NE_SEGFLAGS_DISCARDABLE)
345 memflags |= GMEM_DISCARDABLE;
346 if (flags & NE_SEGFLAGS_MOVEABLE ||
347 ( ! (flags & NE_SEGFLAGS_DATA) &&
348 ! (flags & NE_SEGFLAGS_LOADED) &&
349 ! (flags & NE_SEGFLAGS_ALLOCATED)
352 memflags |= GMEM_MOVEABLE;
353 memflags |= GMEM_ZEROINIT;
354 #else
355 memflags = GMEM_ZEROINIT | GMEM_FIXED;
356 return memflags;
357 #endif
360 /***********************************************************************
361 * MODULE_AllocateSegment (WINPROCS.26)
364 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
366 WORD size = wSize << wElem;
367 HANDLE hMem = GlobalAlloc( MODULE_Ne2MemFlags(wFlags), size);
368 #ifdef WINELIB32
369 return (DWORD)GlobalLock(hMem);
370 #else
371 WORD selector = HIWORD(GlobalLock(hMem));
372 return MAKELONG(hMem, selector);
373 #endif
376 /***********************************************************************
377 * MODULE_CreateSegments
379 #ifndef WINELIB32
380 static BOOL MODULE_CreateSegments( HMODULE hModule )
382 SEGTABLEENTRY *pSegment;
383 NE_MODULE *pModule;
384 int i, minsize;
386 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
387 pSegment = NE_SEG_TABLE( pModule );
388 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
390 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
391 if (i == pModule->ss) minsize += pModule->stack_size;
392 /* The DGROUP is allocated by MODULE_CreateInstance */
393 if (i == pModule->dgroup) continue;
394 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
395 minsize, hModule,
396 !(pSegment->flags & NE_SEGFLAGS_DATA),
397 FALSE,
398 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
399 if (!pSegment->selector) return FALSE;
402 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
403 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
404 return TRUE;
406 #endif
409 /***********************************************************************
410 * MODULE_GetInstance
412 #ifndef WINELIB32
413 static HINSTANCE MODULE_GetInstance( HMODULE hModule )
415 SEGTABLEENTRY *pSegment;
416 NE_MODULE *pModule;
418 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
419 if (pModule->dgroup == 0) return hModule;
421 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
423 return pSegment->selector;
425 #endif
428 /***********************************************************************
429 * MODULE_CreateInstance
431 HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
433 SEGTABLEENTRY *pSegment;
434 NE_MODULE *pModule;
435 int minsize;
436 HINSTANCE hNewInstance, hPrevInstance;
438 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
439 if (pModule->dgroup == 0) return hModule;
441 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
442 hPrevInstance = pSegment->selector;
444 /* if it's a library, create a new instance only the first time */
445 if (hPrevInstance)
447 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
448 if (params == (LOADPARAMS*)-1) return hPrevInstance;
451 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
452 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
453 minsize += pModule->heap_size;
454 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
455 minsize, hModule, FALSE, FALSE, FALSE );
456 if (!hNewInstance) return 0;
457 pSegment->selector = hNewInstance;
458 return hNewInstance;
462 /***********************************************************************
463 * MODULE_LoadExeHeader
465 HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
467 struct mz_header_s mz_header;
468 struct ne_header_s ne_header;
469 int size;
470 HMODULE hModule;
471 NE_MODULE *pModule;
472 BYTE *pData;
473 char *buffer, *fastload = NULL;
474 int fastload_offset = 0, fastload_length = 0;
476 /* Read a block from either the file or the fast-load area. */
477 #define READ(offset,size,buffer) \
478 ((fastload && ((offset) >= fastload_offset) && \
479 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
480 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
481 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
482 FILE_Read( hFile, (buffer), (size) ) == (size)))
484 _llseek( hFile, 0, SEEK_SET );
485 if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
486 (mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11; /* invalid exe */
488 _llseek( hFile, mz_header.ne_offset, SEEK_SET );
489 if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
490 return (HMODULE)11; /* invalid exe */
492 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21; /* win32 exe */
493 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE)11; /* invalid exe */
495 /* We now have a valid NE header */
497 size = sizeof(NE_MODULE) +
498 /* loaded file info */
499 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
500 /* segment table */
501 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
502 /* resource table */
503 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
504 /* resident names table */
505 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
506 /* module ref table */
507 ne_header.n_mod_ref_tab * sizeof(WORD) +
508 /* imported names table */
509 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
510 /* entry table length */
511 ne_header.entry_tab_length;
513 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
514 if (!hModule) return (HMODULE)11; /* invalid exe */
515 FarSetOwner( hModule, hModule );
516 pModule = (NE_MODULE *)GlobalLock( hModule );
517 memcpy( pModule, &ne_header, sizeof(ne_header) );
518 pModule->count = 0;
519 pModule->pe_module = NULL;
520 pModule->self = hModule;
521 pModule->self_loading_sel = 0;
522 pData = (BYTE *)(pModule + 1);
524 /* Clear internal Wine flags in case they are set in the EXE file */
526 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
528 /* Read the fast-load area */
530 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
532 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
533 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
534 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
535 fastload_offset, fastload_length );
536 if ((fastload = (char *)malloc( fastload_length )) != NULL)
538 _llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET );
539 if (FILE_Read( hFile, fastload, fastload_length ) != fastload_length)
541 free( fastload );
542 fastload = NULL;
547 /* Store the filename information */
549 pModule->fileinfo = (int)pData - (int)pModule;
550 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
551 memcpy( pData, ofs, size );
552 ((OFSTRUCT *)pData)->cBytes = size - 1;
553 pData += size;
555 /* Get the segment table */
557 pModule->seg_table = (int)pData - (int)pModule;
558 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
559 if (buffer)
561 int i;
562 struct ne_segment_table_entry_s *pSeg;
564 if (!READ( ne_header.segment_tab_offset,
565 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
566 buffer )) return (HMODULE)11; /* invalid exe */
567 pSeg = (struct ne_segment_table_entry_s *)buffer;
568 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
570 memcpy( pData, pSeg, sizeof(*pSeg) );
571 pData += sizeof(SEGTABLEENTRY);
573 free( buffer );
575 else
577 GlobalFree( hModule );
578 return (HMODULE)11; /* invalid exe */
581 /* Get the resource table */
583 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
585 pModule->res_table = (int)pData - (int)pModule;
586 if (!READ(ne_header.resource_tab_offset,
587 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
588 pData )) return (HMODULE)11; /* invalid exe */
589 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
591 else pModule->res_table = 0; /* No resource table */
593 /* Get the resident names table */
595 pModule->name_table = (int)pData - (int)pModule;
596 if (!READ( ne_header.rname_tab_offset,
597 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
598 pData ))
600 GlobalFree( hModule );
601 return (HMODULE)11; /* invalid exe */
603 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
605 /* Get the module references table */
607 if (ne_header.n_mod_ref_tab > 0)
609 pModule->modref_table = (int)pData - (int)pModule;
610 if (!READ( ne_header.moduleref_tab_offset,
611 ne_header.n_mod_ref_tab * sizeof(WORD),
612 pData )) return (HMODULE)11; /* invalid exe */
613 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
615 else pModule->modref_table = 0; /* No module references */
617 /* Get the imported names table */
619 pModule->import_table = (int)pData - (int)pModule;
620 if (!READ( ne_header.iname_tab_offset,
621 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
622 pData ))
624 GlobalFree( hModule );
625 return (HMODULE)11; /* invalid exe */
627 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
629 /* Get the entry table */
631 pModule->entry_table = (int)pData - (int)pModule;
632 if (!READ( ne_header.entry_tab_offset,
633 ne_header.entry_tab_length,
634 pData ))
636 GlobalFree( hModule );
637 return (HMODULE)11; /* invalid exe */
639 pData += ne_header.entry_tab_length;
641 /* Get the non-resident names table */
643 if (ne_header.nrname_tab_length)
645 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
646 hModule, FALSE, FALSE, FALSE );
647 if (!pModule->nrname_handle)
649 GlobalFree( hModule );
650 return (HMODULE)11; /* invalid exe */
652 buffer = GlobalLock( pModule->nrname_handle );
653 _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
654 if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length )
655 != ne_header.nrname_tab_length)
657 GlobalFree( pModule->nrname_handle );
658 GlobalFree( hModule );
659 return (HMODULE)11; /* invalid exe */
662 else pModule->nrname_handle = 0;
664 /* Allocate a segment for the implicitly-loaded DLLs */
666 if (pModule->modref_count)
668 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
669 (pModule->modref_count+1)*sizeof(HMODULE),
670 hModule, FALSE, FALSE, FALSE );
671 if (!pModule->dlls_to_init)
673 if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
674 GlobalFree( hModule );
675 return (HMODULE)11; /* invalid exe */
678 else pModule->dlls_to_init = 0;
680 pModule->next = hFirstModule;
681 hFirstModule = hModule;
682 return hModule;
683 #undef READ
687 /***********************************************************************
688 * MODULE_GetOrdinal
690 * Lookup the ordinal for a given name.
692 WORD MODULE_GetOrdinal( HMODULE hModule, const char *name )
694 char buffer[256], *cpnt;
695 BYTE len;
696 NE_MODULE *pModule;
698 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
700 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
701 hModule, name );
703 /* First handle names of the form '#xxxx' */
705 if (name[0] == '#') return atoi( name + 1 );
707 /* Now copy and uppercase the string */
709 strcpy( buffer, name );
710 AnsiUpper( buffer );
711 len = strlen( buffer );
713 /* First search the resident names */
715 cpnt = (char *)pModule + pModule->name_table;
717 /* Skip the first entry (module name) */
718 cpnt += *cpnt + 1 + sizeof(WORD);
719 while (*cpnt)
721 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
723 dprintf_module( stddeb, " Found: ordinal=%d\n",
724 *(WORD *)(cpnt + *cpnt + 1) );
725 return *(WORD *)(cpnt + *cpnt + 1);
727 cpnt += *cpnt + 1 + sizeof(WORD);
730 /* Now search the non-resident names table */
732 if (!pModule->nrname_handle) return 0; /* No non-resident table */
733 cpnt = (char *)GlobalLock( pModule->nrname_handle );
735 /* Skip the first entry (module description string) */
736 cpnt += *cpnt + 1 + sizeof(WORD);
737 while (*cpnt)
739 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
741 dprintf_module( stddeb, " Found: ordinal=%d\n",
742 *(WORD *)(cpnt + *cpnt + 1) );
743 return *(WORD *)(cpnt + *cpnt + 1);
745 cpnt += *cpnt + 1 + sizeof(WORD);
747 return 0;
751 /***********************************************************************
752 * MODULE_GetEntryPoint
754 * Return the entry point for a given ordinal.
756 SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
758 NE_MODULE *pModule;
759 WORD curOrdinal = 1;
760 BYTE *p;
761 WORD sel, offset;
763 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
765 p = (BYTE *)pModule + pModule->entry_table;
766 while (*p && (curOrdinal + *p <= ordinal))
768 /* Skipping this bundle */
769 curOrdinal += *p;
770 switch(p[1])
772 case 0: p += 2; break; /* unused */
773 case 0xff: p += 2 + *p * 6; break; /* moveable */
774 default: p += 2 + *p * 3; break; /* fixed */
777 if (!*p) return 0;
779 switch(p[1])
781 case 0: /* unused */
782 return 0;
783 case 0xff: /* moveable */
784 p += 2 + 6 * (ordinal - curOrdinal);
785 sel = p[3];
786 offset = *(WORD *)(p + 4);
787 break;
788 default: /* fixed */
789 sel = p[1];
790 p += 2 + 3 * (ordinal - curOrdinal);
791 offset = *(WORD *)(p + 1);
792 break;
795 if (sel == 0xfe) sel = 0xffff; /* constant entry */
796 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
797 return (SEGPTR)MAKELONG( offset, sel );
801 /***********************************************************************
802 * MODULE_SetEntryPoint
804 * Change the value of an entry point. Use with caution!
805 * It can only change the offset value, not the selector.
807 BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset )
809 NE_MODULE *pModule;
810 WORD curOrdinal = 1;
811 BYTE *p;
813 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
815 p = (BYTE *)pModule + pModule->entry_table;
816 while (*p && (curOrdinal + *p <= ordinal))
818 /* Skipping this bundle */
819 curOrdinal += *p;
820 switch(p[1])
822 case 0: p += 2; break; /* unused */
823 case 0xff: p += 2 + *p * 6; break; /* moveable */
824 default: p += 2 + *p * 3; break; /* fixed */
827 if (!*p) return FALSE;
829 switch(p[1])
831 case 0: /* unused */
832 return FALSE;
833 case 0xff: /* moveable */
834 p += 2 + 6 * (ordinal - curOrdinal);
835 *(WORD *)(p + 4) = offset;
836 break;
837 default: /* fixed */
838 p += 2 + 3 * (ordinal - curOrdinal);
839 *(WORD *)(p + 1) = offset;
840 break;
842 return TRUE;
846 /***********************************************************************
847 * MODULE_GetEntryPointName
849 * Return the entry point name for a given ordinal.
850 * Used only by relay debugging.
851 * Warning: returned pointer is to a Pascal-type string.
853 LPSTR MODULE_GetEntryPointName( HMODULE hModule, WORD ordinal )
855 register char *cpnt;
856 NE_MODULE *pModule;
858 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
860 /* First search the resident names */
862 cpnt = (char *)pModule + pModule->name_table;
863 while (*cpnt)
865 cpnt += *cpnt + 1 + sizeof(WORD);
866 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
869 /* Now search the non-resident names table */
871 if (!pModule->nrname_handle) return 0; /* No non-resident table */
872 cpnt = (char *)GlobalLock( pModule->nrname_handle );
873 while (*cpnt)
875 cpnt += *cpnt + 1 + sizeof(WORD);
876 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
878 return NULL;
882 /***********************************************************************
883 * MODULE_GetWndProcEntry16 (not a Windows API function)
885 * Return an entry point from the WINPROCS dll.
887 #ifndef WINELIB
888 WNDPROC MODULE_GetWndProcEntry16( const char *name )
890 WORD ordinal;
891 static HMODULE hModule = 0;
893 if (!hModule) hModule = GetModuleHandle( "WINPROCS" );
894 ordinal = MODULE_GetOrdinal( hModule, name );
895 return MODULE_GetEntryPoint( hModule, ordinal );
897 #endif
900 /***********************************************************************
901 * MODULE_GetWndProcEntry32 (not a Windows API function)
903 * Return an entry point from the WINPROCS32 dll.
905 #ifndef WINELIB
906 WNDPROC MODULE_GetWndProcEntry32( const char *name )
908 static HMODULE hModule = 0;
910 if (!hModule) hModule = GetModuleHandle( "WINPROCS32" );
911 return PE_GetProcAddress( hModule, name );
913 #endif
916 /***********************************************************************
917 * MODULE_GetModuleName
919 LPSTR MODULE_GetModuleName( HMODULE hModule )
921 NE_MODULE *pModule;
922 BYTE *p, len;
923 static char buffer[10];
925 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
926 p = (BYTE *)pModule + pModule->name_table;
927 len = MIN( *p, 8 );
928 memcpy( buffer, p + 1, len );
929 buffer[len] = '\0';
930 return buffer;
934 /**********************************************************************
935 * MODULE_RegisterModule
937 void MODULE_RegisterModule( HMODULE hModule )
939 NE_MODULE *pModule = MODULE_GetPtr( hModule );
940 pModule->next = hFirstModule;
941 hFirstModule = hModule;
944 /**********************************************************************
945 * MODULE_FindModule
947 * Find a module from a path name.
949 HMODULE MODULE_FindModule( LPCSTR path )
951 HMODULE hModule = hFirstModule;
952 LPCSTR filename, dotptr, modulepath, modulename;
953 BYTE len, *name_table;
955 if (!(filename = strrchr( path, '\\' ))) filename = path;
956 else filename++;
957 if ((dotptr = strrchr( filename, '.' )) != NULL)
958 len = (BYTE)(dotptr - filename);
959 else len = strlen( filename );
961 while(hModule)
963 NE_MODULE *pModule = MODULE_GetPtr( hModule );
964 if (!pModule) break;
965 modulepath = NE_MODULE_NAME(pModule);
966 if (!(modulename = strrchr( modulepath, '\\' )))
967 modulename = modulepath;
968 else modulename++;
969 if (!lstrcmpi( modulename, filename )) return hModule;
971 name_table = (BYTE *)pModule + pModule->name_table;
972 if ((*name_table == len) && !lstrncmpi(filename, name_table+1, len))
973 return hModule;
974 hModule = pModule->next;
976 return 0;
980 /**********************************************************************
981 * MODULE_FreeModule
983 * Remove a module from memory.
985 static void MODULE_FreeModule( HMODULE hModule )
987 HMODULE *hPrevModule;
988 NE_MODULE *pModule;
989 SEGTABLEENTRY *pSegment;
990 HMODULE *pModRef;
991 int i;
993 if (!(pModule = MODULE_GetPtr( hModule ))) return;
994 if (pModule->flags & NE_FFLAGS_BUILTIN)
995 return; /* Can't free built-in module */
997 /* FIXME: should call the exit code for the library here */
999 /* Clear magic number just in case */
1001 pModule->magic = pModule->self = 0;
1003 /* Remove it from the linked list */
1005 hPrevModule = &hFirstModule;
1006 while (*hPrevModule && (*hPrevModule != hModule))
1008 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
1010 if (*hPrevModule) *hPrevModule = pModule->next;
1012 /* Free all the segments */
1014 pSegment = NE_SEG_TABLE( pModule );
1015 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
1017 GlobalFree( pSegment->selector );
1020 /* Free the referenced modules */
1022 pModRef = (HMODULE*)NE_MODULE_TABLE( pModule );
1023 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1025 FreeModule( *pModRef );
1028 /* Free the module storage */
1030 if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
1031 if (pModule->dlls_to_init) GlobalFree( pModule->dlls_to_init );
1032 GlobalFree( hModule );
1034 /* Remove module from cache */
1036 if (hCachedModule == hModule) hCachedModule = 0;
1040 /**********************************************************************
1041 * LoadModule (KERNEL.45)
1043 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
1045 HMODULE hModule;
1046 HANDLE hInstance, hPrevInstance;
1047 NE_MODULE *pModule;
1048 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1049 #ifndef WINELIB
1050 WORD *pModRef, *pDLLs;
1051 HFILE hFile;
1052 int i;
1054 hModule = MODULE_FindModule( name );
1056 if (!hModule) /* We have to load the module */
1058 OFSTRUCT ofs;
1060 /* Try to load the built-in first if not disabled */
1061 if ((hModule = MODULE_LoadBuiltin( name, FALSE ))) return hModule;
1063 if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR)
1065 /* Now try the built-in even if disabled */
1066 if ((hModule = MODULE_LoadBuiltin( name, TRUE )))
1068 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1069 return hModule;
1071 return 2; /* File not found */
1074 /* Create the module structure */
1076 hModule = MODULE_LoadExeHeader( hFile, &ofs );
1077 if (hModule < 32)
1079 /* FIXME: Hack because PE_LoadModule is recursive */
1080 int fd = dup( FILE_GetUnixHandle(hFile) );
1081 _lclose( hFile );
1082 if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
1083 close( fd );
1084 if (hModule < 32)
1085 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1086 name, hModule );
1087 return hModule;
1089 _lclose( hFile );
1090 pModule = MODULE_GetPtr( hModule );
1092 /* Allocate the segments for this module */
1094 MODULE_CreateSegments( hModule );
1096 hPrevInstance = 0;
1097 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1099 /* Load the referenced DLLs */
1101 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
1102 pDLLs = (WORD *)GlobalLock( pModule->dlls_to_init );
1103 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1105 char buffer[256];
1106 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
1107 memcpy( buffer, pstr + 1, *pstr );
1108 strcpy( buffer + *pstr, ".dll" );
1109 dprintf_module( stddeb, "Loading '%s'\n", buffer );
1110 if (!(*pModRef = MODULE_FindModule( buffer )))
1112 /* If the DLL is not loaded yet, load it and store */
1113 /* its handle in the list of DLLs to initialize. */
1114 HMODULE hDLL;
1116 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
1118 char *p;
1120 /* Try with prepending the path of the current module */
1121 GetModuleFileName( hModule, buffer, 256 );
1122 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1123 memcpy( p + 1, pstr + 1, *pstr );
1124 strcpy( p + 1 + *pstr, ".dll" );
1125 hDLL = LoadModule( buffer, (LPVOID)-1 );
1127 if (hDLL < 32)
1129 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1130 buffer, name, hDLL );
1131 return 2; /* file not found */
1133 *pModRef = GetExePtr( hDLL );
1134 *pDLLs++ = *pModRef;
1136 else /* Increment the reference count of the DLL */
1138 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
1139 if (pOldDLL) pOldDLL->count++;
1143 /* Load the segments */
1145 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1147 int fd;
1148 /* Handle self loading modules */
1149 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1150 SELFLOADHEADER *selfloadheader;
1151 HMODULE hselfload = GetModuleHandle("WINPROCS");
1152 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1153 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1154 "Support for self-loading modules is very experimental\n",
1155 *((BYTE*)pModule + pModule->name_table),
1156 *((BYTE*)pModule + pModule->name_table),
1157 (char *)pModule + pModule->name_table + 1);
1158 NE_LoadSegment( hModule, 1 );
1159 selfloadheader = (SELFLOADHEADER *)
1160 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1161 selfloadheader->EntryAddrProc =
1162 MODULE_GetEntryPoint(hselfload,27);
1163 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1164 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1165 pModule->self_loading_sel = GlobalHandleToSel(
1166 GLOBAL_Alloc (GMEM_ZEROINIT,
1167 0xFF00, hModule, FALSE, FALSE, FALSE)
1169 oldss = IF1632_Saved16_ss;
1170 oldsp = IF1632_Saved16_sp;
1171 IF1632_Saved16_ss = pModule->self_loading_sel;
1172 IF1632_Saved16_sp = 0xFF00;
1173 if (!IF1632_Stack32_base) {
1174 STACK32FRAME* frame32;
1175 char *stack32Top;
1176 /* Setup an initial 32 bit stack frame */
1177 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1178 hModule, FALSE, FALSE,
1179 FALSE );
1181 /* Create the 32-bit stack frame */
1183 *(DWORD *)GlobalLock(hInitialStack32) = 0xDEADBEEF;
1184 stack32Top = (char*)GlobalLock(hInitialStack32) +
1185 0x10000;
1186 frame32 = (STACK32FRAME *)stack32Top - 1;
1187 frame32->saved_esp = (DWORD)stack32Top;
1188 frame32->edi = 0;
1189 frame32->esi = 0;
1190 frame32->edx = 0;
1191 frame32->ecx = 0;
1192 frame32->ebx = 0;
1193 frame32->ebp = 0;
1194 frame32->retaddr = 0;
1195 frame32->codeselector = WINE_CODE_SELECTOR;
1196 /* pTask->esp = (DWORD)frame32; */
1197 IF1632_Stack32_base = WIN16_GlobalLock(hInitialStack32);
1200 /* FIXME: we probably need a DOS handle here */
1201 fd = MODULE_OpenFile( hModule );
1202 CallTo16_word_ww (selfloadheader->BootApp,
1203 pModule->self_loading_sel, hModule, fd);
1204 /* some BootApp procs overwrite the selector of dgroup */
1205 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1206 IF1632_Saved16_ss = oldss;
1207 IF1632_Saved16_sp = oldsp;
1208 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1209 if (hInitialStack32){
1210 GlobalUnlock (hInitialStack32);
1211 GlobalFree (hInitialStack32);
1212 IF1632_Stack32_base = hInitialStack32 = 0;
1215 else
1217 for (i = 1; i <= pModule->seg_count; i++)
1218 NE_LoadSegment( hModule, i );
1221 /* Fixup the functions prologs */
1223 NE_FixupPrologs( pModule );
1225 /* Make sure the usage count is 1 on the first loading of */
1226 /* the module, even if it contains circular DLL references */
1228 pModule->count = 1;
1230 else
1232 pModule = MODULE_GetPtr( hModule );
1233 hPrevInstance = MODULE_GetInstance( hModule );
1234 hInstance = MODULE_CreateInstance( hModule, params );
1235 if (hInstance != hPrevInstance) /* not a library */
1236 NE_LoadSegment( hModule, pModule->dgroup );
1237 pModule->count++;
1239 #else
1240 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE) );
1241 pModule = (NE_MODULE *)GlobalLock( hModule );
1242 pModule->count = 1;
1243 pModule->magic = NE_SIGNATURE;
1244 pModule->self = hModule;
1245 hPrevInstance = 0;
1246 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1247 #endif /* WINELIB */
1249 /* Create a task for this instance */
1251 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1253 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1254 params->hEnvironment,
1255 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1256 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1259 return hInstance;
1263 /**********************************************************************
1264 * FreeModule (KERNEL.46)
1266 BOOL FreeModule( HANDLE hModule )
1268 NE_MODULE *pModule;
1270 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1271 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1273 dprintf_module( stddeb, "FreeModule: %s count %d\n",
1274 MODULE_GetModuleName(hModule), pModule->count );
1275 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1276 return TRUE;
1280 /**********************************************************************
1281 * GetModuleHandle (KERNEL.47)
1283 HMODULE WIN16_GetModuleHandle( SEGPTR name )
1285 if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
1286 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1289 HMODULE GetModuleHandle( LPCSTR name )
1291 return MODULE_FindModule( name );
1295 /**********************************************************************
1296 * GetModuleUsage (KERNEL.48)
1298 int GetModuleUsage( HANDLE hModule )
1300 NE_MODULE *pModule;
1302 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1303 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1304 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1305 hModule, pModule->count );
1306 return pModule->count;
1310 /**********************************************************************
1311 * GetModuleFileName (KERNEL.49)
1313 int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1315 NE_MODULE *pModule;
1317 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1318 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1319 lstrcpyn( lpFileName, NE_MODULE_NAME(pModule), nSize );
1320 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1321 return strlen(lpFileName);
1325 /***********************************************************************
1326 * LoadLibrary (KERNEL.95)
1328 HANDLE LoadLibrary( LPCSTR libname )
1330 #ifdef WINELIB
1331 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1332 WINELIB_UNIMP("LoadLibrary()");
1333 return (HANDLE)0;
1334 #else
1335 HANDLE handle;
1337 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1339 /* This does not increment the module reference count, and will
1340 * therefore cause crashes on FreeLibrary calls.
1341 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1343 handle = LoadModule( libname, (LPVOID)-1 );
1344 if (handle == (HANDLE)2) /* file not found */
1346 char buffer[256];
1347 lstrcpyn( buffer, libname, 252 );
1348 strcat( buffer, ".dll" );
1349 handle = LoadModule( buffer, (LPVOID)-1 );
1351 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
1352 return handle;
1353 #endif
1357 /***********************************************************************
1358 * FreeLibrary (KERNEL.96)
1360 void FreeLibrary( HANDLE handle )
1362 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1363 FreeModule( handle );
1367 /***********************************************************************
1368 * WinExec (KERNEL.166)
1370 HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1372 LOADPARAMS params;
1373 HLOCAL cmdShowHandle, cmdLineHandle;
1374 HANDLE handle;
1375 WORD *cmdShowPtr;
1376 char *p, *cmdline, filename[256];
1377 static int use_load_module = 1;
1379 if (!(cmdShowHandle = GlobalAlloc( 0, 2 * sizeof(WORD) ))) return 0;
1380 if (!(cmdLineHandle = GlobalAlloc( 0, 256 ))) return 0;
1382 /* Store nCmdShow */
1384 cmdShowPtr = (WORD *)GlobalLock( cmdShowHandle );
1385 cmdShowPtr[0] = 2;
1386 cmdShowPtr[1] = nCmdShow;
1388 /* Build the filename and command-line */
1390 cmdline = (char *)GlobalLock( cmdLineHandle );
1391 lstrcpyn( filename, lpCmdLine, sizeof(filename) - 4 /* for extension */ );
1392 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1393 if (*p) lstrcpyn( cmdline, p + 1, 128 );
1394 else cmdline[0] = '\0';
1395 *p = '\0';
1397 /* Now load the executable file */
1399 if (use_load_module)
1401 #ifdef WINELIB
1402 /* WINELIB: Use LoadModule() only for the program itself */
1403 use_load_module = 0;
1404 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1405 #else
1406 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1407 #endif /* WINELIB */
1408 params.cmdLine = (SEGPTR)WIN16_GlobalLock( cmdLineHandle );
1409 params.showCmd = (SEGPTR)WIN16_GlobalLock( cmdShowHandle );
1410 params.reserved = 0;
1411 handle = LoadModule( filename, &params );
1412 if (handle == 2) /* file not found */
1414 /* Check that the original file name did not have a suffix */
1415 p = strrchr(filename, '.');
1416 if (!p || (strchr(p, '/') && strchr(p, '\\')))
1418 p = filename + strlen(filename);
1419 strcpy( p, ".exe" );
1420 handle = LoadModule( filename, &params );
1421 *p = '\0'; /* Remove extension */
1425 else handle = 2;
1427 if (handle < 32)
1429 /* Try to start it as a unix program */
1430 if (!fork())
1432 /* Child process */
1433 const char *unixfilename;
1434 const char *argv[256], **argptr;
1435 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1436 nCmdShow == SW_SHOWMINNOACTIVE);
1438 /* get unixfilename */
1439 if (strchr(filename, '/') ||
1440 strchr(filename, ':') ||
1441 strchr(filename, '\\'))
1442 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1443 else unixfilename = filename;
1445 if (unixfilename)
1447 /* build argv */
1448 argptr = argv;
1449 if (iconic) *argptr++ = "-iconic";
1450 *argptr++ = unixfilename;
1451 p = cmdline;
1452 while (1)
1454 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1455 if (!*p) break;
1456 *argptr++ = p;
1457 while (*p && *p != ' ' && *p != '\t') p++;
1459 *argptr++ = 0;
1461 /* Execute */
1462 execvp(argv[0], (char**)argv);
1465 /* Failed ! */
1466 #ifdef WINELIB
1467 /* build argv */
1468 argptr = argv;
1469 *argptr++ = "wine";
1470 if (iconic) *argptr++ = "-iconic";
1471 *argptr++ = lpCmdLine;
1472 *argptr++ = 0;
1474 /* Execute */
1475 execvp(argv[0] , (char**)argv);
1477 /* Failed ! */
1478 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1479 #endif
1480 exit(1);
1484 GlobalFree( cmdShowHandle );
1485 GlobalFree( cmdLineHandle );
1487 #if 0
1488 if (handle < (HANDLE)32) /* Error? */
1489 return handle;
1491 /* FIXME: Yield never returns!
1492 We may want to run more applications or start the debugger
1493 before calling Yield. If we don't Yield will be called immdiately
1494 after returning. Why is it needed for Word anyway? */
1495 Yield(); /* program is executed immediately ....needed for word */
1497 #endif
1498 return handle;
1502 /***********************************************************************
1503 * GetProcAddress (KERNEL.50)
1505 FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
1507 WORD ordinal;
1508 SEGPTR ret;
1510 if (!hModule) hModule = GetCurrentTask();
1511 hModule = GetExePtr( hModule );
1513 if (HIWORD(name) != 0)
1515 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1516 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1517 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1519 else
1521 ordinal = LOWORD(name);
1522 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1523 hModule, ordinal );
1525 if (!ordinal) return (FARPROC)0;
1527 ret = MODULE_GetEntryPoint( hModule, ordinal );
1529 dprintf_module( stddeb, "GetProcAddress: returning %08lx\n", (DWORD)ret );
1530 return (FARPROC)ret;
1534 /**********************************************************************
1535 * GetExpWinVer (KERNEL.167)
1537 WORD GetExpWinVer( HMODULE hModule )
1539 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1540 return pModule ? pModule->expected_version : 0;
1544 /**********************************************************************
1545 * ModuleFirst (TOOLHELP.59)
1547 BOOL ModuleFirst( MODULEENTRY *lpme )
1549 lpme->wNext = hFirstModule;
1550 return ModuleNext( lpme );
1554 /**********************************************************************
1555 * ModuleNext (TOOLHELP.60)
1557 BOOL ModuleNext( MODULEENTRY *lpme )
1559 NE_MODULE *pModule;
1561 if (!lpme->wNext) return FALSE;
1562 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1563 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1564 MAX_MODULE_NAME );
1565 lpme->szModule[MAX_MODULE_NAME] = '\0';
1566 lpme->hModule = lpme->wNext;
1567 lpme->wcUsage = pModule->count;
1568 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1569 lpme->szExePath[MAX_PATH] = '\0';
1570 lpme->wNext = pModule->next;
1571 return TRUE;
1575 /**********************************************************************
1576 * ModuleFindName (TOOLHELP.61)
1578 BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1580 lpme->wNext = GetModuleHandle( name );
1581 return ModuleNext( lpme );
1585 /**********************************************************************
1586 * ModuleFindHandle (TOOLHELP.62)
1588 BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
1590 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1591 lpme->wNext = hModule;
1592 return ModuleNext( lpme );