Release 961215
[wine.git] / loader / module.c
blobed359317ba340916ac7bb80f625a284b8c33810c
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"
29 #include "xmalloc.h"
31 extern HINSTANCE16 PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
33 static HMODULE16 hFirstModule = 0;
34 static HMODULE16 hCachedModule = 0; /* Module cached by MODULE_OpenFile */
36 #ifndef WINELIB
37 static HGLOBAL16 hInitialStack32 = 0;
38 #endif
41 /***********************************************************************
42 * MODULE_GetPtr
44 NE_MODULE *MODULE_GetPtr( HMODULE16 hModule )
46 NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule );
47 if (!pModule || (pModule->magic != NE_SIGNATURE) ||
48 (pModule->self != hModule)) return NULL;
49 return pModule;
53 /***********************************************************************
54 * MODULE_DumpModule
56 void MODULE_DumpModule( HMODULE16 hmodule )
58 int i, ordinal;
59 SEGTABLEENTRY *pSeg;
60 BYTE *pstr;
61 WORD *pword;
62 NE_MODULE *pModule;
64 if (!(pModule = MODULE_GetPtr( hmodule )))
66 fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
67 return;
70 /* Dump the module info */
72 printf( "Module %04x:\n", hmodule );
73 printf( "count=%d flags=%04x heap=%d stack=%d\n",
74 pModule->count, pModule->flags,
75 pModule->heap_size, pModule->stack_size );
76 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
77 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
78 pModule->seg_count, pModule->modref_count );
79 printf( "os_flags=%d swap_area=%d version=%04x\n",
80 pModule->os_flags, pModule->min_swap_area,
81 pModule->expected_version );
82 if (pModule->flags & NE_FFLAGS_WIN32)
83 printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
85 /* Dump the file info */
87 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
89 /* Dump the segment table */
91 printf( "\nSegment table:\n" );
92 pSeg = NE_SEG_TABLE( pModule );
93 for (i = 0; i < pModule->seg_count; i++, pSeg++)
94 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
95 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
96 pSeg->minsize, pSeg->selector );
98 /* Dump the resource table */
100 printf( "\nResource table:\n" );
101 if (pModule->res_table)
103 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
104 printf( "Alignment: %d\n", *pword++ );
105 while (*pword)
107 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
108 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
109 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
110 for (i = 0; i < ptr->count; i++, pname++)
111 printf( "offset=%d len=%d id=%04x\n",
112 pname->offset, pname->length, pname->id );
113 pword = (WORD *)pname;
116 else printf( "None\n" );
118 /* Dump the resident name table */
120 printf( "\nResident-name table:\n" );
121 pstr = (char *)pModule + pModule->name_table;
122 while (*pstr)
124 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
125 *(WORD *)(pstr + *pstr + 1) );
126 pstr += *pstr + 1 + sizeof(WORD);
129 /* Dump the module reference table */
131 printf( "\nModule ref table:\n" );
132 if (pModule->modref_table)
134 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
135 for (i = 0; i < pModule->modref_count; i++, pword++)
137 printf( "%d: %04x -> '%s'\n", i, *pword,
138 MODULE_GetModuleName(*pword));
141 else printf( "None\n" );
143 /* Dump the entry table */
145 printf( "\nEntry table:\n" );
146 pstr = (char *)pModule + pModule->entry_table;
147 ordinal = 1;
148 while (*pstr)
150 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
151 if (!pstr[1])
153 ordinal += *pstr;
154 pstr += 2;
156 else if ((BYTE)pstr[1] == 0xff) /* moveable */
158 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
159 for (i = 0; i < *pstr; i++, pe++)
160 printf( "%d: %02x:%04x (moveable)\n",
161 ordinal++, pe->seg_number, pe->offset );
162 pstr = (char *)pe;
164 else /* fixed */
166 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
167 for (i = 0; i < *pstr; i++, pe++)
168 printf( "%d: %04x (fixed)\n",
169 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
170 pstr = (char *)pe;
174 /* Dump the non-resident names table */
176 printf( "\nNon-resident names table:\n" );
177 if (pModule->nrname_handle)
179 pstr = (char *)GlobalLock16( pModule->nrname_handle );
180 while (*pstr)
182 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
183 *(WORD *)(pstr + *pstr + 1) );
184 pstr += *pstr + 1 + sizeof(WORD);
187 printf( "\n" );
191 /***********************************************************************
192 * MODULE_WalkModules
194 * Walk the module list and print the modules.
196 void MODULE_WalkModules(void)
198 HMODULE16 hModule = hFirstModule;
199 fprintf( stderr, "Module Flags Name\n" );
200 while (hModule)
202 NE_MODULE *pModule = MODULE_GetPtr( hModule );
203 if (!pModule)
205 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
206 return;
208 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
209 *((char *)pModule + pModule->name_table),
210 (char *)pModule + pModule->name_table + 1 );
211 hModule = pModule->next;
216 /***********************************************************************
217 * MODULE_OpenFile
219 int MODULE_OpenFile( HMODULE16 hModule )
221 NE_MODULE *pModule;
222 char *name;
223 const char *unixName;
225 static int cachedfd = -1;
227 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
228 dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
229 hModule, hCachedModule, cachedfd );
230 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
231 if (hCachedModule == hModule) return cachedfd;
232 close( cachedfd );
233 hCachedModule = hModule;
234 name = NE_MODULE_NAME( pModule );
235 if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
236 (cachedfd = open( unixName, O_RDONLY )) == -1)
237 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
238 name, hModule );
239 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
240 name, cachedfd );
241 return cachedfd;
245 /***********************************************************************
246 * MODULE_Ne2MemFlags
248 * This function translates NE segment flags to GlobalAlloc flags
250 static WORD MODULE_Ne2MemFlags(WORD flags)
252 WORD memflags = 0;
253 #if 0
254 if (flags & NE_SEGFLAGS_DISCARDABLE)
255 memflags |= GMEM_DISCARDABLE;
256 if (flags & NE_SEGFLAGS_MOVEABLE ||
257 ( ! (flags & NE_SEGFLAGS_DATA) &&
258 ! (flags & NE_SEGFLAGS_LOADED) &&
259 ! (flags & NE_SEGFLAGS_ALLOCATED)
262 memflags |= GMEM_MOVEABLE;
263 memflags |= GMEM_ZEROINIT;
264 #else
265 memflags = GMEM_ZEROINIT | GMEM_FIXED;
266 return memflags;
267 #endif
270 /***********************************************************************
271 * MODULE_AllocateSegment (WPROCS.26)
274 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
276 WORD size = wSize << wElem;
277 HANDLE16 hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
278 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
281 /***********************************************************************
282 * MODULE_CreateSegments
284 #ifndef WINELIB32
285 static BOOL MODULE_CreateSegments( HMODULE16 hModule )
287 SEGTABLEENTRY *pSegment;
288 NE_MODULE *pModule;
289 int i, minsize;
291 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
292 pSegment = NE_SEG_TABLE( pModule );
293 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
295 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
296 if (i == pModule->ss) minsize += pModule->stack_size;
297 /* The DGROUP is allocated by MODULE_CreateInstance */
298 if (i == pModule->dgroup) continue;
299 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
300 minsize, hModule,
301 !(pSegment->flags & NE_SEGFLAGS_DATA),
302 FALSE,
303 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
304 if (!pSegment->selector) return FALSE;
307 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
308 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
309 return TRUE;
311 #endif
314 /***********************************************************************
315 * MODULE_GetInstance
317 HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule )
319 SEGTABLEENTRY *pSegment;
320 NE_MODULE *pModule;
322 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
323 if (pModule->dgroup == 0) return hModule;
325 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
327 return pSegment->selector;
331 /***********************************************************************
332 * MODULE_CreateInstance
334 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
336 SEGTABLEENTRY *pSegment;
337 NE_MODULE *pModule;
338 int minsize;
339 HINSTANCE16 hNewInstance, hPrevInstance;
341 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
342 if (pModule->dgroup == 0) return hModule;
344 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
345 hPrevInstance = pSegment->selector;
347 /* if it's a library, create a new instance only the first time */
348 if (hPrevInstance)
350 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
351 if (params == (LOADPARAMS*)-1) return hPrevInstance;
354 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
355 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
356 minsize += pModule->heap_size;
357 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
358 minsize, hModule, FALSE, FALSE, FALSE );
359 if (!hNewInstance) return 0;
360 pSegment->selector = hNewInstance;
361 return hNewInstance;
365 /***********************************************************************
366 * MODULE_CreateDummyModule
368 * Create a dummy NE module for Win32 or Winelib.
370 HMODULE16 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
372 HMODULE16 hModule;
373 NE_MODULE *pModule;
374 SEGTABLEENTRY *pSegment;
375 char *pStr;
377 INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
378 + strlen(ofs->szPathName) + 1;
379 INT32 size = sizeof(NE_MODULE) +
380 /* loaded file info */
381 of_size +
382 /* segment table: DS,CS */
383 2 * sizeof(SEGTABLEENTRY) +
384 /* name table */
386 /* several empty tables */
389 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
390 if (!hModule) return (HMODULE16)11; /* invalid exe */
392 FarSetOwner( hModule, hModule );
393 pModule = (NE_MODULE *)GlobalLock16( hModule );
395 /* Set all used entries */
396 pModule->magic = NE_SIGNATURE;
397 pModule->count = 1;
398 pModule->next = 0;
399 pModule->flags = 0;
400 pModule->dgroup = 1;
401 pModule->ss = 1;
402 pModule->cs = 2;
403 pModule->heap_size = 0xe000;
404 pModule->stack_size = 0x1000;
405 pModule->seg_count = 2;
406 pModule->modref_count = 0;
407 pModule->nrname_size = 0;
408 pModule->fileinfo = sizeof(NE_MODULE);
409 pModule->os_flags = NE_OSFLAGS_WINDOWS;
410 pModule->expected_version = 0x030a;
411 pModule->self = hModule;
413 /* Set loaded file information */
414 memcpy( pModule + 1, ofs, of_size );
415 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
417 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
418 pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
419 /* Data segment */
420 pSegment->size = 0;
421 pSegment->flags = NE_SEGFLAGS_DATA;
422 pSegment->minsize = 0x1000;
423 pSegment++;
424 /* Code segment */
425 pSegment->flags = 0;
426 pSegment++;
428 /* Module name */
429 pStr = (char *)pSegment;
430 pModule->name_table = (int)pStr - (int)pModule;
431 strcpy( pStr, "\x08W32SXXXX" );
432 pStr += 9;
434 /* All tables zero terminated */
435 pModule->res_table = pModule->import_table = pModule->entry_table =
436 (int)pStr - (int)pModule;
438 MODULE_RegisterModule( pModule );
439 return hModule;
443 /***********************************************************************
444 * MODULE_LoadExeHeader
446 static HMODULE16 MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
448 struct mz_header_s mz_header;
449 struct ne_header_s ne_header;
450 int size;
451 HMODULE16 hModule;
452 NE_MODULE *pModule;
453 BYTE *pData;
454 char *buffer, *fastload = NULL;
455 int fastload_offset = 0, fastload_length = 0;
457 /* Read a block from either the file or the fast-load area. */
458 #define READ(offset,size,buffer) \
459 ((fastload && ((offset) >= fastload_offset) && \
460 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
461 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
462 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
463 _lread32( hFile, (buffer), (size) ) == (size)))
465 _llseek( hFile, 0, SEEK_SET );
466 if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
467 (mz_header.mz_magic != MZ_SIGNATURE))
468 return (HMODULE16)11; /* invalid exe */
470 _llseek( hFile, mz_header.ne_offset, SEEK_SET );
471 if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
472 return (HMODULE16)11; /* invalid exe */
474 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE16)21; /* win32 exe */
475 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE16)11; /* invalid exe */
477 /* We now have a valid NE header */
479 size = sizeof(NE_MODULE) +
480 /* loaded file info */
481 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
482 /* segment table */
483 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
484 /* resource table */
485 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
486 /* resident names table */
487 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
488 /* module ref table */
489 ne_header.n_mod_ref_tab * sizeof(WORD) +
490 /* imported names table */
491 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
492 /* entry table length */
493 ne_header.entry_tab_length;
495 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
496 if (!hModule) return (HMODULE16)11; /* invalid exe */
497 FarSetOwner( hModule, hModule );
498 pModule = (NE_MODULE *)GlobalLock16( hModule );
499 memcpy( pModule, &ne_header, sizeof(ne_header) );
500 pModule->count = 0;
501 pModule->pe_module = NULL;
502 pModule->self = hModule;
503 pModule->self_loading_sel = 0;
504 pData = (BYTE *)(pModule + 1);
506 /* Clear internal Wine flags in case they are set in the EXE file */
508 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
510 /* Read the fast-load area */
512 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
514 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
515 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
516 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
517 fastload_offset, fastload_length );
518 if ((fastload = (char *)xmalloc( fastload_length )) != NULL)
520 _llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET );
521 if (_lread32(hFile, fastload, fastload_length) != fastload_length)
523 free( fastload );
524 fastload = NULL;
529 /* Store the filename information */
531 pModule->fileinfo = (int)pData - (int)pModule;
532 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
533 memcpy( pData, ofs, size );
534 ((OFSTRUCT *)pData)->cBytes = size - 1;
535 pData += size;
537 /* Get the segment table */
539 pModule->seg_table = (int)pData - (int)pModule;
540 buffer = xmalloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
541 if (buffer)
543 int i;
544 struct ne_segment_table_entry_s *pSeg;
546 if (!READ( ne_header.segment_tab_offset,
547 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
548 buffer )) return (HMODULE16)11; /* invalid exe */
549 pSeg = (struct ne_segment_table_entry_s *)buffer;
550 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
552 memcpy( pData, pSeg, sizeof(*pSeg) );
553 pData += sizeof(SEGTABLEENTRY);
555 free( buffer );
557 else
559 GlobalFree16( hModule );
560 return (HMODULE16)11; /* invalid exe */
563 /* Get the resource table */
565 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
567 pModule->res_table = (int)pData - (int)pModule;
568 if (!READ(ne_header.resource_tab_offset,
569 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
570 pData )) return (HMODULE16)11; /* invalid exe */
571 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
573 else pModule->res_table = 0; /* No resource table */
575 /* Get the resident names table */
577 pModule->name_table = (int)pData - (int)pModule;
578 if (!READ( ne_header.rname_tab_offset,
579 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
580 pData ))
582 GlobalFree16( hModule );
583 return (HMODULE16)11; /* invalid exe */
585 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
587 /* Get the module references table */
589 if (ne_header.n_mod_ref_tab > 0)
591 pModule->modref_table = (int)pData - (int)pModule;
592 if (!READ( ne_header.moduleref_tab_offset,
593 ne_header.n_mod_ref_tab * sizeof(WORD),
594 pData )) return (HMODULE16)11; /* invalid exe */
595 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
597 else pModule->modref_table = 0; /* No module references */
599 /* Get the imported names table */
601 pModule->import_table = (int)pData - (int)pModule;
602 if (!READ( ne_header.iname_tab_offset,
603 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
604 pData ))
606 GlobalFree16( hModule );
607 return (HMODULE16)11; /* invalid exe */
609 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
611 /* Get the entry table */
613 pModule->entry_table = (int)pData - (int)pModule;
614 if (!READ( ne_header.entry_tab_offset,
615 ne_header.entry_tab_length,
616 pData ))
618 GlobalFree16( hModule );
619 return (HMODULE16)11; /* invalid exe */
621 pData += ne_header.entry_tab_length;
623 /* Get the non-resident names table */
625 if (ne_header.nrname_tab_length)
627 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
628 hModule, FALSE, FALSE, FALSE );
629 if (!pModule->nrname_handle)
631 GlobalFree16( hModule );
632 return (HMODULE16)11; /* invalid exe */
634 buffer = GlobalLock16( pModule->nrname_handle );
635 _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
636 if (_lread32( hFile, buffer, ne_header.nrname_tab_length )
637 != ne_header.nrname_tab_length)
639 GlobalFree16( pModule->nrname_handle );
640 GlobalFree16( hModule );
641 return (HMODULE16)11; /* invalid exe */
644 else pModule->nrname_handle = 0;
646 /* Allocate a segment for the implicitly-loaded DLLs */
648 if (pModule->modref_count)
650 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
651 (pModule->modref_count+1)*sizeof(HMODULE16),
652 hModule, FALSE, FALSE, FALSE );
653 if (!pModule->dlls_to_init)
655 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
656 GlobalFree16( hModule );
657 return (HMODULE16)11; /* invalid exe */
660 else pModule->dlls_to_init = 0;
662 MODULE_RegisterModule( pModule );
663 return hModule;
664 #undef READ
668 /***********************************************************************
669 * MODULE_GetOrdinal
671 * Lookup the ordinal for a given name.
673 WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name )
675 char buffer[256], *cpnt;
676 BYTE len;
677 NE_MODULE *pModule;
679 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
681 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
682 hModule, name );
684 /* First handle names of the form '#xxxx' */
686 if (name[0] == '#') return atoi( name + 1 );
688 /* Now copy and uppercase the string */
690 strcpy( buffer, name );
691 AnsiUpper( buffer );
692 len = strlen( buffer );
694 /* First search the resident names */
696 cpnt = (char *)pModule + pModule->name_table;
698 /* Skip the first entry (module name) */
699 cpnt += *cpnt + 1 + sizeof(WORD);
700 while (*cpnt)
702 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
704 dprintf_module( stddeb, " Found: ordinal=%d\n",
705 *(WORD *)(cpnt + *cpnt + 1) );
706 return *(WORD *)(cpnt + *cpnt + 1);
708 cpnt += *cpnt + 1 + sizeof(WORD);
711 /* Now search the non-resident names table */
713 if (!pModule->nrname_handle) return 0; /* No non-resident table */
714 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
716 /* Skip the first entry (module description string) */
717 cpnt += *cpnt + 1 + sizeof(WORD);
718 while (*cpnt)
720 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
722 dprintf_module( stddeb, " Found: ordinal=%d\n",
723 *(WORD *)(cpnt + *cpnt + 1) );
724 return *(WORD *)(cpnt + *cpnt + 1);
726 cpnt += *cpnt + 1 + sizeof(WORD);
728 return 0;
732 /***********************************************************************
733 * MODULE_GetEntryPoint
735 * Return the entry point for a given ordinal.
737 FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
739 NE_MODULE *pModule;
740 WORD curOrdinal = 1;
741 BYTE *p;
742 WORD sel, offset;
744 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
746 p = (BYTE *)pModule + pModule->entry_table;
747 while (*p && (curOrdinal + *p <= ordinal))
749 /* Skipping this bundle */
750 curOrdinal += *p;
751 switch(p[1])
753 case 0: p += 2; break; /* unused */
754 case 0xff: p += 2 + *p * 6; break; /* moveable */
755 default: p += 2 + *p * 3; break; /* fixed */
758 if (!*p) return 0;
760 switch(p[1])
762 case 0: /* unused */
763 return 0;
764 case 0xff: /* moveable */
765 p += 2 + 6 * (ordinal - curOrdinal);
766 sel = p[3];
767 offset = *(WORD *)(p + 4);
768 break;
769 default: /* fixed */
770 sel = p[1];
771 p += 2 + 3 * (ordinal - curOrdinal);
772 offset = *(WORD *)(p + 1);
773 break;
776 if (sel == 0xfe) sel = 0xffff; /* constant entry */
777 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
778 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
782 /***********************************************************************
783 * MODULE_SetEntryPoint
785 * Change the value of an entry point. Use with caution!
786 * It can only change the offset value, not the selector.
788 BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
790 NE_MODULE *pModule;
791 WORD curOrdinal = 1;
792 BYTE *p;
794 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
796 p = (BYTE *)pModule + pModule->entry_table;
797 while (*p && (curOrdinal + *p <= ordinal))
799 /* Skipping this bundle */
800 curOrdinal += *p;
801 switch(p[1])
803 case 0: p += 2; break; /* unused */
804 case 0xff: p += 2 + *p * 6; break; /* moveable */
805 default: p += 2 + *p * 3; break; /* fixed */
808 if (!*p) return FALSE;
810 switch(p[1])
812 case 0: /* unused */
813 return FALSE;
814 case 0xff: /* moveable */
815 p += 2 + 6 * (ordinal - curOrdinal);
816 *(WORD *)(p + 4) = offset;
817 break;
818 default: /* fixed */
819 p += 2 + 3 * (ordinal - curOrdinal);
820 *(WORD *)(p + 1) = offset;
821 break;
823 return TRUE;
827 /***********************************************************************
828 * MODULE_GetWndProcEntry16 (not a Windows API function)
830 * Return an entry point from the WPROCS dll.
832 #ifndef WINELIB
833 FARPROC16 MODULE_GetWndProcEntry16( const char *name )
835 WORD ordinal;
836 FARPROC16 ret;
837 static HMODULE16 hModule = 0;
839 if (!hModule) hModule = GetModuleHandle( "WPROCS" );
840 ordinal = MODULE_GetOrdinal( hModule, name );
841 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
842 fprintf( stderr, "GetWndProc16: %s not found, please report\n", name );
843 return ret;
845 #endif
848 /***********************************************************************
849 * MODULE_GetModuleName
851 LPSTR MODULE_GetModuleName( HMODULE16 hModule )
853 NE_MODULE *pModule;
854 BYTE *p, len;
855 static char buffer[10];
857 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
858 p = (BYTE *)pModule + pModule->name_table;
859 len = MIN( *p, 8 );
860 memcpy( buffer, p + 1, len );
861 buffer[len] = '\0';
862 return buffer;
866 /**********************************************************************
867 * MODULE_RegisterModule
869 void MODULE_RegisterModule( NE_MODULE *pModule )
871 pModule->next = hFirstModule;
872 hFirstModule = pModule->self;
876 /**********************************************************************
877 * MODULE_FindModule
879 * Find a module from a path name.
881 HMODULE16 MODULE_FindModule( LPCSTR path )
883 HMODULE16 hModule = hFirstModule;
884 LPCSTR filename, dotptr, modulepath, modulename;
885 BYTE len, *name_table;
887 if (!(filename = strrchr( path, '\\' ))) filename = path;
888 else filename++;
889 if ((dotptr = strrchr( filename, '.' )) != NULL)
890 len = (BYTE)(dotptr - filename);
891 else len = strlen( filename );
893 while(hModule)
895 NE_MODULE *pModule = MODULE_GetPtr( hModule );
896 if (!pModule) break;
897 modulepath = NE_MODULE_NAME(pModule);
898 if (!(modulename = strrchr( modulepath, '\\' )))
899 modulename = modulepath;
900 else modulename++;
901 if (!lstrcmpi32A( modulename, filename )) return hModule;
903 name_table = (BYTE *)pModule + pModule->name_table;
904 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
905 return hModule;
906 hModule = pModule->next;
908 return 0;
912 /**********************************************************************
913 * MODULE_CallWEP
915 * Call a DLL's WEP, allowing it to shut down.
916 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
918 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
920 FARPROC16 WEP = (FARPROC16)0;
921 WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
923 if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
924 if (!WEP)
926 dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
927 return FALSE;
929 return CallWindowsExitProc( WEP, WEP_FREE_DLL );
933 /**********************************************************************
934 * MODULE_FreeModule
936 * Remove a module from memory.
938 static void MODULE_FreeModule( HMODULE16 hModule )
940 HMODULE16 *hPrevModule;
941 NE_MODULE *pModule;
942 SEGTABLEENTRY *pSegment;
943 HMODULE16 *pModRef;
944 int i;
946 if (!(pModule = MODULE_GetPtr( hModule ))) return;
947 if (pModule->flags & NE_FFLAGS_BUILTIN)
948 return; /* Can't free built-in module */
950 if (pModule->flags & NE_FFLAGS_LIBMODULE) MODULE_CallWEP( hModule );
952 /* Free the objects owned by the module */
954 HOOK_FreeModuleHooks( hModule );
955 CLASS_FreeModuleClasses( hModule );
957 /* Clear magic number just in case */
959 pModule->magic = pModule->self = 0;
961 /* Remove it from the linked list */
963 hPrevModule = &hFirstModule;
964 while (*hPrevModule && (*hPrevModule != hModule))
966 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
968 if (*hPrevModule) *hPrevModule = pModule->next;
970 /* Free all the segments */
972 pSegment = NE_SEG_TABLE( pModule );
973 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
975 GlobalFree16( pSegment->selector );
978 /* Free the referenced modules */
980 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
981 for (i = 0; i < pModule->modref_count; i++, pModRef++)
983 FreeModule16( *pModRef );
986 /* Free the module storage */
988 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
989 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
990 GlobalFree16( hModule );
992 /* Remove module from cache */
994 if (hCachedModule == hModule) hCachedModule = 0;
998 /**********************************************************************
999 * LoadModule (KERNEL.45)
1001 HINSTANCE16 LoadModule( LPCSTR name, LPVOID paramBlock )
1003 HMODULE16 hModule;
1004 HINSTANCE16 hInstance, hPrevInstance;
1005 NE_MODULE *pModule;
1006 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1007 OFSTRUCT ofs;
1008 #ifndef WINELIB
1009 WORD *pModRef, *pDLLs;
1010 HFILE hFile;
1011 int i;
1013 hModule = MODULE_FindModule( name );
1015 if (!hModule) /* We have to load the module */
1017 /* Try to load the built-in first if not disabled */
1018 if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
1020 if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR)
1022 /* Now try the built-in even if disabled */
1023 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
1025 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1026 return hModule;
1028 return 2; /* File not found */
1031 /* Create the module structure */
1033 hModule = MODULE_LoadExeHeader( hFile, &ofs );
1034 if (hModule < 32)
1036 /* FIXME: Hack because PE_LoadModule is recursive */
1037 int fd = dup( FILE_GetUnixHandle(hFile) );
1038 _lclose( hFile );
1039 if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
1040 close( fd );
1041 if (hModule < 32)
1042 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1043 name, hModule );
1044 return hModule;
1046 _lclose( hFile );
1047 pModule = MODULE_GetPtr( hModule );
1049 /* Allocate the segments for this module */
1051 MODULE_CreateSegments( hModule );
1053 hPrevInstance = 0;
1054 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1056 /* Load the referenced DLLs */
1058 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
1059 pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
1060 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1062 char buffer[256];
1063 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
1064 memcpy( buffer, pstr + 1, *pstr );
1065 strcpy( buffer + *pstr, ".dll" );
1066 dprintf_module( stddeb, "Loading '%s'\n", buffer );
1067 if (!(*pModRef = MODULE_FindModule( buffer )))
1069 /* If the DLL is not loaded yet, load it and store */
1070 /* its handle in the list of DLLs to initialize. */
1071 HMODULE16 hDLL;
1073 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
1075 char *p;
1077 /* Try with prepending the path of the current module */
1078 GetModuleFileName16( hModule, buffer, sizeof(buffer) );
1079 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1080 memcpy( p + 1, pstr + 1, *pstr );
1081 strcpy( p + 1 + *pstr, ".dll" );
1082 hDLL = LoadModule( buffer, (LPVOID)-1 );
1084 if (hDLL < 32)
1086 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1087 buffer, name, hDLL );
1088 return 2; /* file not found */
1090 *pModRef = GetExePtr( hDLL );
1091 *pDLLs++ = *pModRef;
1093 else /* Increment the reference count of the DLL */
1095 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
1096 if (pOldDLL) pOldDLL->count++;
1100 /* Load the segments */
1102 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1104 HFILE hf;
1105 /* Handle self loading modules */
1106 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1107 SELFLOADHEADER *selfloadheader;
1108 STACK16FRAME *stack16Top;
1109 HMODULE16 hselfload = GetModuleHandle("WPROCS");
1110 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1111 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1112 "Support for self-loading modules is very experimental\n",
1113 *((BYTE*)pModule + pModule->name_table),
1114 *((BYTE*)pModule + pModule->name_table),
1115 (char *)pModule + pModule->name_table + 1);
1116 NE_LoadSegment( hModule, 1 );
1117 selfloadheader = (SELFLOADHEADER *)
1118 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1119 selfloadheader->EntryAddrProc =
1120 MODULE_GetEntryPoint(hselfload,27);
1121 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1122 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1123 pModule->self_loading_sel = GlobalHandleToSel(
1124 GLOBAL_Alloc (GMEM_ZEROINIT,
1125 0xFF00, hModule, FALSE, FALSE, FALSE)
1127 oldss = IF1632_Saved16_ss;
1128 oldsp = IF1632_Saved16_sp;
1129 IF1632_Saved16_ss = pModule->self_loading_sel;
1130 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
1131 stack16Top = CURRENT_STACK16;
1132 stack16Top->saved_ss = 0;
1133 stack16Top->saved_sp = 0;
1134 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
1135 stack16Top->entry_point = 0;
1136 stack16Top->entry_ip = 0;
1137 stack16Top->entry_cs = 0;
1138 stack16Top->bp = 0;
1139 stack16Top->ip = 0;
1140 stack16Top->cs = 0;
1142 if (!IF1632_Stack32_base) {
1143 STACK32FRAME* frame32;
1144 char *stack32Top;
1145 /* Setup an initial 32 bit stack frame */
1146 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1147 hModule, FALSE, FALSE,
1148 FALSE );
1150 /* Create the 32-bit stack frame */
1152 *(DWORD *)GlobalLock16(hInitialStack32) = 0xDEADBEEF;
1153 stack32Top = (char*)GlobalLock16(hInitialStack32) +
1154 0x10000;
1155 frame32 = (STACK32FRAME *)stack32Top - 1;
1156 frame32->saved_esp = (DWORD)stack32Top;
1157 frame32->edi = 0;
1158 frame32->esi = 0;
1159 frame32->edx = 0;
1160 frame32->ecx = 0;
1161 frame32->ebx = 0;
1162 frame32->ebp = 0;
1163 frame32->retaddr = 0;
1164 frame32->codeselector = WINE_CODE_SELECTOR;
1165 /* pTask->esp = (DWORD)frame32; */
1166 IF1632_Stack32_base = WIN16_GlobalLock16(hInitialStack32);
1169 hf = FILE_DupUnixHandle( MODULE_OpenFile( hModule ) );
1170 CallTo16_word_ww( selfloadheader->BootApp, hModule, hf );
1171 _lclose(hf);
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 HTASK16 hTask;
1219 WORD showcmd;
1221 /* PowerPoint passes NULL as showCmd */
1222 if (params->showCmd)
1223 showcmd = *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1);
1224 else
1225 showcmd = 0; /* FIXME: correct */
1227 hTask = TASK_CreateTask( hModule, hInstance, hPrevInstance,
1228 params->hEnvironment,
1229 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1230 showcmd );
1232 if( hTask && TASK_GetNextTask(hTask)) Yield();
1235 return hInstance;
1239 /**********************************************************************
1240 * FreeModule16 (KERNEL.46)
1242 BOOL16 FreeModule16( HMODULE16 hModule )
1244 NE_MODULE *pModule;
1246 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1247 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1249 dprintf_module( stddeb, "FreeModule16: %s count %d\n",
1250 MODULE_GetModuleName(hModule), pModule->count );
1251 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1252 return TRUE;
1256 /**********************************************************************
1257 * GetModuleHandle (KERNEL.47)
1259 HMODULE16 WIN16_GetModuleHandle( SEGPTR name )
1261 if (HIWORD(name) == 0) return GetExePtr( (HINSTANCE16)name );
1262 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1265 HMODULE16 GetModuleHandle( LPCSTR name )
1267 return MODULE_FindModule( name );
1271 /**********************************************************************
1272 * GetModuleUsage (KERNEL.48)
1274 INT16 GetModuleUsage( HINSTANCE16 hModule )
1276 NE_MODULE *pModule;
1278 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1279 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1280 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1281 hModule, pModule->count );
1282 return pModule->count;
1286 /**********************************************************************
1287 * GetModuleFileName16 (KERNEL.49)
1289 INT16 GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName, INT16 nSize )
1291 NE_MODULE *pModule;
1293 if (!hModule) hModule = GetCurrentTask();
1294 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1295 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1296 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1297 dprintf_module( stddeb, "GetModuleFileName16: %s\n", lpFileName );
1298 return strlen(lpFileName);
1302 /***********************************************************************
1303 * GetModuleFileName32A (KERNEL32.235)
1305 DWORD GetModuleFileName32A( HMODULE32 hModule, LPSTR lpFileName, DWORD size )
1307 NE_MODULE *pModule;
1309 if (!hModule)
1311 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1312 hModule = pTask->hInstance;
1314 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1315 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1316 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
1317 dprintf_module( stddeb, "GetModuleFileName32A: %s\n", lpFileName );
1318 return strlen(lpFileName);
1322 /***********************************************************************
1323 * GetModuleFileName32W (KERNEL32.236)
1325 DWORD GetModuleFileName32W( HMODULE32 hModule, LPWSTR lpFileName, DWORD size )
1327 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1328 DWORD res = GetModuleFileName32A( hModule, fnA, size );
1329 lstrcpynAtoW( lpFileName, fnA, size );
1330 HeapFree( GetProcessHeap(), 0, fnA );
1331 return res;
1335 /**********************************************************************
1336 * GetModuleName (KERNEL.27)
1338 BOOL16 GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
1340 LPSTR name = MODULE_GetModuleName(hinst);
1342 if (!name) return FALSE;
1343 lstrcpyn32A( buf, name, nSize );
1344 return TRUE;
1348 /***********************************************************************
1349 * LoadLibrary (KERNEL.95)
1351 HINSTANCE16 LoadLibrary16( LPCSTR libname )
1353 HINSTANCE16 handle;
1355 if (__winelib)
1357 fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1358 return 0;
1360 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1362 /* This does not increment the module reference count, and will
1363 * therefore cause crashes on FreeLibrary calls.
1364 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1366 handle = LoadModule( libname, (LPVOID)-1 );
1367 if (handle == (HINSTANCE16)2) /* file not found */
1369 char buffer[256];
1370 lstrcpyn32A( buffer, libname, 252 );
1371 strcat( buffer, ".dll" );
1372 handle = LoadModule( buffer, (LPVOID)-1 );
1374 #ifndef WINELIB
1375 if (handle >= (HINSTANCE16)32) NE_InitializeDLLs( GetExePtr(handle) );
1376 #endif
1377 return handle;
1381 /***********************************************************************
1382 * FreeLibrary (KERNEL.96)
1384 void FreeLibrary( HINSTANCE16 handle )
1386 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1387 FreeModule16( handle );
1391 /***********************************************************************
1392 * WinExec (KERNEL.166)
1394 HINSTANCE16 WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1396 LOADPARAMS params;
1397 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1398 HINSTANCE16 handle;
1399 WORD *cmdShowPtr;
1400 char *p, *cmdline, filename[256];
1401 static int use_load_module = 1;
1403 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1404 return 8; /* Out of memory */
1405 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 )))
1407 GlobalFree16( cmdShowHandle );
1408 return 8; /* Out of memory */
1411 /* Store nCmdShow */
1413 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1414 cmdShowPtr[0] = 2;
1415 cmdShowPtr[1] = nCmdShow;
1417 /* Build the filename and command-line */
1419 cmdline = (char *)GlobalLock16( cmdLineHandle );
1420 lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */);
1421 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1422 if (*p) lstrcpyn32A( cmdline, p + 1, 128 );
1423 else cmdline[0] = '\0';
1424 *p = '\0';
1426 /* Now load the executable file */
1428 if (use_load_module)
1430 #ifdef WINELIB
1431 /* WINELIB: Use LoadModule() only for the program itself */
1432 use_load_module = 0;
1433 params.hEnvironment = (HGLOBAL16)GetDOSEnvironment();
1434 #else
1435 params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
1436 #endif /* WINELIB */
1437 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1438 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1439 params.reserved = 0;
1440 handle = LoadModule( filename, &params );
1441 if (handle == 2) /* file not found */
1443 /* Check that the original file name did not have a suffix */
1444 p = strrchr(filename, '.');
1445 /* if there is a '.', check if either \ OR / follow */
1446 if (!p || strchr(p, '/') || strchr(p, '\\'))
1448 p = filename + strlen(filename);
1449 strcpy( p, ".exe" );
1450 handle = LoadModule( filename, &params );
1451 *p = '\0'; /* Remove extension */
1455 else handle = 2;
1457 if (handle < 32)
1459 /* Try to start it as a unix program */
1460 if (!fork())
1462 /* Child process */
1463 const char *unixfilename;
1464 const char *argv[256], **argptr;
1465 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1466 nCmdShow == SW_SHOWMINNOACTIVE);
1468 /* get unixfilename */
1469 if (strchr(filename, '/') ||
1470 strchr(filename, ':') ||
1471 strchr(filename, '\\'))
1472 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1473 else unixfilename = filename;
1475 if (unixfilename)
1477 /* build argv */
1478 argptr = argv;
1479 if (iconic) *argptr++ = "-iconic";
1480 *argptr++ = unixfilename;
1481 p = cmdline;
1482 while (1)
1484 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1485 if (!*p) break;
1486 *argptr++ = p;
1487 while (*p && *p != ' ' && *p != '\t') p++;
1489 *argptr++ = 0;
1491 /* Execute */
1492 execvp(argv[0], (char**)argv);
1495 /* Failed ! */
1497 if (__winelib)
1499 /* build argv */
1500 argptr = argv;
1501 *argptr++ = "wine";
1502 if (iconic) *argptr++ = "-iconic";
1503 *argptr++ = lpCmdLine;
1504 *argptr++ = 0;
1506 /* Execute */
1507 execvp(argv[0] , (char**)argv);
1509 /* Failed ! */
1510 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1512 exit(1);
1516 GlobalFree16( cmdShowHandle );
1517 GlobalFree16( cmdLineHandle );
1518 return handle;
1522 /***********************************************************************
1523 * GetProcAddress16 (KERNEL.50)
1525 FARPROC16 GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1527 WORD ordinal;
1528 FARPROC16 ret;
1530 if (!hModule) hModule = GetCurrentTask();
1531 hModule = GetExePtr( hModule );
1533 if (HIWORD(name) != 0)
1535 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1536 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1537 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1539 else
1541 ordinal = LOWORD(name);
1542 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1543 hModule, ordinal );
1545 if (!ordinal) return (FARPROC16)0;
1547 ret = MODULE_GetEntryPoint( hModule, ordinal );
1549 dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1550 return ret;
1554 /***********************************************************************
1555 * GetProcAddress32 (KERNEL32.257)
1557 FARPROC32 GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1559 #ifndef WINELIB
1560 NE_MODULE *pModule;
1562 hModule = GetExePtr( hModule );
1563 if (!(pModule = MODULE_GetPtr( hModule )))
1564 return (FARPROC32)0;
1565 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1566 return (FARPROC32)0;
1567 if (pModule->flags & NE_FFLAGS_BUILTIN)
1568 return BUILTIN_GetProcAddress32( pModule, function );
1569 return PE_FindExportedFunction( pModule->pe_module, function );
1570 #else
1571 return NULL;
1572 #endif
1576 /**********************************************************************
1577 * GetExpWinVer (KERNEL.167)
1579 WORD GetExpWinVer( HMODULE16 hModule )
1581 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1582 return pModule ? pModule->expected_version : 0;
1586 /**********************************************************************
1587 * IsSharedSelector (KERNEL.345)
1589 BOOL16 IsSharedSelector( HANDLE16 selector )
1591 /* Check whether the selector belongs to a DLL */
1592 NE_MODULE *pModule = MODULE_GetPtr( GetExePtr( selector ));
1593 if (!pModule) return FALSE;
1594 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1598 /**********************************************************************
1599 * ModuleFirst (TOOLHELP.59)
1601 BOOL16 ModuleFirst( MODULEENTRY *lpme )
1603 lpme->wNext = hFirstModule;
1604 return ModuleNext( lpme );
1608 /**********************************************************************
1609 * ModuleNext (TOOLHELP.60)
1611 BOOL16 ModuleNext( MODULEENTRY *lpme )
1613 NE_MODULE *pModule;
1615 if (!lpme->wNext) return FALSE;
1616 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1617 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1618 MAX_MODULE_NAME );
1619 lpme->szModule[MAX_MODULE_NAME] = '\0';
1620 lpme->hModule = lpme->wNext;
1621 lpme->wcUsage = pModule->count;
1622 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1623 lpme->szExePath[MAX_PATH] = '\0';
1624 lpme->wNext = pModule->next;
1625 return TRUE;
1629 /**********************************************************************
1630 * ModuleFindName (TOOLHELP.61)
1632 BOOL16 ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1634 lpme->wNext = GetModuleHandle( name );
1635 return ModuleNext( lpme );
1639 /**********************************************************************
1640 * ModuleFindHandle (TOOLHELP.62)
1642 BOOL16 ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1644 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1645 lpme->wNext = hModule;
1646 return ModuleNext( lpme );