Release 960717
[wine/multimedia.git] / loader / module.c
blob31a998bac9f64520a4dc4b0b9a1e97d7ba2680f5
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 "class.h"
15 #include "dos_fs.h"
16 #include "file.h"
17 #include "global.h"
18 #include "hook.h"
19 #include "ldt.h"
20 #include "module.h"
21 #include "neexe.h"
22 #include "registers.h"
23 #include "stackframe.h"
24 #include "task.h"
25 #include "toolhelp.h"
26 #include "stddebug.h"
27 #include "debug.h"
28 #include "callback.h"
30 extern HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
32 static HMODULE16 hFirstModule = 0;
33 static HMODULE16 hCachedModule = 0; /* Module cached by MODULE_OpenFile */
35 #ifndef WINELIB
36 static HANDLE hInitialStack32 = 0;
37 #endif
40 /***********************************************************************
41 * MODULE_GetPtr
43 NE_MODULE *MODULE_GetPtr( HMODULE16 hModule )
45 NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule );
46 if (!pModule || (pModule->magic != NE_SIGNATURE) ||
47 (pModule->self != hModule)) return NULL;
48 return pModule;
52 /***********************************************************************
53 * MODULE_DumpModule
55 void MODULE_DumpModule( HMODULE16 hmodule )
57 int i, ordinal;
58 SEGTABLEENTRY *pSeg;
59 BYTE *pstr;
60 WORD *pword;
61 NE_MODULE *pModule;
63 if (!(pModule = MODULE_GetPtr( hmodule )))
65 fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
66 return;
69 /* Dump the module info */
71 printf( "Module %04x:\n", hmodule );
72 printf( "count=%d flags=%04x heap=%d stack=%d\n",
73 pModule->count, pModule->flags,
74 pModule->heap_size, pModule->stack_size );
75 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
76 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
77 pModule->seg_count, pModule->modref_count );
78 printf( "os_flags=%d swap_area=%d version=%04x\n",
79 pModule->os_flags, pModule->min_swap_area,
80 pModule->expected_version );
81 if (pModule->flags & NE_FFLAGS_WIN32)
82 printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
84 /* Dump the file info */
86 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
88 /* Dump the segment table */
90 printf( "\nSegment table:\n" );
91 pSeg = NE_SEG_TABLE( pModule );
92 for (i = 0; i < pModule->seg_count; i++, pSeg++)
93 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
94 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
95 pSeg->minsize, pSeg->selector );
97 /* Dump the resource table */
99 printf( "\nResource table:\n" );
100 if (pModule->res_table)
102 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
103 printf( "Alignment: %d\n", *pword++ );
104 while (*pword)
106 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
107 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
108 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
109 for (i = 0; i < ptr->count; i++, pname++)
110 printf( "offset=%d len=%d id=%04x\n",
111 pname->offset, pname->length, pname->id );
112 pword = (WORD *)pname;
115 else printf( "None\n" );
117 /* Dump the resident name table */
119 printf( "\nResident-name table:\n" );
120 pstr = (char *)pModule + pModule->name_table;
121 while (*pstr)
123 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
124 *(WORD *)(pstr + *pstr + 1) );
125 pstr += *pstr + 1 + sizeof(WORD);
128 /* Dump the module reference table */
130 printf( "\nModule ref table:\n" );
131 if (pModule->modref_table)
133 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
134 for (i = 0; i < pModule->modref_count; i++, pword++)
136 printf( "%d: %04x -> '%s'\n", i, *pword,
137 MODULE_GetModuleName(*pword));
140 else printf( "None\n" );
142 /* Dump the entry table */
144 printf( "\nEntry table:\n" );
145 pstr = (char *)pModule + pModule->entry_table;
146 ordinal = 1;
147 while (*pstr)
149 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
150 if (!pstr[1])
152 ordinal += *pstr;
153 pstr += 2;
155 else if ((BYTE)pstr[1] == 0xff) /* moveable */
157 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
158 for (i = 0; i < *pstr; i++, pe++)
159 printf( "%d: %02x:%04x (moveable)\n",
160 ordinal++, pe->seg_number, pe->offset );
161 pstr = (char *)pe;
163 else /* fixed */
165 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
166 for (i = 0; i < *pstr; i++, pe++)
167 printf( "%d: %04x (fixed)\n",
168 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
169 pstr = (char *)pe;
173 /* Dump the non-resident names table */
175 printf( "\nNon-resident names table:\n" );
176 if (pModule->nrname_handle)
178 pstr = (char *)GlobalLock16( pModule->nrname_handle );
179 while (*pstr)
181 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
182 *(WORD *)(pstr + *pstr + 1) );
183 pstr += *pstr + 1 + sizeof(WORD);
186 printf( "\n" );
190 /***********************************************************************
191 * MODULE_WalkModules
193 * Walk the module list and print the modules.
195 void MODULE_WalkModules(void)
197 HMODULE16 hModule = hFirstModule;
198 fprintf( stderr, "Module Flags Name\n" );
199 while (hModule)
201 NE_MODULE *pModule = MODULE_GetPtr( hModule );
202 if (!pModule)
204 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
205 return;
207 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
208 *((char *)pModule + pModule->name_table),
209 (char *)pModule + pModule->name_table + 1 );
210 hModule = pModule->next;
215 /***********************************************************************
216 * MODULE_OpenFile
218 int MODULE_OpenFile( HMODULE16 hModule )
220 NE_MODULE *pModule;
221 char *name;
222 const char *unixName;
224 static int cachedfd = -1;
226 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
227 dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
228 hModule, hCachedModule, cachedfd );
229 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
230 if (hCachedModule == hModule) return cachedfd;
231 close( cachedfd );
232 hCachedModule = hModule;
233 name = NE_MODULE_NAME( pModule );
234 if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
235 (cachedfd = open( unixName, O_RDONLY )) == -1)
236 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
237 name, hModule );
238 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
239 name, cachedfd );
240 return cachedfd;
244 /***********************************************************************
245 * MODULE_Ne2MemFlags
247 * This function translates NE segment flags to GlobalAlloc flags
249 static WORD MODULE_Ne2MemFlags(WORD flags)
251 WORD memflags = 0;
252 #if 0
253 if (flags & NE_SEGFLAGS_DISCARDABLE)
254 memflags |= GMEM_DISCARDABLE;
255 if (flags & NE_SEGFLAGS_MOVEABLE ||
256 ( ! (flags & NE_SEGFLAGS_DATA) &&
257 ! (flags & NE_SEGFLAGS_LOADED) &&
258 ! (flags & NE_SEGFLAGS_ALLOCATED)
261 memflags |= GMEM_MOVEABLE;
262 memflags |= GMEM_ZEROINIT;
263 #else
264 memflags = GMEM_ZEROINIT | GMEM_FIXED;
265 return memflags;
266 #endif
269 /***********************************************************************
270 * MODULE_AllocateSegment (WPROCS.26)
273 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
275 WORD size = wSize << wElem;
276 HANDLE hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
277 #ifdef WINELIB
278 return (DWORD)GlobalLock16(hMem);
279 #else
280 WORD selector = HIWORD(WIN16_GlobalLock16(hMem));
281 return MAKELONG(hMem, selector);
282 #endif
285 /***********************************************************************
286 * MODULE_CreateSegments
288 #ifndef WINELIB32
289 static BOOL MODULE_CreateSegments( HMODULE16 hModule )
291 SEGTABLEENTRY *pSegment;
292 NE_MODULE *pModule;
293 int i, minsize;
295 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
296 pSegment = NE_SEG_TABLE( pModule );
297 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
299 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
300 if (i == pModule->ss) minsize += pModule->stack_size;
301 /* The DGROUP is allocated by MODULE_CreateInstance */
302 if (i == pModule->dgroup) continue;
303 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
304 minsize, hModule,
305 !(pSegment->flags & NE_SEGFLAGS_DATA),
306 FALSE,
307 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
308 if (!pSegment->selector) return FALSE;
311 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
312 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
313 return TRUE;
315 #endif
318 /***********************************************************************
319 * MODULE_GetInstance
321 #ifndef WINELIB32
322 HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule )
324 SEGTABLEENTRY *pSegment;
325 NE_MODULE *pModule;
327 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
328 if (pModule->dgroup == 0) return hModule;
330 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
332 return pSegment->selector;
334 #endif
337 /***********************************************************************
338 * MODULE_CreateInstance
340 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
342 SEGTABLEENTRY *pSegment;
343 NE_MODULE *pModule;
344 int minsize;
345 HINSTANCE hNewInstance, hPrevInstance;
347 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
348 if (pModule->dgroup == 0) return hModule;
350 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
351 hPrevInstance = pSegment->selector;
353 /* if it's a library, create a new instance only the first time */
354 if (hPrevInstance)
356 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
357 if (params == (LOADPARAMS*)-1) return hPrevInstance;
360 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
361 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
362 minsize += pModule->heap_size;
363 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
364 minsize, hModule, FALSE, FALSE, FALSE );
365 if (!hNewInstance) return 0;
366 pSegment->selector = hNewInstance;
367 return hNewInstance;
371 /***********************************************************************
372 * MODULE_CreateDummyModule
374 * Create a dummy NE module for Win32 or Winelib.
376 HMODULE16 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
378 HMODULE16 hModule;
379 NE_MODULE *pModule;
380 SEGTABLEENTRY *pSegment;
381 char *pStr;
383 INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
384 + strlen(ofs->szPathName) + 1;
385 INT32 size = sizeof(NE_MODULE) +
386 /* loaded file info */
387 of_size +
388 /* segment table: DS,CS */
389 2 * sizeof(SEGTABLEENTRY) +
390 /* name table */
392 /* several empty tables */
395 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
396 if (!hModule) return (HMODULE16)11; /* invalid exe */
398 FarSetOwner( hModule, hModule );
399 pModule = (NE_MODULE *)GlobalLock16( hModule );
401 /* Set all used entries */
402 pModule->magic = NE_SIGNATURE;
403 pModule->count = 1;
404 pModule->next = 0;
405 pModule->flags = 0;
406 pModule->dgroup = 1;
407 pModule->ss = 1;
408 pModule->cs = 2;
409 pModule->heap_size = 0xe000;
410 pModule->stack_size = 0x1000;
411 pModule->seg_count = 2;
412 pModule->modref_count = 0;
413 pModule->nrname_size = 0;
414 pModule->fileinfo = sizeof(NE_MODULE);
415 pModule->os_flags = NE_OSFLAGS_WINDOWS;
416 pModule->expected_version = 0x030a;
417 pModule->self = hModule;
419 /* Set loaded file information */
420 memcpy( pModule + 1, ofs, of_size );
421 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
423 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
424 pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
425 /* Data segment */
426 pSegment->size = 0;
427 pSegment->flags = NE_SEGFLAGS_DATA;
428 pSegment->minsize = 0x1000;
429 pSegment++;
430 /* Code segment */
431 pSegment->flags = 0;
432 pSegment++;
434 /* Module name */
435 pStr = (char *)pSegment;
436 pModule->name_table = (int)pStr - (int)pModule;
437 strcpy( pStr, "\x08W32SXXXX" );
438 pStr += 9;
440 /* All tables zero terminated */
441 pModule->res_table = pModule->import_table = pModule->entry_table =
442 (int)pStr - (int)pModule;
444 MODULE_RegisterModule( pModule );
445 return hModule;
449 /***********************************************************************
450 * MODULE_LoadExeHeader
452 static HMODULE16 MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
454 struct mz_header_s mz_header;
455 struct ne_header_s ne_header;
456 int size;
457 HMODULE16 hModule;
458 NE_MODULE *pModule;
459 BYTE *pData;
460 char *buffer, *fastload = NULL;
461 int fastload_offset = 0, fastload_length = 0;
463 /* Read a block from either the file or the fast-load area. */
464 #define READ(offset,size,buffer) \
465 ((fastload && ((offset) >= fastload_offset) && \
466 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
467 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
468 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
469 FILE_Read( hFile, (buffer), (size) ) == (size)))
471 _llseek( hFile, 0, SEEK_SET );
472 if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
473 (mz_header.mz_magic != MZ_SIGNATURE))
474 return (HMODULE16)11; /* invalid exe */
476 _llseek( hFile, mz_header.ne_offset, SEEK_SET );
477 if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
478 return (HMODULE16)11; /* invalid exe */
480 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE16)21; /* win32 exe */
481 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE16)11; /* invalid exe */
483 /* We now have a valid NE header */
485 size = sizeof(NE_MODULE) +
486 /* loaded file info */
487 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
488 /* segment table */
489 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
490 /* resource table */
491 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
492 /* resident names table */
493 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
494 /* module ref table */
495 ne_header.n_mod_ref_tab * sizeof(WORD) +
496 /* imported names table */
497 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
498 /* entry table length */
499 ne_header.entry_tab_length;
501 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
502 if (!hModule) return (HMODULE16)11; /* invalid exe */
503 FarSetOwner( hModule, hModule );
504 pModule = (NE_MODULE *)GlobalLock16( hModule );
505 memcpy( pModule, &ne_header, sizeof(ne_header) );
506 pModule->count = 0;
507 pModule->pe_module = NULL;
508 pModule->self = hModule;
509 pModule->self_loading_sel = 0;
510 pData = (BYTE *)(pModule + 1);
512 /* Clear internal Wine flags in case they are set in the EXE file */
514 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
516 /* Read the fast-load area */
518 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
520 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
521 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
522 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
523 fastload_offset, fastload_length );
524 if ((fastload = (char *)malloc( fastload_length )) != NULL)
526 _llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET );
527 if (FILE_Read( hFile, fastload, fastload_length ) != fastload_length)
529 free( fastload );
530 fastload = NULL;
535 /* Store the filename information */
537 pModule->fileinfo = (int)pData - (int)pModule;
538 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
539 memcpy( pData, ofs, size );
540 ((OFSTRUCT *)pData)->cBytes = size - 1;
541 pData += size;
543 /* Get the segment table */
545 pModule->seg_table = (int)pData - (int)pModule;
546 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
547 if (buffer)
549 int i;
550 struct ne_segment_table_entry_s *pSeg;
552 if (!READ( ne_header.segment_tab_offset,
553 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
554 buffer )) return (HMODULE16)11; /* invalid exe */
555 pSeg = (struct ne_segment_table_entry_s *)buffer;
556 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
558 memcpy( pData, pSeg, sizeof(*pSeg) );
559 pData += sizeof(SEGTABLEENTRY);
561 free( buffer );
563 else
565 GlobalFree16( hModule );
566 return (HMODULE16)11; /* invalid exe */
569 /* Get the resource table */
571 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
573 pModule->res_table = (int)pData - (int)pModule;
574 if (!READ(ne_header.resource_tab_offset,
575 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
576 pData )) return (HMODULE16)11; /* invalid exe */
577 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
579 else pModule->res_table = 0; /* No resource table */
581 /* Get the resident names table */
583 pModule->name_table = (int)pData - (int)pModule;
584 if (!READ( ne_header.rname_tab_offset,
585 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
586 pData ))
588 GlobalFree16( hModule );
589 return (HMODULE16)11; /* invalid exe */
591 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
593 /* Get the module references table */
595 if (ne_header.n_mod_ref_tab > 0)
597 pModule->modref_table = (int)pData - (int)pModule;
598 if (!READ( ne_header.moduleref_tab_offset,
599 ne_header.n_mod_ref_tab * sizeof(WORD),
600 pData )) return (HMODULE16)11; /* invalid exe */
601 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
603 else pModule->modref_table = 0; /* No module references */
605 /* Get the imported names table */
607 pModule->import_table = (int)pData - (int)pModule;
608 if (!READ( ne_header.iname_tab_offset,
609 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
610 pData ))
612 GlobalFree16( hModule );
613 return (HMODULE16)11; /* invalid exe */
615 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
617 /* Get the entry table */
619 pModule->entry_table = (int)pData - (int)pModule;
620 if (!READ( ne_header.entry_tab_offset,
621 ne_header.entry_tab_length,
622 pData ))
624 GlobalFree16( hModule );
625 return (HMODULE16)11; /* invalid exe */
627 pData += ne_header.entry_tab_length;
629 /* Get the non-resident names table */
631 if (ne_header.nrname_tab_length)
633 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
634 hModule, FALSE, FALSE, FALSE );
635 if (!pModule->nrname_handle)
637 GlobalFree16( hModule );
638 return (HMODULE16)11; /* invalid exe */
640 buffer = GlobalLock16( pModule->nrname_handle );
641 _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
642 if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length )
643 != ne_header.nrname_tab_length)
645 GlobalFree16( pModule->nrname_handle );
646 GlobalFree16( hModule );
647 return (HMODULE16)11; /* invalid exe */
650 else pModule->nrname_handle = 0;
652 /* Allocate a segment for the implicitly-loaded DLLs */
654 if (pModule->modref_count)
656 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
657 (pModule->modref_count+1)*sizeof(HMODULE16),
658 hModule, FALSE, FALSE, FALSE );
659 if (!pModule->dlls_to_init)
661 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
662 GlobalFree16( hModule );
663 return (HMODULE16)11; /* invalid exe */
666 else pModule->dlls_to_init = 0;
668 MODULE_RegisterModule( pModule );
669 return hModule;
670 #undef READ
674 /***********************************************************************
675 * MODULE_GetOrdinal
677 * Lookup the ordinal for a given name.
679 WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name )
681 char buffer[256], *cpnt;
682 BYTE len;
683 NE_MODULE *pModule;
685 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
687 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
688 hModule, name );
690 /* First handle names of the form '#xxxx' */
692 if (name[0] == '#') return atoi( name + 1 );
694 /* Now copy and uppercase the string */
696 strcpy( buffer, name );
697 AnsiUpper( buffer );
698 len = strlen( buffer );
700 /* First search the resident names */
702 cpnt = (char *)pModule + pModule->name_table;
704 /* Skip the first entry (module name) */
705 cpnt += *cpnt + 1 + sizeof(WORD);
706 while (*cpnt)
708 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
710 dprintf_module( stddeb, " Found: ordinal=%d\n",
711 *(WORD *)(cpnt + *cpnt + 1) );
712 return *(WORD *)(cpnt + *cpnt + 1);
714 cpnt += *cpnt + 1 + sizeof(WORD);
717 /* Now search the non-resident names table */
719 if (!pModule->nrname_handle) return 0; /* No non-resident table */
720 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
722 /* Skip the first entry (module description string) */
723 cpnt += *cpnt + 1 + sizeof(WORD);
724 while (*cpnt)
726 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
728 dprintf_module( stddeb, " Found: ordinal=%d\n",
729 *(WORD *)(cpnt + *cpnt + 1) );
730 return *(WORD *)(cpnt + *cpnt + 1);
732 cpnt += *cpnt + 1 + sizeof(WORD);
734 return 0;
738 /***********************************************************************
739 * MODULE_GetEntryPoint
741 * Return the entry point for a given ordinal.
743 FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
745 NE_MODULE *pModule;
746 WORD curOrdinal = 1;
747 BYTE *p;
748 WORD sel, offset;
750 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
752 p = (BYTE *)pModule + pModule->entry_table;
753 while (*p && (curOrdinal + *p <= ordinal))
755 /* Skipping this bundle */
756 curOrdinal += *p;
757 switch(p[1])
759 case 0: p += 2; break; /* unused */
760 case 0xff: p += 2 + *p * 6; break; /* moveable */
761 default: p += 2 + *p * 3; break; /* fixed */
764 if (!*p) return 0;
766 switch(p[1])
768 case 0: /* unused */
769 return 0;
770 case 0xff: /* moveable */
771 p += 2 + 6 * (ordinal - curOrdinal);
772 sel = p[3];
773 offset = *(WORD *)(p + 4);
774 break;
775 default: /* fixed */
776 sel = p[1];
777 p += 2 + 3 * (ordinal - curOrdinal);
778 offset = *(WORD *)(p + 1);
779 break;
782 if (sel == 0xfe) sel = 0xffff; /* constant entry */
783 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
784 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
788 /***********************************************************************
789 * MODULE_SetEntryPoint
791 * Change the value of an entry point. Use with caution!
792 * It can only change the offset value, not the selector.
794 BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
796 NE_MODULE *pModule;
797 WORD curOrdinal = 1;
798 BYTE *p;
800 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
802 p = (BYTE *)pModule + pModule->entry_table;
803 while (*p && (curOrdinal + *p <= ordinal))
805 /* Skipping this bundle */
806 curOrdinal += *p;
807 switch(p[1])
809 case 0: p += 2; break; /* unused */
810 case 0xff: p += 2 + *p * 6; break; /* moveable */
811 default: p += 2 + *p * 3; break; /* fixed */
814 if (!*p) return FALSE;
816 switch(p[1])
818 case 0: /* unused */
819 return FALSE;
820 case 0xff: /* moveable */
821 p += 2 + 6 * (ordinal - curOrdinal);
822 *(WORD *)(p + 4) = offset;
823 break;
824 default: /* fixed */
825 p += 2 + 3 * (ordinal - curOrdinal);
826 *(WORD *)(p + 1) = offset;
827 break;
829 return TRUE;
833 /***********************************************************************
834 * MODULE_GetWndProcEntry16 (not a Windows API function)
836 * Return an entry point from the WPROCS dll.
838 #ifndef WINELIB
839 FARPROC16 MODULE_GetWndProcEntry16( const char *name )
841 WORD ordinal;
842 FARPROC16 ret;
843 static HMODULE16 hModule = 0;
845 if (!hModule) hModule = GetModuleHandle( "WPROCS" );
846 ordinal = MODULE_GetOrdinal( hModule, name );
847 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
848 fprintf( stderr, "GetWndProc16: %s not found, please report\n", name );
849 return ret;
851 #endif
854 /***********************************************************************
855 * MODULE_GetModuleName
857 LPSTR MODULE_GetModuleName( HMODULE16 hModule )
859 NE_MODULE *pModule;
860 BYTE *p, len;
861 static char buffer[10];
863 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
864 p = (BYTE *)pModule + pModule->name_table;
865 len = MIN( *p, 8 );
866 memcpy( buffer, p + 1, len );
867 buffer[len] = '\0';
868 return buffer;
872 /**********************************************************************
873 * MODULE_RegisterModule
875 void MODULE_RegisterModule( NE_MODULE *pModule )
877 pModule->next = hFirstModule;
878 hFirstModule = pModule->self;
882 /**********************************************************************
883 * MODULE_FindModule
885 * Find a module from a path name.
887 HMODULE16 MODULE_FindModule( LPCSTR path )
889 HMODULE16 hModule = hFirstModule;
890 LPCSTR filename, dotptr, modulepath, modulename;
891 BYTE len, *name_table;
893 if (!(filename = strrchr( path, '\\' ))) filename = path;
894 else filename++;
895 if ((dotptr = strrchr( filename, '.' )) != NULL)
896 len = (BYTE)(dotptr - filename);
897 else len = strlen( filename );
899 while(hModule)
901 NE_MODULE *pModule = MODULE_GetPtr( hModule );
902 if (!pModule) break;
903 modulepath = NE_MODULE_NAME(pModule);
904 if (!(modulename = strrchr( modulepath, '\\' )))
905 modulename = modulepath;
906 else modulename++;
907 if (!lstrcmpi32A( modulename, filename )) return hModule;
909 name_table = (BYTE *)pModule + pModule->name_table;
910 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
911 return hModule;
912 hModule = pModule->next;
914 return 0;
918 /**********************************************************************
919 * MODULE_CallWEP
921 * Call a DLL's WEP, allowing it to shut down.
922 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
924 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
926 FARPROC16 WEP = (FARPROC16)0;
927 WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
929 if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
930 if (!WEP)
932 dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
933 return FALSE;
935 return CallWindowsExitProc( WEP, WEP_FREE_DLL );
939 /**********************************************************************
940 * MODULE_FreeModule
942 * Remove a module from memory.
944 static void MODULE_FreeModule( HMODULE16 hModule )
946 HMODULE16 *hPrevModule;
947 NE_MODULE *pModule;
948 SEGTABLEENTRY *pSegment;
949 HMODULE16 *pModRef;
950 int i;
952 if (!(pModule = MODULE_GetPtr( hModule ))) return;
953 if (pModule->flags & NE_FFLAGS_BUILTIN)
954 return; /* Can't free built-in module */
956 if (pModule->flags & NE_FFLAGS_LIBMODULE) MODULE_CallWEP( hModule );
958 /* Free the objects owned by the module */
960 HOOK_FreeModuleHooks( hModule );
961 CLASS_FreeModuleClasses( hModule );
963 /* Clear magic number just in case */
965 pModule->magic = pModule->self = 0;
967 /* Remove it from the linked list */
969 hPrevModule = &hFirstModule;
970 while (*hPrevModule && (*hPrevModule != hModule))
972 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
974 if (*hPrevModule) *hPrevModule = pModule->next;
976 /* Free all the segments */
978 pSegment = NE_SEG_TABLE( pModule );
979 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
981 GlobalFree16( pSegment->selector );
984 /* Free the referenced modules */
986 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
987 for (i = 0; i < pModule->modref_count; i++, pModRef++)
989 FreeModule16( *pModRef );
992 /* Free the module storage */
994 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
995 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
996 GlobalFree16( hModule );
998 /* Remove module from cache */
1000 if (hCachedModule == hModule) hCachedModule = 0;
1004 /**********************************************************************
1005 * LoadModule (KERNEL.45)
1007 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
1009 HMODULE16 hModule;
1010 HANDLE hInstance, hPrevInstance;
1011 NE_MODULE *pModule;
1012 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1013 OFSTRUCT ofs;
1014 #ifndef WINELIB
1015 WORD *pModRef, *pDLLs;
1016 HFILE hFile;
1017 int i;
1019 hModule = MODULE_FindModule( name );
1021 if (!hModule) /* We have to load the module */
1023 /* Try to load the built-in first if not disabled */
1024 if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
1026 if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR)
1028 /* Now try the built-in even if disabled */
1029 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
1031 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1032 return hModule;
1034 return 2; /* File not found */
1037 /* Create the module structure */
1039 hModule = MODULE_LoadExeHeader( hFile, &ofs );
1040 if (hModule < 32)
1042 /* FIXME: Hack because PE_LoadModule is recursive */
1043 int fd = dup( FILE_GetUnixHandle(hFile) );
1044 _lclose( hFile );
1045 if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
1046 close( fd );
1047 if (hModule < 32)
1048 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1049 name, hModule );
1050 return hModule;
1052 _lclose( hFile );
1053 pModule = MODULE_GetPtr( hModule );
1055 /* Allocate the segments for this module */
1057 MODULE_CreateSegments( hModule );
1059 hPrevInstance = 0;
1060 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1062 /* Load the referenced DLLs */
1064 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
1065 pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
1066 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1068 char buffer[256];
1069 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
1070 memcpy( buffer, pstr + 1, *pstr );
1071 strcpy( buffer + *pstr, ".dll" );
1072 dprintf_module( stddeb, "Loading '%s'\n", buffer );
1073 if (!(*pModRef = MODULE_FindModule( buffer )))
1075 /* If the DLL is not loaded yet, load it and store */
1076 /* its handle in the list of DLLs to initialize. */
1077 HMODULE16 hDLL;
1079 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
1081 char *p;
1083 /* Try with prepending the path of the current module */
1084 GetModuleFileName( hModule, buffer, sizeof(buffer) );
1085 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1086 memcpy( p + 1, pstr + 1, *pstr );
1087 strcpy( p + 1 + *pstr, ".dll" );
1088 hDLL = LoadModule( buffer, (LPVOID)-1 );
1090 if (hDLL < 32)
1092 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1093 buffer, name, hDLL );
1094 return 2; /* file not found */
1096 *pModRef = GetExePtr( hDLL );
1097 *pDLLs++ = *pModRef;
1099 else /* Increment the reference count of the DLL */
1101 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
1102 if (pOldDLL) pOldDLL->count++;
1106 /* Load the segments */
1108 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1110 int fd;
1111 /* Handle self loading modules */
1112 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1113 SELFLOADHEADER *selfloadheader;
1114 STACK16FRAME *stack16Top;
1115 HMODULE16 hselfload = GetModuleHandle("WPROCS");
1116 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1117 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1118 "Support for self-loading modules is very experimental\n",
1119 *((BYTE*)pModule + pModule->name_table),
1120 *((BYTE*)pModule + pModule->name_table),
1121 (char *)pModule + pModule->name_table + 1);
1122 NE_LoadSegment( hModule, 1 );
1123 selfloadheader = (SELFLOADHEADER *)
1124 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1125 selfloadheader->EntryAddrProc =
1126 MODULE_GetEntryPoint(hselfload,27);
1127 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1128 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1129 pModule->self_loading_sel = GlobalHandleToSel(
1130 GLOBAL_Alloc (GMEM_ZEROINIT,
1131 0xFF00, hModule, FALSE, FALSE, FALSE)
1133 oldss = IF1632_Saved16_ss;
1134 oldsp = IF1632_Saved16_sp;
1135 IF1632_Saved16_ss = pModule->self_loading_sel;
1136 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
1137 stack16Top = CURRENT_STACK16;
1138 stack16Top->saved_ss = 0;
1139 stack16Top->saved_sp = 0;
1140 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
1141 stack16Top->entry_point = 0;
1142 stack16Top->entry_ip = 0;
1143 stack16Top->entry_cs = 0;
1144 stack16Top->bp = 0;
1145 stack16Top->ip = 0;
1146 stack16Top->cs = 0;
1148 if (!IF1632_Stack32_base) {
1149 STACK32FRAME* frame32;
1150 char *stack32Top;
1151 /* Setup an initial 32 bit stack frame */
1152 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1153 hModule, FALSE, FALSE,
1154 FALSE );
1156 /* Create the 32-bit stack frame */
1158 *(DWORD *)GlobalLock16(hInitialStack32) = 0xDEADBEEF;
1159 stack32Top = (char*)GlobalLock16(hInitialStack32) +
1160 0x10000;
1161 frame32 = (STACK32FRAME *)stack32Top - 1;
1162 frame32->saved_esp = (DWORD)stack32Top;
1163 frame32->edi = 0;
1164 frame32->esi = 0;
1165 frame32->edx = 0;
1166 frame32->ecx = 0;
1167 frame32->ebx = 0;
1168 frame32->ebp = 0;
1169 frame32->retaddr = 0;
1170 frame32->codeselector = WINE_CODE_SELECTOR;
1171 /* pTask->esp = (DWORD)frame32; */
1172 IF1632_Stack32_base = WIN16_GlobalLock16(hInitialStack32);
1175 /* FIXME: we probably need a DOS handle here */
1176 fd = MODULE_OpenFile( hModule );
1177 CallTo16_word_ww (selfloadheader->BootApp,
1178 pModule->self_loading_sel, hModule, fd);
1179 /* some BootApp procs overwrite the selector of dgroup */
1180 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1181 IF1632_Saved16_ss = oldss;
1182 IF1632_Saved16_sp = oldsp;
1183 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1184 if (hInitialStack32){
1185 GlobalFree16(hInitialStack32);
1186 IF1632_Stack32_base = hInitialStack32 = 0;
1189 else
1191 for (i = 1; i <= pModule->seg_count; i++)
1192 NE_LoadSegment( hModule, i );
1195 /* Fixup the functions prologs */
1197 NE_FixupPrologs( pModule );
1199 /* Make sure the usage count is 1 on the first loading of */
1200 /* the module, even if it contains circular DLL references */
1202 pModule->count = 1;
1204 else
1206 pModule = MODULE_GetPtr( hModule );
1207 hPrevInstance = MODULE_GetInstance( hModule );
1208 hInstance = MODULE_CreateInstance( hModule, params );
1209 if (hInstance != hPrevInstance) /* not a library */
1210 NE_LoadSegment( hModule, pModule->dgroup );
1211 pModule->count++;
1213 #else
1214 lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1215 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1216 pModule = (NE_MODULE *)GlobalLock16( hModule );
1217 hPrevInstance = 0;
1218 hInstance = MODULE_CreateInstance( hModule, params );
1219 #endif /* WINELIB */
1221 /* Create a task for this instance */
1223 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1225 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1226 params->hEnvironment,
1227 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1228 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1231 return hInstance;
1235 /**********************************************************************
1236 * FreeModule16 (KERNEL.46)
1238 BOOL16 FreeModule16( HMODULE16 hModule )
1240 NE_MODULE *pModule;
1242 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1243 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1245 dprintf_module( stddeb, "FreeModule16: %s count %d\n",
1246 MODULE_GetModuleName(hModule), pModule->count );
1247 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1248 return TRUE;
1252 /**********************************************************************
1253 * GetModuleHandle (KERNEL.47)
1255 HMODULE16 WIN16_GetModuleHandle( SEGPTR name )
1257 if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
1258 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1261 HMODULE16 GetModuleHandle( LPCSTR name )
1263 return MODULE_FindModule( name );
1267 /**********************************************************************
1268 * GetModuleUsage (KERNEL.48)
1270 int GetModuleUsage( HANDLE hModule )
1272 NE_MODULE *pModule;
1274 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1275 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1276 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1277 hModule, pModule->count );
1278 return pModule->count;
1282 /**********************************************************************
1283 * GetModuleFileName (KERNEL.49)
1285 int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1287 NE_MODULE *pModule;
1289 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1290 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1291 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1292 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1293 return strlen(lpFileName);
1297 /***********************************************************************
1298 * LoadLibrary (KERNEL.95)
1300 HANDLE LoadLibrary( LPCSTR libname )
1302 #ifdef WINELIB
1303 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1304 WINELIB_UNIMP("LoadLibrary()");
1305 return (HANDLE)0;
1306 #else
1307 HANDLE handle;
1309 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1311 /* This does not increment the module reference count, and will
1312 * therefore cause crashes on FreeLibrary calls.
1313 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1315 handle = LoadModule( libname, (LPVOID)-1 );
1316 if (handle == (HANDLE)2) /* file not found */
1318 char buffer[256];
1319 lstrcpyn32A( buffer, libname, 252 );
1320 strcat( buffer, ".dll" );
1321 handle = LoadModule( buffer, (LPVOID)-1 );
1323 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
1324 return handle;
1325 #endif
1329 /***********************************************************************
1330 * FreeLibrary (KERNEL.96)
1332 void FreeLibrary( HANDLE handle )
1334 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1335 FreeModule16( handle );
1339 /***********************************************************************
1340 * WinExec (KERNEL.166)
1342 HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1344 LOADPARAMS params;
1345 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1346 HANDLE handle;
1347 WORD *cmdShowPtr;
1348 char *p, *cmdline, filename[256];
1349 static int use_load_module = 1;
1351 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1352 return 8; /* Out of memory */
1353 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 )))
1355 GlobalFree16( cmdShowHandle );
1356 return 8; /* Out of memory */
1359 /* Store nCmdShow */
1361 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1362 cmdShowPtr[0] = 2;
1363 cmdShowPtr[1] = nCmdShow;
1365 /* Build the filename and command-line */
1367 cmdline = (char *)GlobalLock16( cmdLineHandle );
1368 lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */);
1369 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1370 if (*p) lstrcpyn32A( cmdline, p + 1, 128 );
1371 else cmdline[0] = '\0';
1372 *p = '\0';
1374 /* Now load the executable file */
1376 if (use_load_module)
1378 #ifdef WINELIB
1379 /* WINELIB: Use LoadModule() only for the program itself */
1380 use_load_module = 0;
1381 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1382 #else
1383 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1384 #endif /* WINELIB */
1385 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1386 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1387 params.reserved = 0;
1388 handle = LoadModule( filename, &params );
1389 if (handle == 2) /* file not found */
1391 /* Check that the original file name did not have a suffix */
1392 p = strrchr(filename, '.');
1393 if (!p || (strchr(p, '/') && strchr(p, '\\')))
1395 p = filename + strlen(filename);
1396 strcpy( p, ".exe" );
1397 handle = LoadModule( filename, &params );
1398 *p = '\0'; /* Remove extension */
1402 else handle = 2;
1404 if (handle < 32)
1406 /* Try to start it as a unix program */
1407 if (!fork())
1409 /* Child process */
1410 const char *unixfilename;
1411 const char *argv[256], **argptr;
1412 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1413 nCmdShow == SW_SHOWMINNOACTIVE);
1415 /* get unixfilename */
1416 if (strchr(filename, '/') ||
1417 strchr(filename, ':') ||
1418 strchr(filename, '\\'))
1419 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1420 else unixfilename = filename;
1422 if (unixfilename)
1424 /* build argv */
1425 argptr = argv;
1426 if (iconic) *argptr++ = "-iconic";
1427 *argptr++ = unixfilename;
1428 p = cmdline;
1429 while (1)
1431 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1432 if (!*p) break;
1433 *argptr++ = p;
1434 while (*p && *p != ' ' && *p != '\t') p++;
1436 *argptr++ = 0;
1438 /* Execute */
1439 execvp(argv[0], (char**)argv);
1442 /* Failed ! */
1443 #ifdef WINELIB
1444 /* build argv */
1445 argptr = argv;
1446 *argptr++ = "wine";
1447 if (iconic) *argptr++ = "-iconic";
1448 *argptr++ = lpCmdLine;
1449 *argptr++ = 0;
1451 /* Execute */
1452 execvp(argv[0] , (char**)argv);
1454 /* Failed ! */
1455 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1456 #endif
1457 exit(1);
1461 GlobalFree16( cmdShowHandle );
1462 GlobalFree16( cmdLineHandle );
1464 #if 0
1465 if (handle < (HANDLE)32) /* Error? */
1466 return handle;
1468 /* FIXME: Yield never returns!
1469 We may want to run more applications or start the debugger
1470 before calling Yield. If we don't Yield will be called immdiately
1471 after returning. Why is it needed for Word anyway? */
1472 Yield(); /* program is executed immediately ....needed for word */
1474 #endif
1475 return handle;
1479 /***********************************************************************
1480 * GetProcAddress16 (KERNEL.50)
1482 FARPROC16 GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1484 WORD ordinal;
1485 FARPROC16 ret;
1487 if (!hModule) hModule = GetCurrentTask();
1488 hModule = GetExePtr( hModule );
1490 if (HIWORD(name) != 0)
1492 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1493 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1494 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1496 else
1498 ordinal = LOWORD(name);
1499 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1500 hModule, ordinal );
1502 if (!ordinal) return (FARPROC16)0;
1504 ret = MODULE_GetEntryPoint( hModule, ordinal );
1506 dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1507 return ret;
1511 /***********************************************************************
1512 * GetProcAddress32 (KERNEL32.257)
1514 FARPROC32 GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1516 #ifndef WINELIB
1517 NE_MODULE *pModule;
1519 hModule = GetExePtr( hModule );
1520 if (!(pModule = MODULE_GetPtr( hModule )))
1521 return (FARPROC32)0;
1522 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1523 return (FARPROC32)0;
1524 if (pModule->flags & NE_FFLAGS_BUILTIN)
1525 return BUILTIN_GetProcAddress32( pModule, function );
1526 return PE_FindExportedFunction( pModule->pe_module, function );
1527 #else
1528 return NULL;
1529 #endif
1533 /**********************************************************************
1534 * GetExpWinVer (KERNEL.167)
1536 WORD GetExpWinVer( HMODULE16 hModule )
1538 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1539 return pModule ? pModule->expected_version : 0;
1543 /**********************************************************************
1544 * ModuleFirst (TOOLHELP.59)
1546 BOOL16 ModuleFirst( MODULEENTRY *lpme )
1548 lpme->wNext = hFirstModule;
1549 return ModuleNext( lpme );
1553 /**********************************************************************
1554 * ModuleNext (TOOLHELP.60)
1556 BOOL16 ModuleNext( MODULEENTRY *lpme )
1558 NE_MODULE *pModule;
1560 if (!lpme->wNext) return FALSE;
1561 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1562 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1563 MAX_MODULE_NAME );
1564 lpme->szModule[MAX_MODULE_NAME] = '\0';
1565 lpme->hModule = lpme->wNext;
1566 lpme->wcUsage = pModule->count;
1567 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1568 lpme->szExePath[MAX_PATH] = '\0';
1569 lpme->wNext = pModule->next;
1570 return TRUE;
1574 /**********************************************************************
1575 * ModuleFindName (TOOLHELP.61)
1577 BOOL16 ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1579 lpme->wNext = GetModuleHandle( name );
1580 return ModuleNext( lpme );
1584 /**********************************************************************
1585 * ModuleFindHandle (TOOLHELP.62)
1587 BOOL16 ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1589 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1590 lpme->wNext = hModule;
1591 return ModuleNext( lpme );