Release 960728
[wine/multimedia.git] / loader / module.c
blobbf4fd5e80cce2bb6fa07486d532fc27a5277942c
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 HANDLE16 hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
277 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
280 /***********************************************************************
281 * MODULE_CreateSegments
283 #ifndef WINELIB32
284 static BOOL MODULE_CreateSegments( HMODULE16 hModule )
286 SEGTABLEENTRY *pSegment;
287 NE_MODULE *pModule;
288 int i, minsize;
290 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
291 pSegment = NE_SEG_TABLE( pModule );
292 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
294 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
295 if (i == pModule->ss) minsize += pModule->stack_size;
296 /* The DGROUP is allocated by MODULE_CreateInstance */
297 if (i == pModule->dgroup) continue;
298 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
299 minsize, hModule,
300 !(pSegment->flags & NE_SEGFLAGS_DATA),
301 FALSE,
302 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
303 if (!pSegment->selector) return FALSE;
306 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
307 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
308 return TRUE;
310 #endif
313 /***********************************************************************
314 * MODULE_GetInstance
316 HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule )
318 SEGTABLEENTRY *pSegment;
319 NE_MODULE *pModule;
321 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
322 if (pModule->dgroup == 0) return hModule;
324 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
326 return pSegment->selector;
330 /***********************************************************************
331 * MODULE_CreateInstance
333 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
335 SEGTABLEENTRY *pSegment;
336 NE_MODULE *pModule;
337 int minsize;
338 HINSTANCE hNewInstance, hPrevInstance;
340 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
341 if (pModule->dgroup == 0) return hModule;
343 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
344 hPrevInstance = pSegment->selector;
346 /* if it's a library, create a new instance only the first time */
347 if (hPrevInstance)
349 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
350 if (params == (LOADPARAMS*)-1) return hPrevInstance;
353 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
354 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
355 minsize += pModule->heap_size;
356 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
357 minsize, hModule, FALSE, FALSE, FALSE );
358 if (!hNewInstance) return 0;
359 pSegment->selector = hNewInstance;
360 return hNewInstance;
364 /***********************************************************************
365 * MODULE_CreateDummyModule
367 * Create a dummy NE module for Win32 or Winelib.
369 HMODULE16 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
371 HMODULE16 hModule;
372 NE_MODULE *pModule;
373 SEGTABLEENTRY *pSegment;
374 char *pStr;
376 INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
377 + strlen(ofs->szPathName) + 1;
378 INT32 size = sizeof(NE_MODULE) +
379 /* loaded file info */
380 of_size +
381 /* segment table: DS,CS */
382 2 * sizeof(SEGTABLEENTRY) +
383 /* name table */
385 /* several empty tables */
388 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
389 if (!hModule) return (HMODULE16)11; /* invalid exe */
391 FarSetOwner( hModule, hModule );
392 pModule = (NE_MODULE *)GlobalLock16( hModule );
394 /* Set all used entries */
395 pModule->magic = NE_SIGNATURE;
396 pModule->count = 1;
397 pModule->next = 0;
398 pModule->flags = 0;
399 pModule->dgroup = 1;
400 pModule->ss = 1;
401 pModule->cs = 2;
402 pModule->heap_size = 0xe000;
403 pModule->stack_size = 0x1000;
404 pModule->seg_count = 2;
405 pModule->modref_count = 0;
406 pModule->nrname_size = 0;
407 pModule->fileinfo = sizeof(NE_MODULE);
408 pModule->os_flags = NE_OSFLAGS_WINDOWS;
409 pModule->expected_version = 0x030a;
410 pModule->self = hModule;
412 /* Set loaded file information */
413 memcpy( pModule + 1, ofs, of_size );
414 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
416 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
417 pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
418 /* Data segment */
419 pSegment->size = 0;
420 pSegment->flags = NE_SEGFLAGS_DATA;
421 pSegment->minsize = 0x1000;
422 pSegment++;
423 /* Code segment */
424 pSegment->flags = 0;
425 pSegment++;
427 /* Module name */
428 pStr = (char *)pSegment;
429 pModule->name_table = (int)pStr - (int)pModule;
430 strcpy( pStr, "\x08W32SXXXX" );
431 pStr += 9;
433 /* All tables zero terminated */
434 pModule->res_table = pModule->import_table = pModule->entry_table =
435 (int)pStr - (int)pModule;
437 MODULE_RegisterModule( pModule );
438 return hModule;
442 /***********************************************************************
443 * MODULE_LoadExeHeader
445 static HMODULE16 MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
447 struct mz_header_s mz_header;
448 struct ne_header_s ne_header;
449 int size;
450 HMODULE16 hModule;
451 NE_MODULE *pModule;
452 BYTE *pData;
453 char *buffer, *fastload = NULL;
454 int fastload_offset = 0, fastload_length = 0;
456 /* Read a block from either the file or the fast-load area. */
457 #define READ(offset,size,buffer) \
458 ((fastload && ((offset) >= fastload_offset) && \
459 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
460 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
461 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
462 FILE_Read( hFile, (buffer), (size) ) == (size)))
464 _llseek( hFile, 0, SEEK_SET );
465 if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
466 (mz_header.mz_magic != MZ_SIGNATURE))
467 return (HMODULE16)11; /* invalid exe */
469 _llseek( hFile, mz_header.ne_offset, SEEK_SET );
470 if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
471 return (HMODULE16)11; /* invalid exe */
473 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE16)21; /* win32 exe */
474 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE16)11; /* invalid exe */
476 /* We now have a valid NE header */
478 size = sizeof(NE_MODULE) +
479 /* loaded file info */
480 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
481 /* segment table */
482 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
483 /* resource table */
484 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
485 /* resident names table */
486 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
487 /* module ref table */
488 ne_header.n_mod_ref_tab * sizeof(WORD) +
489 /* imported names table */
490 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
491 /* entry table length */
492 ne_header.entry_tab_length;
494 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
495 if (!hModule) return (HMODULE16)11; /* invalid exe */
496 FarSetOwner( hModule, hModule );
497 pModule = (NE_MODULE *)GlobalLock16( hModule );
498 memcpy( pModule, &ne_header, sizeof(ne_header) );
499 pModule->count = 0;
500 pModule->pe_module = NULL;
501 pModule->self = hModule;
502 pModule->self_loading_sel = 0;
503 pData = (BYTE *)(pModule + 1);
505 /* Clear internal Wine flags in case they are set in the EXE file */
507 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
509 /* Read the fast-load area */
511 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
513 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
514 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
515 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
516 fastload_offset, fastload_length );
517 if ((fastload = (char *)malloc( fastload_length )) != NULL)
519 _llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET );
520 if (FILE_Read( hFile, fastload, fastload_length ) != fastload_length)
522 free( fastload );
523 fastload = NULL;
528 /* Store the filename information */
530 pModule->fileinfo = (int)pData - (int)pModule;
531 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
532 memcpy( pData, ofs, size );
533 ((OFSTRUCT *)pData)->cBytes = size - 1;
534 pData += size;
536 /* Get the segment table */
538 pModule->seg_table = (int)pData - (int)pModule;
539 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
540 if (buffer)
542 int i;
543 struct ne_segment_table_entry_s *pSeg;
545 if (!READ( ne_header.segment_tab_offset,
546 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
547 buffer )) return (HMODULE16)11; /* invalid exe */
548 pSeg = (struct ne_segment_table_entry_s *)buffer;
549 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
551 memcpy( pData, pSeg, sizeof(*pSeg) );
552 pData += sizeof(SEGTABLEENTRY);
554 free( buffer );
556 else
558 GlobalFree16( hModule );
559 return (HMODULE16)11; /* invalid exe */
562 /* Get the resource table */
564 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
566 pModule->res_table = (int)pData - (int)pModule;
567 if (!READ(ne_header.resource_tab_offset,
568 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
569 pData )) return (HMODULE16)11; /* invalid exe */
570 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
572 else pModule->res_table = 0; /* No resource table */
574 /* Get the resident names table */
576 pModule->name_table = (int)pData - (int)pModule;
577 if (!READ( ne_header.rname_tab_offset,
578 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
579 pData ))
581 GlobalFree16( hModule );
582 return (HMODULE16)11; /* invalid exe */
584 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
586 /* Get the module references table */
588 if (ne_header.n_mod_ref_tab > 0)
590 pModule->modref_table = (int)pData - (int)pModule;
591 if (!READ( ne_header.moduleref_tab_offset,
592 ne_header.n_mod_ref_tab * sizeof(WORD),
593 pData )) return (HMODULE16)11; /* invalid exe */
594 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
596 else pModule->modref_table = 0; /* No module references */
598 /* Get the imported names table */
600 pModule->import_table = (int)pData - (int)pModule;
601 if (!READ( ne_header.iname_tab_offset,
602 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
603 pData ))
605 GlobalFree16( hModule );
606 return (HMODULE16)11; /* invalid exe */
608 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
610 /* Get the entry table */
612 pModule->entry_table = (int)pData - (int)pModule;
613 if (!READ( ne_header.entry_tab_offset,
614 ne_header.entry_tab_length,
615 pData ))
617 GlobalFree16( hModule );
618 return (HMODULE16)11; /* invalid exe */
620 pData += ne_header.entry_tab_length;
622 /* Get the non-resident names table */
624 if (ne_header.nrname_tab_length)
626 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
627 hModule, FALSE, FALSE, FALSE );
628 if (!pModule->nrname_handle)
630 GlobalFree16( hModule );
631 return (HMODULE16)11; /* invalid exe */
633 buffer = GlobalLock16( pModule->nrname_handle );
634 _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
635 if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length )
636 != ne_header.nrname_tab_length)
638 GlobalFree16( pModule->nrname_handle );
639 GlobalFree16( hModule );
640 return (HMODULE16)11; /* invalid exe */
643 else pModule->nrname_handle = 0;
645 /* Allocate a segment for the implicitly-loaded DLLs */
647 if (pModule->modref_count)
649 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
650 (pModule->modref_count+1)*sizeof(HMODULE16),
651 hModule, FALSE, FALSE, FALSE );
652 if (!pModule->dlls_to_init)
654 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
655 GlobalFree16( hModule );
656 return (HMODULE16)11; /* invalid exe */
659 else pModule->dlls_to_init = 0;
661 MODULE_RegisterModule( pModule );
662 return hModule;
663 #undef READ
667 /***********************************************************************
668 * MODULE_GetOrdinal
670 * Lookup the ordinal for a given name.
672 WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name )
674 char buffer[256], *cpnt;
675 BYTE len;
676 NE_MODULE *pModule;
678 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
680 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
681 hModule, name );
683 /* First handle names of the form '#xxxx' */
685 if (name[0] == '#') return atoi( name + 1 );
687 /* Now copy and uppercase the string */
689 strcpy( buffer, name );
690 AnsiUpper( buffer );
691 len = strlen( buffer );
693 /* First search the resident names */
695 cpnt = (char *)pModule + pModule->name_table;
697 /* Skip the first entry (module name) */
698 cpnt += *cpnt + 1 + sizeof(WORD);
699 while (*cpnt)
701 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
703 dprintf_module( stddeb, " Found: ordinal=%d\n",
704 *(WORD *)(cpnt + *cpnt + 1) );
705 return *(WORD *)(cpnt + *cpnt + 1);
707 cpnt += *cpnt + 1 + sizeof(WORD);
710 /* Now search the non-resident names table */
712 if (!pModule->nrname_handle) return 0; /* No non-resident table */
713 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
715 /* Skip the first entry (module description string) */
716 cpnt += *cpnt + 1 + sizeof(WORD);
717 while (*cpnt)
719 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
721 dprintf_module( stddeb, " Found: ordinal=%d\n",
722 *(WORD *)(cpnt + *cpnt + 1) );
723 return *(WORD *)(cpnt + *cpnt + 1);
725 cpnt += *cpnt + 1 + sizeof(WORD);
727 return 0;
731 /***********************************************************************
732 * MODULE_GetEntryPoint
734 * Return the entry point for a given ordinal.
736 FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
738 NE_MODULE *pModule;
739 WORD curOrdinal = 1;
740 BYTE *p;
741 WORD sel, offset;
743 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
745 p = (BYTE *)pModule + pModule->entry_table;
746 while (*p && (curOrdinal + *p <= ordinal))
748 /* Skipping this bundle */
749 curOrdinal += *p;
750 switch(p[1])
752 case 0: p += 2; break; /* unused */
753 case 0xff: p += 2 + *p * 6; break; /* moveable */
754 default: p += 2 + *p * 3; break; /* fixed */
757 if (!*p) return 0;
759 switch(p[1])
761 case 0: /* unused */
762 return 0;
763 case 0xff: /* moveable */
764 p += 2 + 6 * (ordinal - curOrdinal);
765 sel = p[3];
766 offset = *(WORD *)(p + 4);
767 break;
768 default: /* fixed */
769 sel = p[1];
770 p += 2 + 3 * (ordinal - curOrdinal);
771 offset = *(WORD *)(p + 1);
772 break;
775 if (sel == 0xfe) sel = 0xffff; /* constant entry */
776 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
777 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
781 /***********************************************************************
782 * MODULE_SetEntryPoint
784 * Change the value of an entry point. Use with caution!
785 * It can only change the offset value, not the selector.
787 BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
789 NE_MODULE *pModule;
790 WORD curOrdinal = 1;
791 BYTE *p;
793 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
795 p = (BYTE *)pModule + pModule->entry_table;
796 while (*p && (curOrdinal + *p <= ordinal))
798 /* Skipping this bundle */
799 curOrdinal += *p;
800 switch(p[1])
802 case 0: p += 2; break; /* unused */
803 case 0xff: p += 2 + *p * 6; break; /* moveable */
804 default: p += 2 + *p * 3; break; /* fixed */
807 if (!*p) return FALSE;
809 switch(p[1])
811 case 0: /* unused */
812 return FALSE;
813 case 0xff: /* moveable */
814 p += 2 + 6 * (ordinal - curOrdinal);
815 *(WORD *)(p + 4) = offset;
816 break;
817 default: /* fixed */
818 p += 2 + 3 * (ordinal - curOrdinal);
819 *(WORD *)(p + 1) = offset;
820 break;
822 return TRUE;
826 /***********************************************************************
827 * MODULE_GetWndProcEntry16 (not a Windows API function)
829 * Return an entry point from the WPROCS dll.
831 #ifndef WINELIB
832 FARPROC16 MODULE_GetWndProcEntry16( const char *name )
834 WORD ordinal;
835 FARPROC16 ret;
836 static HMODULE16 hModule = 0;
838 if (!hModule) hModule = GetModuleHandle( "WPROCS" );
839 ordinal = MODULE_GetOrdinal( hModule, name );
840 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
841 fprintf( stderr, "GetWndProc16: %s not found, please report\n", name );
842 return ret;
844 #endif
847 /***********************************************************************
848 * MODULE_GetModuleName
850 LPSTR MODULE_GetModuleName( HMODULE16 hModule )
852 NE_MODULE *pModule;
853 BYTE *p, len;
854 static char buffer[10];
856 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
857 p = (BYTE *)pModule + pModule->name_table;
858 len = MIN( *p, 8 );
859 memcpy( buffer, p + 1, len );
860 buffer[len] = '\0';
861 return buffer;
865 /**********************************************************************
866 * MODULE_RegisterModule
868 void MODULE_RegisterModule( NE_MODULE *pModule )
870 pModule->next = hFirstModule;
871 hFirstModule = pModule->self;
875 /**********************************************************************
876 * MODULE_FindModule
878 * Find a module from a path name.
880 HMODULE16 MODULE_FindModule( LPCSTR path )
882 HMODULE16 hModule = hFirstModule;
883 LPCSTR filename, dotptr, modulepath, modulename;
884 BYTE len, *name_table;
886 if (!(filename = strrchr( path, '\\' ))) filename = path;
887 else filename++;
888 if ((dotptr = strrchr( filename, '.' )) != NULL)
889 len = (BYTE)(dotptr - filename);
890 else len = strlen( filename );
892 while(hModule)
894 NE_MODULE *pModule = MODULE_GetPtr( hModule );
895 if (!pModule) break;
896 modulepath = NE_MODULE_NAME(pModule);
897 if (!(modulename = strrchr( modulepath, '\\' )))
898 modulename = modulepath;
899 else modulename++;
900 if (!lstrcmpi32A( modulename, filename )) return hModule;
902 name_table = (BYTE *)pModule + pModule->name_table;
903 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
904 return hModule;
905 hModule = pModule->next;
907 return 0;
911 /**********************************************************************
912 * MODULE_CallWEP
914 * Call a DLL's WEP, allowing it to shut down.
915 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
917 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
919 FARPROC16 WEP = (FARPROC16)0;
920 WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
922 if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
923 if (!WEP)
925 dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
926 return FALSE;
928 return CallWindowsExitProc( WEP, WEP_FREE_DLL );
932 /**********************************************************************
933 * MODULE_FreeModule
935 * Remove a module from memory.
937 static void MODULE_FreeModule( HMODULE16 hModule )
939 HMODULE16 *hPrevModule;
940 NE_MODULE *pModule;
941 SEGTABLEENTRY *pSegment;
942 HMODULE16 *pModRef;
943 int i;
945 if (!(pModule = MODULE_GetPtr( hModule ))) return;
946 if (pModule->flags & NE_FFLAGS_BUILTIN)
947 return; /* Can't free built-in module */
949 if (pModule->flags & NE_FFLAGS_LIBMODULE) MODULE_CallWEP( hModule );
951 /* Free the objects owned by the module */
953 HOOK_FreeModuleHooks( hModule );
954 CLASS_FreeModuleClasses( hModule );
956 /* Clear magic number just in case */
958 pModule->magic = pModule->self = 0;
960 /* Remove it from the linked list */
962 hPrevModule = &hFirstModule;
963 while (*hPrevModule && (*hPrevModule != hModule))
965 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
967 if (*hPrevModule) *hPrevModule = pModule->next;
969 /* Free all the segments */
971 pSegment = NE_SEG_TABLE( pModule );
972 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
974 GlobalFree16( pSegment->selector );
977 /* Free the referenced modules */
979 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
980 for (i = 0; i < pModule->modref_count; i++, pModRef++)
982 FreeModule16( *pModRef );
985 /* Free the module storage */
987 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
988 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
989 GlobalFree16( hModule );
991 /* Remove module from cache */
993 if (hCachedModule == hModule) hCachedModule = 0;
997 /**********************************************************************
998 * LoadModule (KERNEL.45)
1000 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
1002 HMODULE16 hModule;
1003 HANDLE hInstance, hPrevInstance;
1004 NE_MODULE *pModule;
1005 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1006 OFSTRUCT ofs;
1007 #ifndef WINELIB
1008 WORD *pModRef, *pDLLs;
1009 HFILE hFile;
1010 int i;
1012 hModule = MODULE_FindModule( name );
1014 if (!hModule) /* We have to load the module */
1016 /* Try to load the built-in first if not disabled */
1017 if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
1019 if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR)
1021 /* Now try the built-in even if disabled */
1022 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
1024 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1025 return hModule;
1027 return 2; /* File not found */
1030 /* Create the module structure */
1032 hModule = MODULE_LoadExeHeader( hFile, &ofs );
1033 if (hModule < 32)
1035 /* FIXME: Hack because PE_LoadModule is recursive */
1036 int fd = dup( FILE_GetUnixHandle(hFile) );
1037 _lclose( hFile );
1038 if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
1039 close( fd );
1040 if (hModule < 32)
1041 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1042 name, hModule );
1043 return hModule;
1045 _lclose( hFile );
1046 pModule = MODULE_GetPtr( hModule );
1048 /* Allocate the segments for this module */
1050 MODULE_CreateSegments( hModule );
1052 hPrevInstance = 0;
1053 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1055 /* Load the referenced DLLs */
1057 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
1058 pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
1059 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1061 char buffer[256];
1062 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
1063 memcpy( buffer, pstr + 1, *pstr );
1064 strcpy( buffer + *pstr, ".dll" );
1065 dprintf_module( stddeb, "Loading '%s'\n", buffer );
1066 if (!(*pModRef = MODULE_FindModule( buffer )))
1068 /* If the DLL is not loaded yet, load it and store */
1069 /* its handle in the list of DLLs to initialize. */
1070 HMODULE16 hDLL;
1072 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
1074 char *p;
1076 /* Try with prepending the path of the current module */
1077 GetModuleFileName( hModule, buffer, sizeof(buffer) );
1078 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1079 memcpy( p + 1, pstr + 1, *pstr );
1080 strcpy( p + 1 + *pstr, ".dll" );
1081 hDLL = LoadModule( buffer, (LPVOID)-1 );
1083 if (hDLL < 32)
1085 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1086 buffer, name, hDLL );
1087 return 2; /* file not found */
1089 *pModRef = GetExePtr( hDLL );
1090 *pDLLs++ = *pModRef;
1092 else /* Increment the reference count of the DLL */
1094 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
1095 if (pOldDLL) pOldDLL->count++;
1099 /* Load the segments */
1101 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1103 int fd;
1104 /* Handle self loading modules */
1105 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1106 SELFLOADHEADER *selfloadheader;
1107 STACK16FRAME *stack16Top;
1108 HMODULE16 hselfload = GetModuleHandle("WPROCS");
1109 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1110 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1111 "Support for self-loading modules is very experimental\n",
1112 *((BYTE*)pModule + pModule->name_table),
1113 *((BYTE*)pModule + pModule->name_table),
1114 (char *)pModule + pModule->name_table + 1);
1115 NE_LoadSegment( hModule, 1 );
1116 selfloadheader = (SELFLOADHEADER *)
1117 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1118 selfloadheader->EntryAddrProc =
1119 MODULE_GetEntryPoint(hselfload,27);
1120 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1121 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1122 pModule->self_loading_sel = GlobalHandleToSel(
1123 GLOBAL_Alloc (GMEM_ZEROINIT,
1124 0xFF00, hModule, FALSE, FALSE, FALSE)
1126 oldss = IF1632_Saved16_ss;
1127 oldsp = IF1632_Saved16_sp;
1128 IF1632_Saved16_ss = pModule->self_loading_sel;
1129 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
1130 stack16Top = CURRENT_STACK16;
1131 stack16Top->saved_ss = 0;
1132 stack16Top->saved_sp = 0;
1133 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
1134 stack16Top->entry_point = 0;
1135 stack16Top->entry_ip = 0;
1136 stack16Top->entry_cs = 0;
1137 stack16Top->bp = 0;
1138 stack16Top->ip = 0;
1139 stack16Top->cs = 0;
1141 if (!IF1632_Stack32_base) {
1142 STACK32FRAME* frame32;
1143 char *stack32Top;
1144 /* Setup an initial 32 bit stack frame */
1145 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1146 hModule, FALSE, FALSE,
1147 FALSE );
1149 /* Create the 32-bit stack frame */
1151 *(DWORD *)GlobalLock16(hInitialStack32) = 0xDEADBEEF;
1152 stack32Top = (char*)GlobalLock16(hInitialStack32) +
1153 0x10000;
1154 frame32 = (STACK32FRAME *)stack32Top - 1;
1155 frame32->saved_esp = (DWORD)stack32Top;
1156 frame32->edi = 0;
1157 frame32->esi = 0;
1158 frame32->edx = 0;
1159 frame32->ecx = 0;
1160 frame32->ebx = 0;
1161 frame32->ebp = 0;
1162 frame32->retaddr = 0;
1163 frame32->codeselector = WINE_CODE_SELECTOR;
1164 /* pTask->esp = (DWORD)frame32; */
1165 IF1632_Stack32_base = WIN16_GlobalLock16(hInitialStack32);
1168 /* FIXME: we probably need a DOS handle here */
1169 fd = MODULE_OpenFile( hModule );
1170 CallTo16_word_ww (selfloadheader->BootApp,
1171 pModule->self_loading_sel, hModule, fd);
1172 /* some BootApp procs overwrite the selector of dgroup */
1173 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1174 IF1632_Saved16_ss = oldss;
1175 IF1632_Saved16_sp = oldsp;
1176 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1177 if (hInitialStack32){
1178 GlobalFree16(hInitialStack32);
1179 IF1632_Stack32_base = hInitialStack32 = 0;
1182 else
1184 for (i = 1; i <= pModule->seg_count; i++)
1185 NE_LoadSegment( hModule, i );
1188 /* Fixup the functions prologs */
1190 NE_FixupPrologs( pModule );
1192 /* Make sure the usage count is 1 on the first loading of */
1193 /* the module, even if it contains circular DLL references */
1195 pModule->count = 1;
1197 else
1199 pModule = MODULE_GetPtr( hModule );
1200 hPrevInstance = MODULE_GetInstance( hModule );
1201 hInstance = MODULE_CreateInstance( hModule, params );
1202 if (hInstance != hPrevInstance) /* not a library */
1203 NE_LoadSegment( hModule, pModule->dgroup );
1204 pModule->count++;
1206 #else
1207 lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1208 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1209 pModule = (NE_MODULE *)GlobalLock16( hModule );
1210 hPrevInstance = 0;
1211 hInstance = MODULE_CreateInstance( hModule, params );
1212 #endif /* WINELIB */
1214 /* Create a task for this instance */
1216 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1218 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1219 params->hEnvironment,
1220 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1221 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1224 return hInstance;
1228 /**********************************************************************
1229 * FreeModule16 (KERNEL.46)
1231 BOOL16 FreeModule16( HMODULE16 hModule )
1233 NE_MODULE *pModule;
1235 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1236 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1238 dprintf_module( stddeb, "FreeModule16: %s count %d\n",
1239 MODULE_GetModuleName(hModule), pModule->count );
1240 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1241 return TRUE;
1245 /**********************************************************************
1246 * GetModuleHandle (KERNEL.47)
1248 HMODULE16 WIN16_GetModuleHandle( SEGPTR name )
1250 if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
1251 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1254 HMODULE16 GetModuleHandle( LPCSTR name )
1256 return MODULE_FindModule( name );
1260 /**********************************************************************
1261 * GetModuleUsage (KERNEL.48)
1263 int GetModuleUsage( HANDLE hModule )
1265 NE_MODULE *pModule;
1267 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1268 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1269 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1270 hModule, pModule->count );
1271 return pModule->count;
1275 /**********************************************************************
1276 * GetModuleFileName (KERNEL.49)
1278 int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1280 NE_MODULE *pModule;
1282 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1283 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1284 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1285 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1286 return strlen(lpFileName);
1290 /***********************************************************************
1291 * LoadLibrary (KERNEL.95)
1293 HANDLE LoadLibrary( LPCSTR libname )
1295 HANDLE handle;
1297 if (__winelib)
1299 fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1300 return (HANDLE)0;
1302 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1304 /* This does not increment the module reference count, and will
1305 * therefore cause crashes on FreeLibrary calls.
1306 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1308 handle = LoadModule( libname, (LPVOID)-1 );
1309 if (handle == (HANDLE)2) /* file not found */
1311 char buffer[256];
1312 lstrcpyn32A( buffer, libname, 252 );
1313 strcat( buffer, ".dll" );
1314 handle = LoadModule( buffer, (LPVOID)-1 );
1316 #ifndef WINELIB
1317 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
1318 #endif
1319 return handle;
1323 /***********************************************************************
1324 * FreeLibrary (KERNEL.96)
1326 void FreeLibrary( HANDLE handle )
1328 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1329 FreeModule16( handle );
1333 /***********************************************************************
1334 * WinExec (KERNEL.166)
1336 HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1338 LOADPARAMS params;
1339 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1340 HANDLE handle;
1341 WORD *cmdShowPtr;
1342 char *p, *cmdline, filename[256];
1343 static int use_load_module = 1;
1345 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1346 return 8; /* Out of memory */
1347 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 )))
1349 GlobalFree16( cmdShowHandle );
1350 return 8; /* Out of memory */
1353 /* Store nCmdShow */
1355 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1356 cmdShowPtr[0] = 2;
1357 cmdShowPtr[1] = nCmdShow;
1359 /* Build the filename and command-line */
1361 cmdline = (char *)GlobalLock16( cmdLineHandle );
1362 lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */);
1363 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1364 if (*p) lstrcpyn32A( cmdline, p + 1, 128 );
1365 else cmdline[0] = '\0';
1366 *p = '\0';
1368 /* Now load the executable file */
1370 if (use_load_module)
1372 #ifdef WINELIB
1373 /* WINELIB: Use LoadModule() only for the program itself */
1374 use_load_module = 0;
1375 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1376 #else
1377 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1378 #endif /* WINELIB */
1379 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1380 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1381 params.reserved = 0;
1382 handle = LoadModule( filename, &params );
1383 if (handle == 2) /* file not found */
1385 /* Check that the original file name did not have a suffix */
1386 p = strrchr(filename, '.');
1387 if (!p || (strchr(p, '/') && strchr(p, '\\')))
1389 p = filename + strlen(filename);
1390 strcpy( p, ".exe" );
1391 handle = LoadModule( filename, &params );
1392 *p = '\0'; /* Remove extension */
1396 else handle = 2;
1398 if (handle < 32)
1400 /* Try to start it as a unix program */
1401 if (!fork())
1403 /* Child process */
1404 const char *unixfilename;
1405 const char *argv[256], **argptr;
1406 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1407 nCmdShow == SW_SHOWMINNOACTIVE);
1409 /* get unixfilename */
1410 if (strchr(filename, '/') ||
1411 strchr(filename, ':') ||
1412 strchr(filename, '\\'))
1413 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1414 else unixfilename = filename;
1416 if (unixfilename)
1418 /* build argv */
1419 argptr = argv;
1420 if (iconic) *argptr++ = "-iconic";
1421 *argptr++ = unixfilename;
1422 p = cmdline;
1423 while (1)
1425 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1426 if (!*p) break;
1427 *argptr++ = p;
1428 while (*p && *p != ' ' && *p != '\t') p++;
1430 *argptr++ = 0;
1432 /* Execute */
1433 execvp(argv[0], (char**)argv);
1436 /* Failed ! */
1438 if (__winelib)
1440 /* build argv */
1441 argptr = argv;
1442 *argptr++ = "wine";
1443 if (iconic) *argptr++ = "-iconic";
1444 *argptr++ = lpCmdLine;
1445 *argptr++ = 0;
1447 /* Execute */
1448 execvp(argv[0] , (char**)argv);
1450 /* Failed ! */
1451 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1453 exit(1);
1457 GlobalFree16( cmdShowHandle );
1458 GlobalFree16( cmdLineHandle );
1460 #if 0
1461 if (handle < (HANDLE)32) /* Error? */
1462 return handle;
1464 /* FIXME: Yield never returns!
1465 We may want to run more applications or start the debugger
1466 before calling Yield. If we don't Yield will be called immdiately
1467 after returning. Why is it needed for Word anyway? */
1468 Yield(); /* program is executed immediately ....needed for word */
1470 #endif
1471 return handle;
1475 /***********************************************************************
1476 * GetProcAddress16 (KERNEL.50)
1478 FARPROC16 GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1480 WORD ordinal;
1481 FARPROC16 ret;
1483 if (!hModule) hModule = GetCurrentTask();
1484 hModule = GetExePtr( hModule );
1486 if (HIWORD(name) != 0)
1488 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1489 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1490 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1492 else
1494 ordinal = LOWORD(name);
1495 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1496 hModule, ordinal );
1498 if (!ordinal) return (FARPROC16)0;
1500 ret = MODULE_GetEntryPoint( hModule, ordinal );
1502 dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1503 return ret;
1507 /***********************************************************************
1508 * GetProcAddress32 (KERNEL32.257)
1510 FARPROC32 GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1512 #ifndef WINELIB
1513 NE_MODULE *pModule;
1515 hModule = GetExePtr( hModule );
1516 if (!(pModule = MODULE_GetPtr( hModule )))
1517 return (FARPROC32)0;
1518 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1519 return (FARPROC32)0;
1520 if (pModule->flags & NE_FFLAGS_BUILTIN)
1521 return BUILTIN_GetProcAddress32( pModule, function );
1522 return PE_FindExportedFunction( pModule->pe_module, function );
1523 #else
1524 return NULL;
1525 #endif
1529 /**********************************************************************
1530 * GetExpWinVer (KERNEL.167)
1532 WORD GetExpWinVer( HMODULE16 hModule )
1534 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1535 return pModule ? pModule->expected_version : 0;
1539 /**********************************************************************
1540 * ModuleFirst (TOOLHELP.59)
1542 BOOL16 ModuleFirst( MODULEENTRY *lpme )
1544 lpme->wNext = hFirstModule;
1545 return ModuleNext( lpme );
1549 /**********************************************************************
1550 * ModuleNext (TOOLHELP.60)
1552 BOOL16 ModuleNext( MODULEENTRY *lpme )
1554 NE_MODULE *pModule;
1556 if (!lpme->wNext) return FALSE;
1557 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1558 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1559 MAX_MODULE_NAME );
1560 lpme->szModule[MAX_MODULE_NAME] = '\0';
1561 lpme->hModule = lpme->wNext;
1562 lpme->wcUsage = pModule->count;
1563 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1564 lpme->szExePath[MAX_PATH] = '\0';
1565 lpme->wNext = pModule->next;
1566 return TRUE;
1570 /**********************************************************************
1571 * ModuleFindName (TOOLHELP.61)
1573 BOOL16 ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1575 lpme->wNext = GetModuleHandle( name );
1576 return ModuleNext( lpme );
1580 /**********************************************************************
1581 * ModuleFindHandle (TOOLHELP.62)
1583 BOOL16 ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1585 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1586 lpme->wNext = hModule;
1587 return ModuleNext( lpme );