Release 970509
[wine/multimedia.git] / loader / module.c
blob19bb6d0cf4a68883d477cf7ce71ff0e79d4244c6
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, (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, fastload_offset, SEEK_SET);
513 if (_lread32(hFile, fastload, fastload_length) != fastload_length)
515 HeapFree( SystemHeap, 0, fastload );
516 fprintf(stderr, "Error reading fast-load area !\n");
517 fastload = NULL;
522 /* Store the filename information */
524 pModule->fileinfo = (int)pData - (int)pModule;
525 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
526 memcpy( pData, ofs, size );
527 ((OFSTRUCT *)pData)->cBytes = size - 1;
528 pData += size;
530 /* Get the segment table */
532 pModule->seg_table = (int)pData - (int)pModule;
533 buffer = HeapAlloc( SystemHeap, 0, ne_header.n_segment_tab *
534 sizeof(struct ne_segment_table_entry_s));
535 if (buffer)
537 int i;
538 struct ne_segment_table_entry_s *pSeg;
540 if (!READ( mz_header.ne_offset + ne_header.segment_tab_offset,
541 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
542 buffer ))
544 HeapFree( SystemHeap, 0, buffer );
545 if (fastload) HeapFree( SystemHeap, 0, fastload );
546 GlobalFree16( hModule );
547 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 HeapFree( SystemHeap, 0, buffer );
557 else
559 if (fastload) HeapFree( SystemHeap, 0, fastload );
560 GlobalFree16( hModule );
561 return (HMODULE16)11; /* invalid exe */
564 /* Get the resource table */
566 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
568 pModule->res_table = (int)pData - (int)pModule;
569 if (!READ(mz_header.ne_offset + ne_header.resource_tab_offset,
570 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
571 pData )) return (HMODULE16)11; /* invalid exe */
572 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
574 else pModule->res_table = 0; /* No resource table */
576 /* Get the resident names table */
578 pModule->name_table = (int)pData - (int)pModule;
579 if (!READ( mz_header.ne_offset + ne_header.rname_tab_offset,
580 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
581 pData ))
583 if (fastload) HeapFree( SystemHeap, 0, fastload );
584 GlobalFree16( hModule );
585 return (HMODULE16)11; /* invalid exe */
587 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
589 /* Get the module references table */
591 if (ne_header.n_mod_ref_tab > 0)
593 pModule->modref_table = (int)pData - (int)pModule;
594 if (!READ( mz_header.ne_offset + ne_header.moduleref_tab_offset,
595 ne_header.n_mod_ref_tab * sizeof(WORD),
596 pData ))
598 if (fastload) HeapFree( SystemHeap, 0, fastload );
599 GlobalFree16( hModule );
600 return (HMODULE16)11; /* invalid exe */
602 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
604 else pModule->modref_table = 0; /* No module references */
606 /* Get the imported names table */
608 pModule->import_table = (int)pData - (int)pModule;
609 if (!READ( mz_header.ne_offset + ne_header.iname_tab_offset,
610 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
611 pData ))
613 if (fastload) HeapFree( SystemHeap, 0, fastload );
614 GlobalFree16( hModule );
615 return (HMODULE16)11; /* invalid exe */
617 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
619 /* Get the entry table */
621 pModule->entry_table = (int)pData - (int)pModule;
622 if (!READ( mz_header.ne_offset + ne_header.entry_tab_offset,
623 ne_header.entry_tab_length,
624 pData ))
626 if (fastload) HeapFree( SystemHeap, 0, fastload );
627 GlobalFree16( hModule );
628 return (HMODULE16)11; /* invalid exe */
630 pData += ne_header.entry_tab_length;
632 /* Free the fast-load area */
634 #undef READ
635 if (fastload) HeapFree( SystemHeap, 0, fastload );
637 /* Get the non-resident names table */
639 if (ne_header.nrname_tab_length)
641 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
642 hModule, FALSE, FALSE, FALSE );
643 if (!pModule->nrname_handle)
645 GlobalFree16( hModule );
646 return (HMODULE16)11; /* invalid exe */
648 buffer = GlobalLock16( pModule->nrname_handle );
649 _llseek32( hFile, ne_header.nrname_tab_offset, SEEK_SET );
650 if (_lread32( hFile, buffer, ne_header.nrname_tab_length )
651 != ne_header.nrname_tab_length)
653 GlobalFree16( pModule->nrname_handle );
654 GlobalFree16( hModule );
655 return (HMODULE16)11; /* invalid exe */
658 else pModule->nrname_handle = 0;
660 /* Allocate a segment for the implicitly-loaded DLLs */
662 if (pModule->modref_count)
664 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
665 (pModule->modref_count+1)*sizeof(HMODULE16),
666 hModule, FALSE, FALSE, FALSE );
667 if (!pModule->dlls_to_init)
669 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
670 GlobalFree16( hModule );
671 return (HMODULE16)11; /* invalid exe */
674 else pModule->dlls_to_init = 0;
676 MODULE_RegisterModule( pModule );
677 return hModule;
681 /***********************************************************************
682 * MODULE_GetOrdinal
684 * Lookup the ordinal for a given name.
686 WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name )
688 char buffer[256], *cpnt;
689 BYTE len;
690 NE_MODULE *pModule;
692 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
694 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
695 hModule, name );
697 /* First handle names of the form '#xxxx' */
699 if (name[0] == '#') return atoi( name + 1 );
701 /* Now copy and uppercase the string */
703 strcpy( buffer, name );
704 CharUpper32A( buffer );
705 len = strlen( buffer );
707 /* First search the resident names */
709 cpnt = (char *)pModule + pModule->name_table;
711 /* Skip the first entry (module name) */
712 cpnt += *cpnt + 1 + sizeof(WORD);
713 while (*cpnt)
715 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
717 dprintf_module( stddeb, " Found: ordinal=%d\n",
718 *(WORD *)(cpnt + *cpnt + 1) );
719 return *(WORD *)(cpnt + *cpnt + 1);
721 cpnt += *cpnt + 1 + sizeof(WORD);
724 /* Now search the non-resident names table */
726 if (!pModule->nrname_handle) return 0; /* No non-resident table */
727 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
729 /* Skip the first entry (module description string) */
730 cpnt += *cpnt + 1 + sizeof(WORD);
731 while (*cpnt)
733 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
735 dprintf_module( stddeb, " Found: ordinal=%d\n",
736 *(WORD *)(cpnt + *cpnt + 1) );
737 return *(WORD *)(cpnt + *cpnt + 1);
739 cpnt += *cpnt + 1 + sizeof(WORD);
741 return 0;
745 /***********************************************************************
746 * MODULE_GetEntryPoint
748 * Return the entry point for a given ordinal.
750 FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
752 NE_MODULE *pModule;
753 WORD curOrdinal = 1;
754 BYTE *p;
755 WORD sel, offset;
757 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
759 p = (BYTE *)pModule + pModule->entry_table;
760 while (*p && (curOrdinal + *p <= ordinal))
762 /* Skipping this bundle */
763 curOrdinal += *p;
764 switch(p[1])
766 case 0: p += 2; break; /* unused */
767 case 0xff: p += 2 + *p * 6; break; /* moveable */
768 default: p += 2 + *p * 3; break; /* fixed */
771 if (!*p) return 0;
773 switch(p[1])
775 case 0: /* unused */
776 return 0;
777 case 0xff: /* moveable */
778 p += 2 + 6 * (ordinal - curOrdinal);
779 sel = p[3];
780 offset = *(WORD *)(p + 4);
781 break;
782 default: /* fixed */
783 sel = p[1];
784 p += 2 + 3 * (ordinal - curOrdinal);
785 offset = *(WORD *)(p + 1);
786 break;
789 if (sel == 0xfe) sel = 0xffff; /* constant entry */
790 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
791 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
795 /***********************************************************************
796 * MODULE_SetEntryPoint
798 * Change the value of an entry point. Use with caution!
799 * It can only change the offset value, not the selector.
801 BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
803 NE_MODULE *pModule;
804 WORD curOrdinal = 1;
805 BYTE *p;
807 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
809 p = (BYTE *)pModule + pModule->entry_table;
810 while (*p && (curOrdinal + *p <= ordinal))
812 /* Skipping this bundle */
813 curOrdinal += *p;
814 switch(p[1])
816 case 0: p += 2; break; /* unused */
817 case 0xff: p += 2 + *p * 6; break; /* moveable */
818 default: p += 2 + *p * 3; break; /* fixed */
821 if (!*p) return FALSE;
823 switch(p[1])
825 case 0: /* unused */
826 return FALSE;
827 case 0xff: /* moveable */
828 p += 2 + 6 * (ordinal - curOrdinal);
829 *(WORD *)(p + 4) = offset;
830 break;
831 default: /* fixed */
832 p += 2 + 3 * (ordinal - curOrdinal);
833 *(WORD *)(p + 1) = offset;
834 break;
836 return TRUE;
840 /***********************************************************************
841 * MODULE_GetWndProcEntry16 (not a Windows API function)
843 * Return an entry point from the WPROCS dll.
845 #ifndef WINELIB
846 FARPROC16 MODULE_GetWndProcEntry16( const char *name )
848 WORD ordinal;
849 FARPROC16 ret;
850 static HMODULE16 hModule = 0;
852 if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
853 ordinal = MODULE_GetOrdinal( hModule, name );
854 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
855 fprintf( stderr, "GetWndProc16: %s not found, please report\n", name );
856 return ret;
858 #endif
861 /***********************************************************************
862 * MODULE_GetModuleName
864 LPSTR MODULE_GetModuleName( HMODULE16 hModule )
866 NE_MODULE *pModule;
867 BYTE *p, len;
868 static char buffer[10];
870 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
871 p = (BYTE *)pModule + pModule->name_table;
872 len = MIN( *p, 8 );
873 memcpy( buffer, p + 1, len );
874 buffer[len] = '\0';
875 return buffer;
879 /**********************************************************************
880 * MODULE_RegisterModule
882 void MODULE_RegisterModule( NE_MODULE *pModule )
884 pModule->next = hFirstModule;
885 hFirstModule = pModule->self;
889 /**********************************************************************
890 * MODULE_FindModule
892 * Find a module from a path name.
894 HMODULE16 MODULE_FindModule( LPCSTR path )
896 HMODULE16 hModule = hFirstModule;
897 LPCSTR filename, dotptr, modulepath, modulename;
898 BYTE len, *name_table;
900 if (!(filename = strrchr( path, '\\' ))) filename = path;
901 else filename++;
902 if ((dotptr = strrchr( filename, '.' )) != NULL)
903 len = (BYTE)(dotptr - filename);
904 else len = strlen( filename );
906 while(hModule)
908 NE_MODULE *pModule = MODULE_GetPtr( hModule );
909 if (!pModule) break;
910 modulepath = NE_MODULE_NAME(pModule);
911 if (!(modulename = strrchr( modulepath, '\\' )))
912 modulename = modulepath;
913 else modulename++;
914 if (!lstrcmpi32A( modulename, filename )) return hModule;
916 name_table = (BYTE *)pModule + pModule->name_table;
917 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
918 return hModule;
919 hModule = pModule->next;
921 return 0;
925 /**********************************************************************
926 * MODULE_CallWEP
928 * Call a DLL's WEP, allowing it to shut down.
929 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
931 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
933 FARPROC16 WEP = (FARPROC16)0;
934 WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
936 if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
937 if (!WEP)
939 dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
940 return FALSE;
942 return CallWindowsExitProc( WEP, WEP_FREE_DLL );
946 /**********************************************************************
947 * MODULE_FreeModule
949 * Remove a module from memory.
951 static void MODULE_FreeModule( HMODULE16 hModule )
953 HMODULE16 *hPrevModule;
954 NE_MODULE *pModule;
955 SEGTABLEENTRY *pSegment;
956 HMODULE16 *pModRef;
957 int i;
959 if (!(pModule = MODULE_GetPtr( hModule ))) return;
960 if (pModule->flags & NE_FFLAGS_BUILTIN)
961 return; /* Can't free built-in module */
963 if (pModule->flags & NE_FFLAGS_LIBMODULE) MODULE_CallWEP( hModule );
965 /* Free the objects owned by the module */
967 HOOK_FreeModuleHooks( hModule );
968 CLASS_FreeModuleClasses( hModule );
970 /* Clear magic number just in case */
972 pModule->magic = pModule->self = 0;
974 /* Remove it from the linked list */
976 hPrevModule = &hFirstModule;
977 while (*hPrevModule && (*hPrevModule != hModule))
979 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
981 if (*hPrevModule) *hPrevModule = pModule->next;
983 /* Free all the segments */
985 pSegment = NE_SEG_TABLE( pModule );
986 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
988 GlobalFree16( pSegment->selector );
991 /* Free the referenced modules */
993 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
994 for (i = 0; i < pModule->modref_count; i++, pModRef++)
996 FreeModule16( *pModRef );
999 /* Free the module storage */
1001 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
1002 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
1003 GlobalFree16( hModule );
1005 /* Remove module from cache */
1007 if (hCachedModule == hModule) hCachedModule = 0;
1011 /**********************************************************************
1012 * MODULE_Load
1014 * Implementation of LoadModule()
1016 HINSTANCE16 MODULE_Load( LPCSTR name, LPVOID paramBlock, BOOL32 first )
1018 HMODULE16 hModule;
1019 HINSTANCE16 hInstance, hPrevInstance;
1020 NE_MODULE *pModule;
1021 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1022 OFSTRUCT ofs;
1023 #ifndef WINELIB
1024 WORD *pModRef, *pDLLs;
1025 HFILE32 hFile;
1026 int i;
1027 extern const char * DEBUG_curr_module;
1029 hModule = MODULE_FindModule( name );
1031 if (!hModule) /* We have to load the module */
1033 /* Try to load the built-in first if not disabled */
1034 if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
1036 if ((hFile = OpenFile32( name, &ofs, OF_READ )) == HFILE_ERROR32)
1038 /* Now try the built-in even if disabled */
1039 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
1041 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1042 return hModule;
1044 return 2; /* File not found */
1048 * Record this so that the internal debugger gets some
1049 * record of what it is that we are working with.
1051 DEBUG_curr_module = name;
1053 /* Create the module structure */
1055 hModule = MODULE_LoadExeHeader( hFile, &ofs );
1056 if (hModule < 32)
1058 /* Note: PE_LoadModule closes the file */
1059 if (hModule == 21)
1060 hModule = PE_LoadModule( hFile, &ofs, paramBlock );
1061 else _lclose32( hFile );
1063 if (hModule < 32)
1064 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1065 name, hModule );
1066 return hModule;
1068 _lclose32( hFile );
1069 pModule = MODULE_GetPtr( hModule );
1071 /* Allocate the segments for this module */
1073 MODULE_CreateSegments( hModule );
1075 hPrevInstance = 0;
1076 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1078 /* Load the referenced DLLs */
1080 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
1081 pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
1082 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1084 char buffer[256];
1085 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
1086 memcpy( buffer, pstr + 1, *pstr );
1087 strcpy( buffer + *pstr, ".dll" );
1088 dprintf_module( stddeb, "Loading '%s'\n", buffer );
1089 if (!(*pModRef = MODULE_FindModule( buffer )))
1091 /* If the DLL is not loaded yet, load it and store */
1092 /* its handle in the list of DLLs to initialize. */
1093 HMODULE16 hDLL;
1095 if ((hDLL = MODULE_Load( buffer, (LPVOID)-1, FALSE )) == 2)
1097 /* file not found */
1098 char *p;
1100 /* Try with prepending the path of the current module */
1101 GetModuleFileName16( hModule, buffer, sizeof(buffer) );
1102 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1103 memcpy( p + 1, pstr + 1, *pstr );
1104 strcpy( p + 1 + *pstr, ".dll" );
1105 hDLL = MODULE_Load( buffer, (LPVOID)-1, FALSE );
1107 if (hDLL < 32)
1109 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1110 buffer, name, hDLL );
1111 return 2; /* file not found */
1113 *pModRef = GetExePtr( hDLL );
1114 *pDLLs++ = *pModRef;
1116 else /* Increment the reference count of the DLL */
1118 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
1119 if (pOldDLL) pOldDLL->count++;
1123 /* Load the segments */
1125 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1127 HFILE32 hf;
1128 HGLOBAL16 hInitialStack32 = 0;
1129 /* Handle self loading modules */
1130 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1131 SELFLOADHEADER *selfloadheader;
1132 STACK16FRAME *stack16Top;
1133 HMODULE16 hselfload = GetModuleHandle16("WPROCS");
1134 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1135 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1136 "Support for self-loading modules is very experimental\n",
1137 *((BYTE*)pModule + pModule->name_table),
1138 *((BYTE*)pModule + pModule->name_table),
1139 (char *)pModule + pModule->name_table + 1);
1140 NE_LoadSegment( hModule, 1 );
1141 selfloadheader = (SELFLOADHEADER *)
1142 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1143 selfloadheader->EntryAddrProc =
1144 MODULE_GetEntryPoint(hselfload,27);
1145 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1146 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
1147 pModule->self_loading_sel = GlobalHandleToSel(
1148 GLOBAL_Alloc (GMEM_ZEROINIT,
1149 0xFF00, hModule, FALSE, FALSE, FALSE)
1151 oldss = IF1632_Saved16_ss;
1152 oldsp = IF1632_Saved16_sp;
1153 IF1632_Saved16_ss = pModule->self_loading_sel;
1154 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
1155 stack16Top = CURRENT_STACK16;
1156 stack16Top->saved_ss = 0;
1157 stack16Top->saved_sp = 0;
1158 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
1159 stack16Top->entry_point = 0;
1160 stack16Top->entry_ip = 0;
1161 stack16Top->entry_cs = 0;
1162 stack16Top->bp = 0;
1163 stack16Top->ip = 0;
1164 stack16Top->cs = 0;
1166 if (!IF1632_Saved32_esp)
1168 STACK32FRAME* frame32;
1169 char *stack32Top;
1170 /* Setup an initial 32 bit stack frame */
1171 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1172 hModule, FALSE, FALSE,
1173 FALSE );
1175 /* Create the 32-bit stack frame */
1177 stack32Top = (char*)GlobalLock16(hInitialStack32) +
1178 0x10000;
1179 frame32 = (STACK32FRAME *)stack32Top - 1;
1180 frame32->saved_esp = (DWORD)stack32Top;
1181 frame32->edi = 0;
1182 frame32->esi = 0;
1183 frame32->edx = 0;
1184 frame32->ecx = 0;
1185 frame32->ebx = 0;
1186 frame32->ebp = 0;
1187 frame32->retaddr = 0;
1188 frame32->codeselector = WINE_CODE_SELECTOR;
1189 /* pTask->esp = (DWORD)frame32; */
1191 hf = FILE_DupUnixHandle( MODULE_OpenFile( hModule ) );
1192 CallTo16_word_ww( selfloadheader->BootApp, hModule, hf );
1193 _lclose32(hf);
1194 /* some BootApp procs overwrite the selector of dgroup */
1195 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1196 IF1632_Saved16_ss = oldss;
1197 IF1632_Saved16_sp = oldsp;
1198 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1199 if (hInitialStack32)
1201 GlobalFree16(hInitialStack32);
1202 hInitialStack32 = 0;
1205 else
1207 for (i = 1; i <= pModule->seg_count; i++)
1208 NE_LoadSegment( hModule, i );
1211 /* Fixup the functions prologs */
1213 NE_FixupPrologs( pModule );
1215 /* Make sure the usage count is 1 on the first loading of */
1216 /* the module, even if it contains circular DLL references */
1218 pModule->count = 1;
1220 if (first && (pModule->flags & NE_FFLAGS_LIBMODULE))
1221 NE_InitializeDLLs( hModule );
1223 else
1225 pModule = MODULE_GetPtr( hModule );
1226 hPrevInstance = MODULE_GetInstance( hModule );
1227 hInstance = MODULE_CreateInstance( hModule, params );
1228 if (hInstance != hPrevInstance) /* not a library */
1229 NE_LoadSegment( hModule, pModule->dgroup );
1230 pModule->count++;
1232 #else
1233 lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1234 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1235 pModule = (NE_MODULE *)GlobalLock16( hModule );
1236 hPrevInstance = 0;
1237 hInstance = MODULE_CreateInstance( hModule, params );
1238 #endif /* WINELIB */
1240 /* Create a task for this instance */
1242 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1244 HTASK16 hTask;
1245 WORD showcmd;
1247 /* PowerPoint passes NULL as showCmd */
1248 if (params->showCmd)
1249 showcmd = *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1);
1250 else
1251 showcmd = 0; /* FIXME: correct */
1253 hTask = TASK_CreateTask( hModule, hInstance, hPrevInstance,
1254 params->hEnvironment,
1255 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1256 showcmd );
1258 if( hTask && TASK_GetNextTask(hTask)) Yield();
1261 return hInstance;
1265 /**********************************************************************
1266 * LoadModule16 (KERNEL.45)
1268 HINSTANCE16 LoadModule16( LPCSTR name, LPVOID paramBlock )
1270 return MODULE_Load( name, paramBlock, TRUE );
1274 /**********************************************************************
1275 * FreeModule16 (KERNEL.46)
1277 BOOL16 FreeModule16( HMODULE16 hModule )
1279 NE_MODULE *pModule;
1281 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1282 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1284 dprintf_module( stddeb, "FreeModule16: %s count %d\n",
1285 MODULE_GetModuleName(hModule), pModule->count );
1286 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1287 return TRUE;
1291 /**********************************************************************
1292 * GetModuleHandle16 (KERNEL.47)
1294 HMODULE16 WIN16_GetModuleHandle( SEGPTR name )
1296 if (HIWORD(name) == 0) return GetExePtr( (HINSTANCE16)name );
1297 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1300 HMODULE16 GetModuleHandle16( LPCSTR name )
1302 return MODULE_FindModule( name );
1306 /**********************************************************************
1307 * GetModuleUsage (KERNEL.48)
1309 INT16 GetModuleUsage( HINSTANCE16 hModule )
1311 NE_MODULE *pModule;
1313 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1314 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1315 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1316 hModule, pModule->count );
1317 return pModule->count;
1321 /**********************************************************************
1322 * GetModuleFileName16 (KERNEL.49)
1324 INT16 GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName, INT16 nSize )
1326 NE_MODULE *pModule;
1328 if (!hModule) hModule = GetCurrentTask();
1329 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1330 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1331 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1332 dprintf_module( stddeb, "GetModuleFileName16: %s\n", lpFileName );
1333 return strlen(lpFileName);
1337 /***********************************************************************
1338 * GetModuleFileName32A (KERNEL32.235)
1340 DWORD GetModuleFileName32A( HMODULE32 hModule, LPSTR lpFileName, DWORD size )
1342 NE_MODULE *pModule;
1344 if (!hModule)
1346 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1347 hModule = pTask->hInstance;
1349 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1350 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1351 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
1352 dprintf_module( stddeb, "GetModuleFileName32A: %s\n", lpFileName );
1353 return strlen(lpFileName);
1357 /***********************************************************************
1358 * GetModuleFileName32W (KERNEL32.236)
1360 DWORD GetModuleFileName32W( HMODULE32 hModule, LPWSTR lpFileName, DWORD size )
1362 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1363 DWORD res = GetModuleFileName32A( hModule, fnA, size );
1364 lstrcpynAtoW( lpFileName, fnA, size );
1365 HeapFree( GetProcessHeap(), 0, fnA );
1366 return res;
1370 /**********************************************************************
1371 * GetModuleName (KERNEL.27)
1373 BOOL16 GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
1375 LPSTR name = MODULE_GetModuleName(hinst);
1377 if (!name) return FALSE;
1378 lstrcpyn32A( buf, name, nSize );
1379 return TRUE;
1383 /***********************************************************************
1384 * LoadLibraryEx32W (KERNEL.513)
1386 HINSTANCE16 LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf, DWORD flags )
1388 fprintf(stderr,"LoadLibraryEx32W(%s,%d,%08lx)\n",libname,hf,flags);
1389 if (!flags && !hf)
1390 return LoadLibrary32A(libname);
1391 return 0;
1394 /***********************************************************************
1395 * LoadLibrary (KERNEL.95)
1397 HINSTANCE16 LoadLibrary16( LPCSTR libname )
1399 HINSTANCE16 handle;
1401 if (__winelib)
1403 fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1404 return 0;
1406 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1408 /* This does not increment the module reference count, and will
1409 * therefore cause crashes on FreeLibrary calls.
1410 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1412 handle = MODULE_Load( libname, (LPVOID)-1, TRUE );
1413 if (handle == (HINSTANCE16)2) /* file not found */
1415 char buffer[256];
1416 lstrcpyn32A( buffer, libname, 252 );
1417 strcat( buffer, ".dll" );
1418 handle = MODULE_Load( buffer, (LPVOID)-1, TRUE );
1420 return handle;
1424 /***********************************************************************
1425 * FreeLibrary16 (KERNEL.96)
1427 void FreeLibrary16( HINSTANCE16 handle )
1429 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1430 FreeModule16( handle );
1434 /***********************************************************************
1435 * WinExec16 (KERNEL.166)
1437 HINSTANCE16 WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
1439 return WinExec32( lpCmdLine, nCmdShow );
1443 /***********************************************************************
1444 * WinExec32 (KERNEL32.566)
1446 HINSTANCE32 WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow )
1448 LOADPARAMS params;
1449 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1450 HINSTANCE16 handle;
1451 WORD *cmdShowPtr;
1452 char *p, *cmdline, filename[256];
1453 static int use_load_module = 1;
1455 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1456 return 8; /* Out of memory */
1457 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 )))
1459 GlobalFree16( cmdShowHandle );
1460 return 8; /* Out of memory */
1463 /* Store nCmdShow */
1465 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1466 cmdShowPtr[0] = 2;
1467 cmdShowPtr[1] = nCmdShow;
1469 /* Build the filename and command-line */
1471 cmdline = (char *)GlobalLock16( cmdLineHandle );
1472 lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */);
1473 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1474 if (*p) lstrcpyn32A( cmdline + 1, p + 1, 127 );
1475 else cmdline[1] = '\0';
1476 cmdline[0] = strlen( cmdline + 1 ) + 1;
1477 *p = '\0';
1479 /* Now load the executable file */
1481 if (use_load_module)
1483 #ifdef WINELIB
1484 /* WINELIB: Use LoadModule() only for the program itself */
1485 use_load_module = 0;
1486 params.hEnvironment = (HGLOBAL16)GetDOSEnvironment();
1487 #else
1488 params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
1489 #endif /* WINELIB */
1490 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1491 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1492 params.reserved = 0;
1493 handle = LoadModule16( filename, &params );
1494 if (handle == 2) /* file not found */
1496 /* Check that the original file name did not have a suffix */
1497 p = strrchr(filename, '.');
1498 /* if there is a '.', check if either \ OR / follow */
1499 if (!p || strchr(p, '/') || strchr(p, '\\'))
1501 p = filename + strlen(filename);
1502 strcpy( p, ".exe" );
1503 handle = LoadModule16( filename, &params );
1504 *p = '\0'; /* Remove extension */
1508 else handle = 2;
1510 if (handle < 32)
1512 /* Try to start it as a unix program */
1513 if (!fork())
1515 /* Child process */
1516 DOS_FULL_NAME full_name;
1517 const char *unixfilename = NULL;
1518 const char *argv[256], **argptr;
1519 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1520 nCmdShow == SW_SHOWMINNOACTIVE);
1522 /* get unixfilename */
1523 if (strchr(filename, '/') ||
1524 strchr(filename, ':') ||
1525 strchr(filename, '\\'))
1527 if (DOSFS_GetFullName( filename, TRUE, &full_name ))
1528 unixfilename = full_name.long_name;
1530 else unixfilename = filename;
1532 if (unixfilename)
1534 /* build argv */
1535 argptr = argv;
1536 if (iconic) *argptr++ = "-iconic";
1537 *argptr++ = unixfilename;
1538 p = cmdline;
1539 while (1)
1541 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1542 if (!*p) break;
1543 *argptr++ = p;
1544 while (*p && *p != ' ' && *p != '\t') p++;
1546 *argptr++ = 0;
1548 /* Execute */
1549 execvp(argv[0], (char**)argv);
1552 /* Failed ! */
1554 if (__winelib)
1556 /* build argv */
1557 argptr = argv;
1558 *argptr++ = "wine";
1559 if (iconic) *argptr++ = "-iconic";
1560 *argptr++ = lpCmdLine;
1561 *argptr++ = 0;
1563 /* Execute */
1564 execvp(argv[0] , (char**)argv);
1566 /* Failed ! */
1567 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1569 exit(1);
1573 GlobalFree16( cmdShowHandle );
1574 GlobalFree16( cmdLineHandle );
1575 return handle;
1579 /***********************************************************************
1580 * GetProcAddress16 (KERNEL.50)
1582 FARPROC16 GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1584 WORD ordinal;
1585 FARPROC16 ret;
1587 if (!hModule) hModule = GetCurrentTask();
1588 hModule = GetExePtr( hModule );
1590 if (HIWORD(name) != 0)
1592 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1593 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1594 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1596 else
1598 ordinal = LOWORD(name);
1599 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1600 hModule, ordinal );
1602 if (!ordinal) return (FARPROC16)0;
1604 ret = MODULE_GetEntryPoint( hModule, ordinal );
1606 dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1607 return ret;
1611 /***********************************************************************
1612 * GetProcAddress32 (KERNEL32.257)
1614 FARPROC32 GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1616 #ifndef WINELIB
1617 NE_MODULE *pModule;
1619 if (HIWORD(function))
1620 dprintf_win32(stddeb,"GetProcAddress32(%08lx,%s)\n",(DWORD)hModule,function);
1621 else
1622 dprintf_win32(stddeb,"GetProcAddress32(%08lx,%p)\n",(DWORD)hModule,function);
1623 hModule = GetExePtr( hModule );
1624 if (!(pModule = MODULE_GetPtr( hModule )))
1625 return (FARPROC32)0;
1626 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1627 return (FARPROC32)0;
1628 if (pModule->flags & NE_FFLAGS_BUILTIN)
1629 return BUILTIN_GetProcAddress32( pModule, function );
1630 return PE_FindExportedFunction( pModule->pe_module, function );
1631 #else
1632 return NULL;
1633 #endif
1636 /***********************************************************************
1637 * RtlImageNtHeaders (NTDLL)
1639 LPIMAGE_NT_HEADERS
1640 RtlImageNtHeader(HMODULE32 hModule)
1642 #ifndef WINELIB
1643 NE_MODULE *pModule;
1645 hModule = GetExePtr( hModule );
1646 if (!(pModule = MODULE_GetPtr( hModule )))
1647 return (LPIMAGE_NT_HEADERS)0;
1648 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1649 return (LPIMAGE_NT_HEADERS)0;
1650 return pModule->pe_module->pe_header;
1651 #else
1652 return NULL;
1653 #endif
1657 /**********************************************************************
1658 * GetExpWinVer (KERNEL.167)
1660 WORD GetExpWinVer( HMODULE16 hModule )
1662 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1663 return pModule ? pModule->expected_version : 0;
1667 /**********************************************************************
1668 * IsSharedSelector (KERNEL.345)
1670 BOOL16 IsSharedSelector( HANDLE16 selector )
1672 /* Check whether the selector belongs to a DLL */
1673 NE_MODULE *pModule = MODULE_GetPtr( GetExePtr( selector ));
1674 if (!pModule) return FALSE;
1675 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1679 /**********************************************************************
1680 * ModuleFirst (TOOLHELP.59)
1682 BOOL16 ModuleFirst( MODULEENTRY *lpme )
1684 lpme->wNext = hFirstModule;
1685 return ModuleNext( lpme );
1689 /**********************************************************************
1690 * ModuleNext (TOOLHELP.60)
1692 BOOL16 ModuleNext( MODULEENTRY *lpme )
1694 NE_MODULE *pModule;
1696 if (!lpme->wNext) return FALSE;
1697 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1698 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1699 MAX_MODULE_NAME );
1700 lpme->szModule[MAX_MODULE_NAME] = '\0';
1701 lpme->hModule = lpme->wNext;
1702 lpme->wcUsage = pModule->count;
1703 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1704 lpme->szExePath[MAX_PATH] = '\0';
1705 lpme->wNext = pModule->next;
1706 return TRUE;
1710 /**********************************************************************
1711 * ModuleFindName (TOOLHELP.61)
1713 BOOL16 ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1715 lpme->wNext = GetModuleHandle16( name );
1716 return ModuleNext( lpme );
1720 /**********************************************************************
1721 * ModuleFindHandle (TOOLHELP.62)
1723 BOOL16 ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1725 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1726 lpme->wNext = hModule;
1727 return ModuleNext( lpme );