Release 970305
[wine/multimedia.git] / loader / module.c
blobb2474894c4b752079b2b18a30a5edb8eaa499032
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 "file.h"
16 #include "global.h"
17 #include "heap.h"
18 #include "hook.h"
19 #include "module.h"
20 #include "neexe.h"
21 #include "selectors.h"
22 #include "stackframe.h"
23 #include "task.h"
24 #include "toolhelp.h"
25 #include "stddebug.h"
26 #include "debug.h"
27 #include "callback.h"
29 extern HINSTANCE16 PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
31 static HMODULE16 hFirstModule = 0;
32 static HMODULE16 hCachedModule = 0; /* Module cached by MODULE_OpenFile */
35 /***********************************************************************
36 * MODULE_GetPtr
38 NE_MODULE *MODULE_GetPtr( HMODULE16 hModule )
40 NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule );
41 if (!pModule || (pModule->magic != NE_SIGNATURE) ||
42 (pModule->self != hModule)) return NULL;
43 return pModule;
47 /***********************************************************************
48 * MODULE_DumpModule
50 void MODULE_DumpModule( HMODULE16 hmodule )
52 int i, ordinal;
53 SEGTABLEENTRY *pSeg;
54 BYTE *pstr;
55 WORD *pword;
56 NE_MODULE *pModule;
58 if (!(pModule = MODULE_GetPtr( hmodule )))
60 fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
61 return;
64 /* Dump the module info */
66 printf( "Module %04x:\n", hmodule );
67 printf( "count=%d flags=%04x heap=%d stack=%d\n",
68 pModule->count, pModule->flags,
69 pModule->heap_size, pModule->stack_size );
70 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
71 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
72 pModule->seg_count, pModule->modref_count );
73 printf( "os_flags=%d swap_area=%d version=%04x\n",
74 pModule->os_flags, pModule->min_swap_area,
75 pModule->expected_version );
76 if (pModule->flags & NE_FFLAGS_WIN32)
77 printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
79 /* Dump the file info */
81 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
83 /* Dump the segment table */
85 printf( "\nSegment table:\n" );
86 pSeg = NE_SEG_TABLE( pModule );
87 for (i = 0; i < pModule->seg_count; i++, pSeg++)
88 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
89 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
90 pSeg->minsize, pSeg->selector );
92 /* Dump the resource table */
94 printf( "\nResource table:\n" );
95 if (pModule->res_table)
97 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
98 printf( "Alignment: %d\n", *pword++ );
99 while (*pword)
101 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
102 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
103 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
104 for (i = 0; i < ptr->count; i++, pname++)
105 printf( "offset=%d len=%d id=%04x\n",
106 pname->offset, pname->length, pname->id );
107 pword = (WORD *)pname;
110 else printf( "None\n" );
112 /* Dump the resident name table */
114 printf( "\nResident-name table:\n" );
115 pstr = (char *)pModule + pModule->name_table;
116 while (*pstr)
118 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
119 *(WORD *)(pstr + *pstr + 1) );
120 pstr += *pstr + 1 + sizeof(WORD);
123 /* Dump the module reference table */
125 printf( "\nModule ref table:\n" );
126 if (pModule->modref_table)
128 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
129 for (i = 0; i < pModule->modref_count; i++, pword++)
131 printf( "%d: %04x -> '%s'\n", i, *pword,
132 MODULE_GetModuleName(*pword));
135 else printf( "None\n" );
137 /* Dump the entry table */
139 printf( "\nEntry table:\n" );
140 pstr = (char *)pModule + pModule->entry_table;
141 ordinal = 1;
142 while (*pstr)
144 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
145 if (!pstr[1])
147 ordinal += *pstr;
148 pstr += 2;
150 else if ((BYTE)pstr[1] == 0xff) /* moveable */
152 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
153 for (i = 0; i < *pstr; i++, pe++)
154 printf( "%d: %02x:%04x (moveable)\n",
155 ordinal++, pe->seg_number, pe->offset );
156 pstr = (char *)pe;
158 else /* fixed */
160 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
161 for (i = 0; i < *pstr; i++, pe++)
162 printf( "%d: %04x (fixed)\n",
163 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
164 pstr = (char *)pe;
168 /* Dump the non-resident names table */
170 printf( "\nNon-resident names table:\n" );
171 if (pModule->nrname_handle)
173 pstr = (char *)GlobalLock16( pModule->nrname_handle );
174 while (*pstr)
176 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
177 *(WORD *)(pstr + *pstr + 1) );
178 pstr += *pstr + 1 + sizeof(WORD);
181 printf( "\n" );
185 /***********************************************************************
186 * MODULE_WalkModules
188 * Walk the module list and print the modules.
190 void MODULE_WalkModules(void)
192 HMODULE16 hModule = hFirstModule;
193 fprintf( stderr, "Module Flags Name\n" );
194 while (hModule)
196 NE_MODULE *pModule = MODULE_GetPtr( hModule );
197 if (!pModule)
199 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
200 return;
202 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
203 *((char *)pModule + pModule->name_table),
204 (char *)pModule + pModule->name_table + 1 );
205 hModule = pModule->next;
210 /***********************************************************************
211 * MODULE_OpenFile
213 int MODULE_OpenFile( HMODULE16 hModule )
215 NE_MODULE *pModule;
216 DOS_FULL_NAME full_name;
217 char *name;
219 static int cachedfd = -1;
221 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
222 dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
223 hModule, hCachedModule, cachedfd );
224 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
225 if (hCachedModule == hModule) return cachedfd;
226 close( cachedfd );
227 hCachedModule = hModule;
228 name = NE_MODULE_NAME( pModule );
229 if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
230 (cachedfd = open( full_name.long_name, O_RDONLY )) == -1)
231 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
232 name, hModule );
233 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
234 name, cachedfd );
235 return cachedfd;
239 /***********************************************************************
240 * MODULE_Ne2MemFlags
242 * This function translates NE segment flags to GlobalAlloc flags
244 static WORD MODULE_Ne2MemFlags(WORD flags)
246 WORD memflags = 0;
247 #if 0
248 if (flags & NE_SEGFLAGS_DISCARDABLE)
249 memflags |= GMEM_DISCARDABLE;
250 if (flags & NE_SEGFLAGS_MOVEABLE ||
251 ( ! (flags & NE_SEGFLAGS_DATA) &&
252 ! (flags & NE_SEGFLAGS_LOADED) &&
253 ! (flags & NE_SEGFLAGS_ALLOCATED)
256 memflags |= GMEM_MOVEABLE;
257 memflags |= GMEM_ZEROINIT;
258 #else
259 memflags = GMEM_ZEROINIT | GMEM_FIXED;
260 return memflags;
261 #endif
264 /***********************************************************************
265 * MODULE_AllocateSegment (WPROCS.26)
268 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
270 WORD size = wSize << wElem;
271 HANDLE16 hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
272 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
275 /***********************************************************************
276 * MODULE_CreateSegments
278 static BOOL32 MODULE_CreateSegments( HMODULE16 hModule )
280 SEGTABLEENTRY *pSegment;
281 NE_MODULE *pModule;
282 int i, minsize;
284 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
285 pSegment = NE_SEG_TABLE( pModule );
286 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
288 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
289 if (i == pModule->ss) minsize += pModule->stack_size;
290 /* The DGROUP is allocated by MODULE_CreateInstance */
291 if (i == pModule->dgroup) continue;
292 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
293 minsize, hModule,
294 !(pSegment->flags & NE_SEGFLAGS_DATA),
295 FALSE,
296 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
297 if (!pSegment->selector) return FALSE;
300 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
301 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
302 return TRUE;
306 /***********************************************************************
307 * MODULE_GetInstance
309 HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule )
311 SEGTABLEENTRY *pSegment;
312 NE_MODULE *pModule;
314 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
315 if (pModule->dgroup == 0) return hModule;
317 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
319 return pSegment->selector;
323 /***********************************************************************
324 * MODULE_CreateInstance
326 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
328 SEGTABLEENTRY *pSegment;
329 NE_MODULE *pModule;
330 int minsize;
331 HINSTANCE16 hNewInstance, hPrevInstance;
333 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
334 if (pModule->dgroup == 0) return hModule;
336 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
337 hPrevInstance = pSegment->selector;
339 /* if it's a library, create a new instance only the first time */
340 if (hPrevInstance)
342 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
343 if (params == (LOADPARAMS*)-1) return hPrevInstance;
346 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
347 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
348 minsize += pModule->heap_size;
349 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
350 minsize, hModule, FALSE, FALSE, FALSE );
351 if (!hNewInstance) return 0;
352 pSegment->selector = hNewInstance;
353 return hNewInstance;
357 /***********************************************************************
358 * MODULE_CreateDummyModule
360 * Create a dummy NE module for Win32 or Winelib.
362 HMODULE16 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
364 HMODULE16 hModule;
365 NE_MODULE *pModule;
366 SEGTABLEENTRY *pSegment;
367 char *pStr;
369 INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
370 + strlen(ofs->szPathName) + 1;
371 INT32 size = sizeof(NE_MODULE) +
372 /* loaded file info */
373 of_size +
374 /* segment table: DS,CS */
375 2 * sizeof(SEGTABLEENTRY) +
376 /* name table */
378 /* several empty tables */
381 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
382 if (!hModule) return (HMODULE16)11; /* invalid exe */
384 FarSetOwner( hModule, hModule );
385 pModule = (NE_MODULE *)GlobalLock16( hModule );
387 /* Set all used entries */
388 pModule->magic = NE_SIGNATURE;
389 pModule->count = 1;
390 pModule->next = 0;
391 pModule->flags = 0;
392 pModule->dgroup = 1;
393 pModule->ss = 1;
394 pModule->cs = 2;
395 pModule->heap_size = 0xe000;
396 pModule->stack_size = 0x1000;
397 pModule->seg_count = 2;
398 pModule->modref_count = 0;
399 pModule->nrname_size = 0;
400 pModule->fileinfo = sizeof(NE_MODULE);
401 pModule->os_flags = NE_OSFLAGS_WINDOWS;
402 pModule->expected_version = 0x030a;
403 pModule->self = hModule;
405 /* Set loaded file information */
406 memcpy( pModule + 1, ofs, of_size );
407 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
409 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
410 pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
411 /* Data segment */
412 pSegment->size = 0;
413 pSegment->flags = NE_SEGFLAGS_DATA;
414 pSegment->minsize = 0x1000;
415 pSegment++;
416 /* Code segment */
417 pSegment->flags = 0;
418 pSegment++;
420 /* Module name */
421 pStr = (char *)pSegment;
422 pModule->name_table = (int)pStr - (int)pModule;
423 strcpy( pStr, "\x08W32SXXXX" );
424 pStr += 9;
426 /* All tables zero terminated */
427 pModule->res_table = pModule->import_table = pModule->entry_table =
428 (int)pStr - (int)pModule;
430 MODULE_RegisterModule( pModule );
431 return hModule;
435 /***********************************************************************
436 * MODULE_LoadExeHeader
438 static HMODULE16 MODULE_LoadExeHeader( HFILE32 hFile, OFSTRUCT *ofs )
440 struct mz_header_s mz_header;
441 struct ne_header_s ne_header;
442 int size;
443 HMODULE16 hModule;
444 NE_MODULE *pModule;
445 BYTE *pData;
446 char *buffer, *fastload = NULL;
447 int fastload_offset = 0, fastload_length = 0;
449 /* Read a block from either the file or the fast-load area. */
450 #define READ(offset,size,buffer) \
451 ((fastload && ((offset) >= fastload_offset) && \
452 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
453 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
454 (_llseek32( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
455 _lread32( hFile, (buffer), (size) ) == (size)))
457 _llseek32( hFile, 0, SEEK_SET );
458 if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
459 (mz_header.mz_magic != MZ_SIGNATURE))
460 return (HMODULE16)11; /* invalid exe */
462 _llseek32( hFile, mz_header.ne_offset, SEEK_SET );
463 if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
464 return (HMODULE16)11; /* invalid exe */
466 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE16)21; /* win32 exe */
467 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE16)11; /* invalid exe */
469 /* We now have a valid NE header */
471 size = sizeof(NE_MODULE) +
472 /* loaded file info */
473 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
474 /* segment table */
475 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
476 /* resource table */
477 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
478 /* resident names table */
479 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
480 /* module ref table */
481 ne_header.n_mod_ref_tab * sizeof(WORD) +
482 /* imported names table */
483 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
484 /* entry table length */
485 ne_header.entry_tab_length;
487 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
488 if (!hModule) return (HMODULE16)11; /* invalid exe */
489 FarSetOwner( hModule, hModule );
490 pModule = (NE_MODULE *)GlobalLock16( hModule );
491 memcpy( pModule, &ne_header, sizeof(ne_header) );
492 pModule->count = 0;
493 pModule->pe_module = NULL;
494 pModule->self = hModule;
495 pModule->self_loading_sel = 0;
496 pData = (BYTE *)(pModule + 1);
498 /* Clear internal Wine flags in case they are set in the EXE file */
500 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
502 /* Read the fast-load area */
504 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
506 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
507 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
508 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
509 fastload_offset, fastload_length );
510 if ((fastload = HeapAlloc( SystemHeap, 0, fastload_length )) != NULL)
512 _llseek32( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET);
513 if (_lread32(hFile, fastload, fastload_length) != fastload_length)
515 HeapFree( SystemHeap, 0, fastload );
516 fastload = NULL;
521 /* Store the filename information */
523 pModule->fileinfo = (int)pData - (int)pModule;
524 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
525 memcpy( pData, ofs, size );
526 ((OFSTRUCT *)pData)->cBytes = size - 1;
527 pData += size;
529 /* Get the segment table */
531 pModule->seg_table = (int)pData - (int)pModule;
532 buffer = HeapAlloc( SystemHeap, 0, ne_header.n_segment_tab *
533 sizeof(struct ne_segment_table_entry_s));
534 if (buffer)
536 int i;
537 struct ne_segment_table_entry_s *pSeg;
539 if (!READ( ne_header.segment_tab_offset,
540 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
541 buffer ))
543 HeapFree( SystemHeap, 0, buffer );
544 HeapFree( SystemHeap, 0, fastload );
545 GlobalFree16( hModule );
546 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 HeapFree( SystemHeap, 0, buffer );
556 else
558 HeapFree( SystemHeap, 0, fastload );
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 HeapFree( SystemHeap, 0, fastload );
583 GlobalFree16( hModule );
584 return (HMODULE16)11; /* invalid exe */
586 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
588 /* Get the module references table */
590 if (ne_header.n_mod_ref_tab > 0)
592 pModule->modref_table = (int)pData - (int)pModule;
593 if (!READ( ne_header.moduleref_tab_offset,
594 ne_header.n_mod_ref_tab * sizeof(WORD),
595 pData ))
597 HeapFree( SystemHeap, 0, fastload );
598 GlobalFree16( hModule );
599 return (HMODULE16)11; /* invalid exe */
601 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
603 else pModule->modref_table = 0; /* No module references */
605 /* Get the imported names table */
607 pModule->import_table = (int)pData - (int)pModule;
608 if (!READ( ne_header.iname_tab_offset,
609 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
610 pData ))
612 HeapFree( SystemHeap, 0, fastload );
613 GlobalFree16( hModule );
614 return (HMODULE16)11; /* invalid exe */
616 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
618 /* Get the entry table */
620 pModule->entry_table = (int)pData - (int)pModule;
621 if (!READ( ne_header.entry_tab_offset,
622 ne_header.entry_tab_length,
623 pData ))
625 HeapFree( SystemHeap, 0, fastload );
626 GlobalFree16( hModule );
627 return (HMODULE16)11; /* invalid exe */
629 pData += ne_header.entry_tab_length;
631 /* Free the fast-load area */
633 #undef READ
634 HeapFree( SystemHeap, 0, fastload );
636 /* Get the non-resident names table */
638 if (ne_header.nrname_tab_length)
640 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
641 hModule, FALSE, FALSE, FALSE );
642 if (!pModule->nrname_handle)
644 GlobalFree16( hModule );
645 return (HMODULE16)11; /* invalid exe */
647 buffer = GlobalLock16( pModule->nrname_handle );
648 _llseek32( hFile, ne_header.nrname_tab_offset, SEEK_SET );
649 if (_lread32( hFile, buffer, ne_header.nrname_tab_length )
650 != ne_header.nrname_tab_length)
652 GlobalFree16( pModule->nrname_handle );
653 GlobalFree16( hModule );
654 return (HMODULE16)11; /* invalid exe */
657 else pModule->nrname_handle = 0;
659 /* Allocate a segment for the implicitly-loaded DLLs */
661 if (pModule->modref_count)
663 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
664 (pModule->modref_count+1)*sizeof(HMODULE16),
665 hModule, FALSE, FALSE, FALSE );
666 if (!pModule->dlls_to_init)
668 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
669 GlobalFree16( hModule );
670 return (HMODULE16)11; /* invalid exe */
673 else pModule->dlls_to_init = 0;
675 MODULE_RegisterModule( pModule );
676 return hModule;
680 /***********************************************************************
681 * MODULE_GetOrdinal
683 * Lookup the ordinal for a given name.
685 WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name )
687 char buffer[256], *cpnt;
688 BYTE len;
689 NE_MODULE *pModule;
691 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
693 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
694 hModule, name );
696 /* First handle names of the form '#xxxx' */
698 if (name[0] == '#') return atoi( name + 1 );
700 /* Now copy and uppercase the string */
702 strcpy( buffer, name );
703 CharUpper32A( buffer );
704 len = strlen( buffer );
706 /* First search the resident names */
708 cpnt = (char *)pModule + pModule->name_table;
710 /* Skip the first entry (module name) */
711 cpnt += *cpnt + 1 + sizeof(WORD);
712 while (*cpnt)
714 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
716 dprintf_module( stddeb, " Found: ordinal=%d\n",
717 *(WORD *)(cpnt + *cpnt + 1) );
718 return *(WORD *)(cpnt + *cpnt + 1);
720 cpnt += *cpnt + 1 + sizeof(WORD);
723 /* Now search the non-resident names table */
725 if (!pModule->nrname_handle) return 0; /* No non-resident table */
726 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
728 /* Skip the first entry (module description string) */
729 cpnt += *cpnt + 1 + sizeof(WORD);
730 while (*cpnt)
732 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
734 dprintf_module( stddeb, " Found: ordinal=%d\n",
735 *(WORD *)(cpnt + *cpnt + 1) );
736 return *(WORD *)(cpnt + *cpnt + 1);
738 cpnt += *cpnt + 1 + sizeof(WORD);
740 return 0;
744 /***********************************************************************
745 * MODULE_GetEntryPoint
747 * Return the entry point for a given ordinal.
749 FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
751 NE_MODULE *pModule;
752 WORD curOrdinal = 1;
753 BYTE *p;
754 WORD sel, offset;
756 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
758 p = (BYTE *)pModule + pModule->entry_table;
759 while (*p && (curOrdinal + *p <= ordinal))
761 /* Skipping this bundle */
762 curOrdinal += *p;
763 switch(p[1])
765 case 0: p += 2; break; /* unused */
766 case 0xff: p += 2 + *p * 6; break; /* moveable */
767 default: p += 2 + *p * 3; break; /* fixed */
770 if (!*p) return 0;
772 switch(p[1])
774 case 0: /* unused */
775 return 0;
776 case 0xff: /* moveable */
777 p += 2 + 6 * (ordinal - curOrdinal);
778 sel = p[3];
779 offset = *(WORD *)(p + 4);
780 break;
781 default: /* fixed */
782 sel = p[1];
783 p += 2 + 3 * (ordinal - curOrdinal);
784 offset = *(WORD *)(p + 1);
785 break;
788 if (sel == 0xfe) sel = 0xffff; /* constant entry */
789 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
790 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
794 /***********************************************************************
795 * MODULE_SetEntryPoint
797 * Change the value of an entry point. Use with caution!
798 * It can only change the offset value, not the selector.
800 BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
802 NE_MODULE *pModule;
803 WORD curOrdinal = 1;
804 BYTE *p;
806 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
808 p = (BYTE *)pModule + pModule->entry_table;
809 while (*p && (curOrdinal + *p <= ordinal))
811 /* Skipping this bundle */
812 curOrdinal += *p;
813 switch(p[1])
815 case 0: p += 2; break; /* unused */
816 case 0xff: p += 2 + *p * 6; break; /* moveable */
817 default: p += 2 + *p * 3; break; /* fixed */
820 if (!*p) return FALSE;
822 switch(p[1])
824 case 0: /* unused */
825 return FALSE;
826 case 0xff: /* moveable */
827 p += 2 + 6 * (ordinal - curOrdinal);
828 *(WORD *)(p + 4) = offset;
829 break;
830 default: /* fixed */
831 p += 2 + 3 * (ordinal - curOrdinal);
832 *(WORD *)(p + 1) = offset;
833 break;
835 return TRUE;
839 /***********************************************************************
840 * MODULE_GetWndProcEntry16 (not a Windows API function)
842 * Return an entry point from the WPROCS dll.
844 #ifndef WINELIB
845 FARPROC16 MODULE_GetWndProcEntry16( const char *name )
847 WORD ordinal;
848 FARPROC16 ret;
849 static HMODULE16 hModule = 0;
851 if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
852 ordinal = MODULE_GetOrdinal( hModule, name );
853 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
854 fprintf( stderr, "GetWndProc16: %s not found, please report\n", name );
855 return ret;
857 #endif
860 /***********************************************************************
861 * MODULE_GetModuleName
863 LPSTR MODULE_GetModuleName( HMODULE16 hModule )
865 NE_MODULE *pModule;
866 BYTE *p, len;
867 static char buffer[10];
869 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
870 p = (BYTE *)pModule + pModule->name_table;
871 len = MIN( *p, 8 );
872 memcpy( buffer, p + 1, len );
873 buffer[len] = '\0';
874 return buffer;
878 /**********************************************************************
879 * MODULE_RegisterModule
881 void MODULE_RegisterModule( NE_MODULE *pModule )
883 pModule->next = hFirstModule;
884 hFirstModule = pModule->self;
888 /**********************************************************************
889 * MODULE_FindModule
891 * Find a module from a path name.
893 HMODULE16 MODULE_FindModule( LPCSTR path )
895 HMODULE16 hModule = hFirstModule;
896 LPCSTR filename, dotptr, modulepath, modulename;
897 BYTE len, *name_table;
899 if (!(filename = strrchr( path, '\\' ))) filename = path;
900 else filename++;
901 if ((dotptr = strrchr( filename, '.' )) != NULL)
902 len = (BYTE)(dotptr - filename);
903 else len = strlen( filename );
905 while(hModule)
907 NE_MODULE *pModule = MODULE_GetPtr( hModule );
908 if (!pModule) break;
909 modulepath = NE_MODULE_NAME(pModule);
910 if (!(modulename = strrchr( modulepath, '\\' )))
911 modulename = modulepath;
912 else modulename++;
913 if (!lstrcmpi32A( modulename, filename )) return hModule;
915 name_table = (BYTE *)pModule + pModule->name_table;
916 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
917 return hModule;
918 hModule = pModule->next;
920 return 0;
924 /**********************************************************************
925 * MODULE_CallWEP
927 * Call a DLL's WEP, allowing it to shut down.
928 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
930 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
932 FARPROC16 WEP = (FARPROC16)0;
933 WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
935 if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
936 if (!WEP)
938 dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
939 return FALSE;
941 return CallWindowsExitProc( WEP, WEP_FREE_DLL );
945 /**********************************************************************
946 * MODULE_FreeModule
948 * Remove a module from memory.
950 static void MODULE_FreeModule( HMODULE16 hModule )
952 HMODULE16 *hPrevModule;
953 NE_MODULE *pModule;
954 SEGTABLEENTRY *pSegment;
955 HMODULE16 *pModRef;
956 int i;
958 if (!(pModule = MODULE_GetPtr( hModule ))) return;
959 if (pModule->flags & NE_FFLAGS_BUILTIN)
960 return; /* Can't free built-in module */
962 if (pModule->flags & NE_FFLAGS_LIBMODULE) MODULE_CallWEP( hModule );
964 /* Free the objects owned by the module */
966 HOOK_FreeModuleHooks( hModule );
967 CLASS_FreeModuleClasses( hModule );
969 /* Clear magic number just in case */
971 pModule->magic = pModule->self = 0;
973 /* Remove it from the linked list */
975 hPrevModule = &hFirstModule;
976 while (*hPrevModule && (*hPrevModule != hModule))
978 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
980 if (*hPrevModule) *hPrevModule = pModule->next;
982 /* Free all the segments */
984 pSegment = NE_SEG_TABLE( pModule );
985 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
987 GlobalFree16( pSegment->selector );
990 /* Free the referenced modules */
992 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
993 for (i = 0; i < pModule->modref_count; i++, pModRef++)
995 FreeModule16( *pModRef );
998 /* Free the module storage */
1000 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
1001 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
1002 GlobalFree16( hModule );
1004 /* Remove module from cache */
1006 if (hCachedModule == hModule) hCachedModule = 0;
1010 /**********************************************************************
1011 * MODULE_Load
1013 * Implementation of LoadModule()
1015 HINSTANCE16 MODULE_Load( LPCSTR name, LPVOID paramBlock, BOOL32 first )
1017 HMODULE16 hModule;
1018 HINSTANCE16 hInstance, hPrevInstance;
1019 NE_MODULE *pModule;
1020 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1021 OFSTRUCT ofs;
1022 #ifndef WINELIB
1023 WORD *pModRef, *pDLLs;
1024 HFILE32 hFile;
1025 int i;
1026 extern const char * DEBUG_curr_module;
1028 hModule = MODULE_FindModule( name );
1030 if (!hModule) /* We have to load the module */
1032 /* Try to load the built-in first if not disabled */
1033 if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
1035 if ((hFile = OpenFile32( name, &ofs, OF_READ )) == HFILE_ERROR32)
1037 /* Now try the built-in even if disabled */
1038 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
1040 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1041 return hModule;
1043 return 2; /* File not found */
1047 * Record this so that the internal debugger gets some
1048 * record of what it is that we are working with.
1050 DEBUG_curr_module = name;
1052 /* Create the module structure */
1054 hModule = MODULE_LoadExeHeader( hFile, &ofs );
1055 if (hModule < 32)
1057 /* FIXME: Hack because PE_LoadModule is recursive */
1058 int fd = dup( FILE_GetUnixHandle(hFile) );
1059 _lclose32( hFile );
1060 if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
1061 close( fd );
1062 if (hModule < 32)
1063 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1064 name, hModule );
1065 return hModule;
1067 _lclose32( hFile );
1068 pModule = MODULE_GetPtr( hModule );
1070 /* Allocate the segments for this module */
1072 MODULE_CreateSegments( hModule );
1074 hPrevInstance = 0;
1075 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1077 /* Load the referenced DLLs */
1079 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
1080 pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
1081 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1083 char buffer[256];
1084 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
1085 memcpy( buffer, pstr + 1, *pstr );
1086 strcpy( buffer + *pstr, ".dll" );
1087 dprintf_module( stddeb, "Loading '%s'\n", buffer );
1088 if (!(*pModRef = MODULE_FindModule( buffer )))
1090 /* If the DLL is not loaded yet, load it and store */
1091 /* its handle in the list of DLLs to initialize. */
1092 HMODULE16 hDLL;
1094 if ((hDLL = MODULE_Load( buffer, (LPVOID)-1, FALSE )) == 2)
1096 /* file not found */
1097 char *p;
1099 /* Try with prepending the path of the current module */
1100 GetModuleFileName16( hModule, buffer, sizeof(buffer) );
1101 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1102 memcpy( p + 1, pstr + 1, *pstr );
1103 strcpy( p + 1 + *pstr, ".dll" );
1104 hDLL = MODULE_Load( buffer, (LPVOID)-1, FALSE );
1106 if (hDLL < 32)
1108 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1109 buffer, name, hDLL );
1110 return 2; /* file not found */
1112 *pModRef = GetExePtr( hDLL );
1113 *pDLLs++ = *pModRef;
1115 else /* Increment the reference count of the DLL */
1117 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
1118 if (pOldDLL) pOldDLL->count++;
1122 /* Load the segments */
1124 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1126 HFILE32 hf;
1127 HGLOBAL16 hInitialStack32 = 0;
1128 /* Handle self loading modules */
1129 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1130 SELFLOADHEADER *selfloadheader;
1131 STACK16FRAME *stack16Top;
1132 HMODULE16 hselfload = GetModuleHandle16("WPROCS");
1133 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1134 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1135 "Support for self-loading modules is very experimental\n",
1136 *((BYTE*)pModule + pModule->name_table),
1137 *((BYTE*)pModule + pModule->name_table),
1138 (char *)pModule + pModule->name_table + 1);
1139 NE_LoadSegment( hModule, 1 );
1140 selfloadheader = (SELFLOADHEADER *)
1141 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1142 selfloadheader->EntryAddrProc =
1143 MODULE_GetEntryPoint(hselfload,27);
1144 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1145 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
1146 pModule->self_loading_sel = GlobalHandleToSel(
1147 GLOBAL_Alloc (GMEM_ZEROINIT,
1148 0xFF00, hModule, FALSE, FALSE, FALSE)
1150 oldss = IF1632_Saved16_ss;
1151 oldsp = IF1632_Saved16_sp;
1152 IF1632_Saved16_ss = pModule->self_loading_sel;
1153 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
1154 stack16Top = CURRENT_STACK16;
1155 stack16Top->saved_ss = 0;
1156 stack16Top->saved_sp = 0;
1157 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
1158 stack16Top->entry_point = 0;
1159 stack16Top->entry_ip = 0;
1160 stack16Top->entry_cs = 0;
1161 stack16Top->bp = 0;
1162 stack16Top->ip = 0;
1163 stack16Top->cs = 0;
1165 if (!IF1632_Saved32_esp)
1167 STACK32FRAME* frame32;
1168 char *stack32Top;
1169 /* Setup an initial 32 bit stack frame */
1170 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1171 hModule, FALSE, FALSE,
1172 FALSE );
1174 /* Create the 32-bit stack frame */
1176 stack32Top = (char*)GlobalLock16(hInitialStack32) +
1177 0x10000;
1178 frame32 = (STACK32FRAME *)stack32Top - 1;
1179 frame32->saved_esp = (DWORD)stack32Top;
1180 frame32->edi = 0;
1181 frame32->esi = 0;
1182 frame32->edx = 0;
1183 frame32->ecx = 0;
1184 frame32->ebx = 0;
1185 frame32->ebp = 0;
1186 frame32->retaddr = 0;
1187 frame32->codeselector = WINE_CODE_SELECTOR;
1188 /* pTask->esp = (DWORD)frame32; */
1190 hf = FILE_DupUnixHandle( MODULE_OpenFile( hModule ) );
1191 CallTo16_word_ww( selfloadheader->BootApp, hModule, hf );
1192 _lclose32(hf);
1193 /* some BootApp procs overwrite the selector of dgroup */
1194 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1195 IF1632_Saved16_ss = oldss;
1196 IF1632_Saved16_sp = oldsp;
1197 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1198 if (hInitialStack32)
1200 GlobalFree16(hInitialStack32);
1201 hInitialStack32 = 0;
1204 else
1206 for (i = 1; i <= pModule->seg_count; i++)
1207 NE_LoadSegment( hModule, i );
1210 /* Fixup the functions prologs */
1212 NE_FixupPrologs( pModule );
1214 /* Make sure the usage count is 1 on the first loading of */
1215 /* the module, even if it contains circular DLL references */
1217 pModule->count = 1;
1219 if (first && (pModule->flags & NE_FFLAGS_LIBMODULE))
1220 NE_InitializeDLLs( hModule );
1222 else
1224 pModule = MODULE_GetPtr( hModule );
1225 hPrevInstance = MODULE_GetInstance( hModule );
1226 hInstance = MODULE_CreateInstance( hModule, params );
1227 if (hInstance != hPrevInstance) /* not a library */
1228 NE_LoadSegment( hModule, pModule->dgroup );
1229 pModule->count++;
1231 #else
1232 lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1233 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1234 pModule = (NE_MODULE *)GlobalLock16( hModule );
1235 hPrevInstance = 0;
1236 hInstance = MODULE_CreateInstance( hModule, params );
1237 #endif /* WINELIB */
1239 /* Create a task for this instance */
1241 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1243 HTASK16 hTask;
1244 WORD showcmd;
1246 /* PowerPoint passes NULL as showCmd */
1247 if (params->showCmd)
1248 showcmd = *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1);
1249 else
1250 showcmd = 0; /* FIXME: correct */
1252 hTask = TASK_CreateTask( hModule, hInstance, hPrevInstance,
1253 params->hEnvironment,
1254 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1255 showcmd );
1257 if( hTask && TASK_GetNextTask(hTask)) Yield();
1260 return hInstance;
1264 /**********************************************************************
1265 * LoadModule16 (KERNEL.45)
1267 HINSTANCE16 LoadModule16( LPCSTR name, LPVOID paramBlock )
1269 return MODULE_Load( name, paramBlock, TRUE );
1273 /**********************************************************************
1274 * FreeModule16 (KERNEL.46)
1276 BOOL16 FreeModule16( HMODULE16 hModule )
1278 NE_MODULE *pModule;
1280 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1281 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1283 dprintf_module( stddeb, "FreeModule16: %s count %d\n",
1284 MODULE_GetModuleName(hModule), pModule->count );
1285 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1286 return TRUE;
1290 /**********************************************************************
1291 * GetModuleHandle16 (KERNEL.47)
1293 HMODULE16 WIN16_GetModuleHandle( SEGPTR name )
1295 if (HIWORD(name) == 0) return GetExePtr( (HINSTANCE16)name );
1296 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1299 HMODULE16 GetModuleHandle16( LPCSTR name )
1301 return MODULE_FindModule( name );
1305 /**********************************************************************
1306 * GetModuleUsage (KERNEL.48)
1308 INT16 GetModuleUsage( HINSTANCE16 hModule )
1310 NE_MODULE *pModule;
1312 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1313 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1314 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1315 hModule, pModule->count );
1316 return pModule->count;
1320 /**********************************************************************
1321 * GetModuleFileName16 (KERNEL.49)
1323 INT16 GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName, INT16 nSize )
1325 NE_MODULE *pModule;
1327 if (!hModule) hModule = GetCurrentTask();
1328 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1329 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1330 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1331 dprintf_module( stddeb, "GetModuleFileName16: %s\n", lpFileName );
1332 return strlen(lpFileName);
1336 /***********************************************************************
1337 * GetModuleFileName32A (KERNEL32.235)
1339 DWORD GetModuleFileName32A( HMODULE32 hModule, LPSTR lpFileName, DWORD size )
1341 NE_MODULE *pModule;
1343 if (!hModule)
1345 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1346 hModule = pTask->hInstance;
1348 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1349 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1350 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
1351 dprintf_module( stddeb, "GetModuleFileName32A: %s\n", lpFileName );
1352 return strlen(lpFileName);
1356 /***********************************************************************
1357 * GetModuleFileName32W (KERNEL32.236)
1359 DWORD GetModuleFileName32W( HMODULE32 hModule, LPWSTR lpFileName, DWORD size )
1361 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1362 DWORD res = GetModuleFileName32A( hModule, fnA, size );
1363 lstrcpynAtoW( lpFileName, fnA, size );
1364 HeapFree( GetProcessHeap(), 0, fnA );
1365 return res;
1369 /**********************************************************************
1370 * GetModuleName (KERNEL.27)
1372 BOOL16 GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
1374 LPSTR name = MODULE_GetModuleName(hinst);
1376 if (!name) return FALSE;
1377 lstrcpyn32A( buf, name, nSize );
1378 return TRUE;
1382 /***********************************************************************
1383 * LoadLibrary (KERNEL.95)
1385 HINSTANCE16 LoadLibrary16( LPCSTR libname )
1387 HINSTANCE16 handle;
1389 if (__winelib)
1391 fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1392 return 0;
1394 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1396 /* This does not increment the module reference count, and will
1397 * therefore cause crashes on FreeLibrary calls.
1398 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1400 handle = MODULE_Load( libname, (LPVOID)-1, TRUE );
1401 if (handle == (HINSTANCE16)2) /* file not found */
1403 char buffer[256];
1404 lstrcpyn32A( buffer, libname, 252 );
1405 strcat( buffer, ".dll" );
1406 handle = MODULE_Load( buffer, (LPVOID)-1, TRUE );
1408 return handle;
1412 /***********************************************************************
1413 * FreeLibrary16 (KERNEL.96)
1415 void FreeLibrary16( HINSTANCE16 handle )
1417 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1418 FreeModule16( handle );
1422 /***********************************************************************
1423 * WinExec16 (KERNEL.166)
1425 HINSTANCE16 WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
1427 return WinExec32( lpCmdLine, nCmdShow );
1431 /***********************************************************************
1432 * WinExec32 (KERNEL32.566)
1434 HINSTANCE32 WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow )
1436 LOADPARAMS params;
1437 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1438 HINSTANCE16 handle;
1439 WORD *cmdShowPtr;
1440 char *p, *cmdline, filename[256];
1441 static int use_load_module = 1;
1443 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1444 return 8; /* Out of memory */
1445 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 )))
1447 GlobalFree16( cmdShowHandle );
1448 return 8; /* Out of memory */
1451 /* Store nCmdShow */
1453 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1454 cmdShowPtr[0] = 2;
1455 cmdShowPtr[1] = nCmdShow;
1457 /* Build the filename and command-line */
1459 cmdline = (char *)GlobalLock16( cmdLineHandle );
1460 lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */);
1461 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1462 if (*p) lstrcpyn32A( cmdline, p + 1, 128 );
1463 else cmdline[0] = '\0';
1464 *p = '\0';
1466 /* Now load the executable file */
1468 if (use_load_module)
1470 #ifdef WINELIB
1471 /* WINELIB: Use LoadModule() only for the program itself */
1472 use_load_module = 0;
1473 params.hEnvironment = (HGLOBAL16)GetDOSEnvironment();
1474 #else
1475 params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
1476 #endif /* WINELIB */
1477 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1478 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1479 params.reserved = 0;
1480 handle = LoadModule16( filename, &params );
1481 if (handle == 2) /* file not found */
1483 /* Check that the original file name did not have a suffix */
1484 p = strrchr(filename, '.');
1485 /* if there is a '.', check if either \ OR / follow */
1486 if (!p || strchr(p, '/') || strchr(p, '\\'))
1488 p = filename + strlen(filename);
1489 strcpy( p, ".exe" );
1490 handle = LoadModule16( filename, &params );
1491 *p = '\0'; /* Remove extension */
1495 else handle = 2;
1497 if (handle < 32)
1499 /* Try to start it as a unix program */
1500 if (!fork())
1502 /* Child process */
1503 DOS_FULL_NAME full_name;
1504 const char *unixfilename = NULL;
1505 const char *argv[256], **argptr;
1506 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1507 nCmdShow == SW_SHOWMINNOACTIVE);
1509 /* get unixfilename */
1510 if (strchr(filename, '/') ||
1511 strchr(filename, ':') ||
1512 strchr(filename, '\\'))
1514 if (DOSFS_GetFullName( filename, TRUE, &full_name ))
1515 unixfilename = full_name.long_name;
1517 else unixfilename = filename;
1519 if (unixfilename)
1521 /* build argv */
1522 argptr = argv;
1523 if (iconic) *argptr++ = "-iconic";
1524 *argptr++ = unixfilename;
1525 p = cmdline;
1526 while (1)
1528 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1529 if (!*p) break;
1530 *argptr++ = p;
1531 while (*p && *p != ' ' && *p != '\t') p++;
1533 *argptr++ = 0;
1535 /* Execute */
1536 execvp(argv[0], (char**)argv);
1539 /* Failed ! */
1541 if (__winelib)
1543 /* build argv */
1544 argptr = argv;
1545 *argptr++ = "wine";
1546 if (iconic) *argptr++ = "-iconic";
1547 *argptr++ = lpCmdLine;
1548 *argptr++ = 0;
1550 /* Execute */
1551 execvp(argv[0] , (char**)argv);
1553 /* Failed ! */
1554 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1556 exit(1);
1560 GlobalFree16( cmdShowHandle );
1561 GlobalFree16( cmdLineHandle );
1562 return handle;
1566 /***********************************************************************
1567 * GetProcAddress16 (KERNEL.50)
1569 FARPROC16 GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1571 WORD ordinal;
1572 FARPROC16 ret;
1574 if (!hModule) hModule = GetCurrentTask();
1575 hModule = GetExePtr( hModule );
1577 if (HIWORD(name) != 0)
1579 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1580 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1581 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1583 else
1585 ordinal = LOWORD(name);
1586 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1587 hModule, ordinal );
1589 if (!ordinal) return (FARPROC16)0;
1591 ret = MODULE_GetEntryPoint( hModule, ordinal );
1593 dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1594 return ret;
1598 /***********************************************************************
1599 * GetProcAddress32 (KERNEL32.257)
1601 FARPROC32 GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1603 #ifndef WINELIB
1604 NE_MODULE *pModule;
1606 hModule = GetExePtr( hModule );
1607 if (!(pModule = MODULE_GetPtr( hModule )))
1608 return (FARPROC32)0;
1609 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1610 return (FARPROC32)0;
1611 if (pModule->flags & NE_FFLAGS_BUILTIN)
1612 return BUILTIN_GetProcAddress32( pModule, function );
1613 return PE_FindExportedFunction( pModule->pe_module, function );
1614 #else
1615 return NULL;
1616 #endif
1620 /**********************************************************************
1621 * GetExpWinVer (KERNEL.167)
1623 WORD GetExpWinVer( HMODULE16 hModule )
1625 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1626 return pModule ? pModule->expected_version : 0;
1630 /**********************************************************************
1631 * IsSharedSelector (KERNEL.345)
1633 BOOL16 IsSharedSelector( HANDLE16 selector )
1635 /* Check whether the selector belongs to a DLL */
1636 NE_MODULE *pModule = MODULE_GetPtr( GetExePtr( selector ));
1637 if (!pModule) return FALSE;
1638 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1642 /**********************************************************************
1643 * ModuleFirst (TOOLHELP.59)
1645 BOOL16 ModuleFirst( MODULEENTRY *lpme )
1647 lpme->wNext = hFirstModule;
1648 return ModuleNext( lpme );
1652 /**********************************************************************
1653 * ModuleNext (TOOLHELP.60)
1655 BOOL16 ModuleNext( MODULEENTRY *lpme )
1657 NE_MODULE *pModule;
1659 if (!lpme->wNext) return FALSE;
1660 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1661 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1662 MAX_MODULE_NAME );
1663 lpme->szModule[MAX_MODULE_NAME] = '\0';
1664 lpme->hModule = lpme->wNext;
1665 lpme->wcUsage = pModule->count;
1666 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1667 lpme->szExePath[MAX_PATH] = '\0';
1668 lpme->wNext = pModule->next;
1669 return TRUE;
1673 /**********************************************************************
1674 * ModuleFindName (TOOLHELP.61)
1676 BOOL16 ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1678 lpme->wNext = GetModuleHandle16( name );
1679 return ModuleNext( lpme );
1683 /**********************************************************************
1684 * ModuleFindHandle (TOOLHELP.62)
1686 BOOL16 ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1688 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1689 lpme->wNext = hModule;
1690 return ModuleNext( lpme );