Release 961013
[wine/multimedia.git] / loader / module.c
blob6dadc3f1122a406c974e2aed522c1de39941cc41
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 HINSTANCE16 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 HGLOBAL16 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 HINSTANCE16 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 _lread32( hFile, (buffer), (size) ) == (size)))
464 _llseek( hFile, 0, SEEK_SET );
465 if ((_lread32(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 (_lread32( 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 (_lread32(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 (_lread32( 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 HINSTANCE16 LoadModule( LPCSTR name, LPVOID paramBlock )
1002 HMODULE16 hModule;
1003 HINSTANCE16 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 HFILE hf;
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 hf = FILE_DupUnixHandle( MODULE_OpenFile( hModule ) );
1169 CallTo16_word_ww( selfloadheader->BootApp, hModule, hf );
1170 _lclose(hf);
1171 /* some BootApp procs overwrite the selector of dgroup */
1172 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1173 IF1632_Saved16_ss = oldss;
1174 IF1632_Saved16_sp = oldsp;
1175 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1176 if (hInitialStack32){
1177 GlobalFree16(hInitialStack32);
1178 IF1632_Stack32_base = hInitialStack32 = 0;
1181 else
1183 for (i = 1; i <= pModule->seg_count; i++)
1184 NE_LoadSegment( hModule, i );
1187 /* Fixup the functions prologs */
1189 NE_FixupPrologs( pModule );
1191 /* Make sure the usage count is 1 on the first loading of */
1192 /* the module, even if it contains circular DLL references */
1194 pModule->count = 1;
1196 else
1198 pModule = MODULE_GetPtr( hModule );
1199 hPrevInstance = MODULE_GetInstance( hModule );
1200 hInstance = MODULE_CreateInstance( hModule, params );
1201 if (hInstance != hPrevInstance) /* not a library */
1202 NE_LoadSegment( hModule, pModule->dgroup );
1203 pModule->count++;
1205 #else
1206 lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1207 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1208 pModule = (NE_MODULE *)GlobalLock16( hModule );
1209 hPrevInstance = 0;
1210 hInstance = MODULE_CreateInstance( hModule, params );
1211 #endif /* WINELIB */
1213 /* Create a task for this instance */
1215 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1217 HTASK16 hTask;
1218 WORD showcmd;
1220 /* PowerPoint passes NULL as showCmd */
1221 if (params->showCmd)
1222 showcmd = *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1);
1223 else
1224 showcmd = 0; /* FIXME: correct */
1226 hTask = TASK_CreateTask( hModule, hInstance, hPrevInstance,
1227 params->hEnvironment,
1228 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1229 showcmd );
1231 if( hTask && TASK_GetNextTask(hTask)) Yield();
1234 return hInstance;
1238 /**********************************************************************
1239 * FreeModule16 (KERNEL.46)
1241 BOOL16 FreeModule16( HMODULE16 hModule )
1243 NE_MODULE *pModule;
1245 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1246 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1248 dprintf_module( stddeb, "FreeModule16: %s count %d\n",
1249 MODULE_GetModuleName(hModule), pModule->count );
1250 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1251 return TRUE;
1255 /**********************************************************************
1256 * GetModuleHandle (KERNEL.47)
1258 HMODULE16 WIN16_GetModuleHandle( SEGPTR name )
1260 if (HIWORD(name) == 0) return GetExePtr( (HINSTANCE16)name );
1261 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1264 HMODULE16 GetModuleHandle( LPCSTR name )
1266 return MODULE_FindModule( name );
1270 /**********************************************************************
1271 * GetModuleUsage (KERNEL.48)
1273 INT16 GetModuleUsage( HINSTANCE16 hModule )
1275 NE_MODULE *pModule;
1277 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1278 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1279 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1280 hModule, pModule->count );
1281 return pModule->count;
1285 /**********************************************************************
1286 * GetModuleFileName (KERNEL.49)
1288 INT16 GetModuleFileName( HINSTANCE16 hModule, LPSTR lpFileName, INT16 nSize )
1290 NE_MODULE *pModule;
1292 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1293 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1294 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1295 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1296 return strlen(lpFileName);
1299 /**********************************************************************
1300 * GetModuleName (KERNEL.27)
1302 BOOL16 GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
1304 LPSTR name = MODULE_GetModuleName(hinst);
1306 if (!name) return FALSE;
1307 lstrcpyn32A( buf, name, nSize );
1308 return TRUE;
1312 /***********************************************************************
1313 * LoadLibrary (KERNEL.95)
1315 HINSTANCE16 LoadLibrary( LPCSTR libname )
1317 HINSTANCE16 handle;
1319 if (__winelib)
1321 fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1322 return 0;
1324 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1326 /* This does not increment the module reference count, and will
1327 * therefore cause crashes on FreeLibrary calls.
1328 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1330 handle = LoadModule( libname, (LPVOID)-1 );
1331 if (handle == (HINSTANCE16)2) /* file not found */
1333 char buffer[256];
1334 lstrcpyn32A( buffer, libname, 252 );
1335 strcat( buffer, ".dll" );
1336 handle = LoadModule( buffer, (LPVOID)-1 );
1338 #ifndef WINELIB
1339 if (handle >= (HINSTANCE16)32) NE_InitializeDLLs( GetExePtr(handle) );
1340 #endif
1341 return handle;
1345 /***********************************************************************
1346 * FreeLibrary (KERNEL.96)
1348 void FreeLibrary( HINSTANCE16 handle )
1350 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1351 FreeModule16( handle );
1355 /***********************************************************************
1356 * WinExec (KERNEL.166)
1358 HINSTANCE16 WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1360 LOADPARAMS params;
1361 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1362 HINSTANCE16 handle;
1363 WORD *cmdShowPtr;
1364 char *p, *cmdline, filename[256];
1365 static int use_load_module = 1;
1367 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1368 return 8; /* Out of memory */
1369 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 )))
1371 GlobalFree16( cmdShowHandle );
1372 return 8; /* Out of memory */
1375 /* Store nCmdShow */
1377 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1378 cmdShowPtr[0] = 2;
1379 cmdShowPtr[1] = nCmdShow;
1381 /* Build the filename and command-line */
1383 cmdline = (char *)GlobalLock16( cmdLineHandle );
1384 lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */);
1385 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1386 if (*p) lstrcpyn32A( cmdline, p + 1, 128 );
1387 else cmdline[0] = '\0';
1388 *p = '\0';
1390 /* Now load the executable file */
1392 if (use_load_module)
1394 #ifdef WINELIB
1395 /* WINELIB: Use LoadModule() only for the program itself */
1396 use_load_module = 0;
1397 params.hEnvironment = (HGLOBAL16)GetDOSEnvironment();
1398 #else
1399 params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
1400 #endif /* WINELIB */
1401 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1402 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1403 params.reserved = 0;
1404 handle = LoadModule( filename, &params );
1405 if (handle == 2) /* file not found */
1407 /* Check that the original file name did not have a suffix */
1408 p = strrchr(filename, '.');
1409 if (!p || (strchr(p, '/') && strchr(p, '\\')))
1411 p = filename + strlen(filename);
1412 strcpy( p, ".exe" );
1413 handle = LoadModule( filename, &params );
1414 *p = '\0'; /* Remove extension */
1418 else handle = 2;
1420 if (handle < 32)
1422 /* Try to start it as a unix program */
1423 if (!fork())
1425 /* Child process */
1426 const char *unixfilename;
1427 const char *argv[256], **argptr;
1428 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1429 nCmdShow == SW_SHOWMINNOACTIVE);
1431 /* get unixfilename */
1432 if (strchr(filename, '/') ||
1433 strchr(filename, ':') ||
1434 strchr(filename, '\\'))
1435 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1436 else unixfilename = filename;
1438 if (unixfilename)
1440 /* build argv */
1441 argptr = argv;
1442 if (iconic) *argptr++ = "-iconic";
1443 *argptr++ = unixfilename;
1444 p = cmdline;
1445 while (1)
1447 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1448 if (!*p) break;
1449 *argptr++ = p;
1450 while (*p && *p != ' ' && *p != '\t') p++;
1452 *argptr++ = 0;
1454 /* Execute */
1455 execvp(argv[0], (char**)argv);
1458 /* Failed ! */
1460 if (__winelib)
1462 /* build argv */
1463 argptr = argv;
1464 *argptr++ = "wine";
1465 if (iconic) *argptr++ = "-iconic";
1466 *argptr++ = lpCmdLine;
1467 *argptr++ = 0;
1469 /* Execute */
1470 execvp(argv[0] , (char**)argv);
1472 /* Failed ! */
1473 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1475 exit(1);
1479 GlobalFree16( cmdShowHandle );
1480 GlobalFree16( cmdLineHandle );
1481 return handle;
1485 /***********************************************************************
1486 * GetProcAddress16 (KERNEL.50)
1488 FARPROC16 GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1490 WORD ordinal;
1491 FARPROC16 ret;
1493 if (!hModule) hModule = GetCurrentTask();
1494 hModule = GetExePtr( hModule );
1496 if (HIWORD(name) != 0)
1498 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1499 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1500 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1502 else
1504 ordinal = LOWORD(name);
1505 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1506 hModule, ordinal );
1508 if (!ordinal) return (FARPROC16)0;
1510 ret = MODULE_GetEntryPoint( hModule, ordinal );
1512 dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1513 return ret;
1517 /***********************************************************************
1518 * GetProcAddress32 (KERNEL32.257)
1520 FARPROC32 GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1522 #ifndef WINELIB
1523 NE_MODULE *pModule;
1525 hModule = GetExePtr( hModule );
1526 if (!(pModule = MODULE_GetPtr( hModule )))
1527 return (FARPROC32)0;
1528 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1529 return (FARPROC32)0;
1530 if (pModule->flags & NE_FFLAGS_BUILTIN)
1531 return BUILTIN_GetProcAddress32( pModule, function );
1532 return PE_FindExportedFunction( pModule->pe_module, function );
1533 #else
1534 return NULL;
1535 #endif
1539 /**********************************************************************
1540 * GetExpWinVer (KERNEL.167)
1542 WORD GetExpWinVer( HMODULE16 hModule )
1544 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1545 return pModule ? pModule->expected_version : 0;
1549 /**********************************************************************
1550 * IsSharedSelector (KERNEL.345)
1552 BOOL16 IsSharedSelector( HANDLE16 selector )
1554 /* Check whether the selector belongs to a DLL */
1555 NE_MODULE *pModule = MODULE_GetPtr( GetExePtr( selector ));
1556 if (!pModule) return FALSE;
1557 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1561 /**********************************************************************
1562 * ModuleFirst (TOOLHELP.59)
1564 BOOL16 ModuleFirst( MODULEENTRY *lpme )
1566 lpme->wNext = hFirstModule;
1567 return ModuleNext( lpme );
1571 /**********************************************************************
1572 * ModuleNext (TOOLHELP.60)
1574 BOOL16 ModuleNext( MODULEENTRY *lpme )
1576 NE_MODULE *pModule;
1578 if (!lpme->wNext) return FALSE;
1579 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1580 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1581 MAX_MODULE_NAME );
1582 lpme->szModule[MAX_MODULE_NAME] = '\0';
1583 lpme->hModule = lpme->wNext;
1584 lpme->wcUsage = pModule->count;
1585 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1586 lpme->szExePath[MAX_PATH] = '\0';
1587 lpme->wNext = pModule->next;
1588 return TRUE;
1592 /**********************************************************************
1593 * ModuleFindName (TOOLHELP.61)
1595 BOOL16 ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1597 lpme->wNext = GetModuleHandle( name );
1598 return ModuleNext( lpme );
1602 /**********************************************************************
1603 * ModuleFindHandle (TOOLHELP.62)
1605 BOOL16 ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1607 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1608 lpme->wNext = hModule;
1609 return ModuleNext( lpme );