Release 980315
[wine/multimedia.git] / loader / module.c
blob7a8d58526c6cf21e0a8f36116ddf5fd28283b71c
1 /*
2 * Modules
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14 #include "windows.h"
15 #include "class.h"
16 #include "file.h"
17 #include "global.h"
18 #include "heap.h"
19 #include "module.h"
20 #include "neexe.h"
21 #include "process.h"
22 #include "thread.h"
23 #include "resource.h"
24 #include "selectors.h"
25 #include "stackframe.h"
26 #include "task.h"
27 #include "toolhelp.h"
28 #include "debug.h"
29 #include "callback.h"
31 extern HINSTANCE16 PE_LoadModule( HFILE32 hf, OFSTRUCT *ofs, LOADPARAMS* params );
33 extern BOOL32 THREAD_InitDone;
35 static HMODULE16 hFirstModule = 0;
36 static HMODULE16 hCachedModule = 0; /* Module cached by MODULE_OpenFile */
38 static HMODULE32 MODULE_LoadModule(LPCSTR name,BOOL32 force) { return 0; }
39 HMODULE32 (*fnBUILTIN_LoadModule)(LPCSTR name,BOOL32 force) = MODULE_LoadModule;
42 /***********************************************************************
43 * MODULE_GetPtr
45 NE_MODULE *MODULE_GetPtr( HMODULE32 hModule )
47 HMODULE16 hnd =MODULE_HANDLEtoHMODULE16(hModule);
49 if (!hnd)
50 return NULL;
51 return (NE_MODULE*)GlobalLock16(hnd);
54 /***********************************************************************
55 * MODULE_HANDLEtoHMODULE16
57 HMODULE16
58 MODULE_HANDLEtoHMODULE16(HANDLE32 handle) {
59 NE_MODULE *pModule;
61 if (HIWORD(handle))
63 /* this is a HMODULE32 */
65 /* walk the list looking for the correct startaddress */
66 pModule = (NE_MODULE *)GlobalLock16( hFirstModule );
67 while (pModule)
69 if (pModule->module32 == handle) return pModule->self;
70 pModule = (NE_MODULE*)GlobalLock16(pModule->next);
72 return 0;
74 return GetExePtr(handle);
77 /***********************************************************************
78 * MODULE_HANDLEtoHMODULE32
79 * return HMODULE32, if possible, HMODULE16 otherwise
81 HMODULE32
82 MODULE_HANDLEtoHMODULE32(HANDLE32 handle) {
83 NE_MODULE *pModule;
85 if (HIWORD(handle))
86 return (HMODULE32)handle;
87 else {
88 handle = GetExePtr(handle);
89 if (!handle)
90 return 0;
91 pModule = (NE_MODULE *)GlobalLock16( handle );
92 if (!pModule)
93 return 0;
95 if (pModule->module32) return pModule->module32;
96 return handle;
100 /***********************************************************************
101 * MODULE_DumpModule
103 void MODULE_DumpModule( HMODULE32 hModule )
105 int i, ordinal;
106 SEGTABLEENTRY *pSeg;
107 BYTE *pstr;
108 WORD *pword;
109 NE_MODULE *pModule;
111 if (!(pModule = MODULE_GetPtr( hModule )))
113 fprintf( stderr, "**** %04x is not a module handle\n", hModule );
114 return;
117 /* Dump the module info */
119 printf( "Module %04x:\n", hModule );
120 printf( "count=%d flags=%04x heap=%d stack=%d\n",
121 pModule->count, pModule->flags,
122 pModule->heap_size, pModule->stack_size );
123 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
124 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
125 pModule->seg_count, pModule->modref_count );
126 printf( "os_flags=%d swap_area=%d version=%04x\n",
127 pModule->os_flags, pModule->min_swap_area,
128 pModule->expected_version );
129 if (pModule->flags & NE_FFLAGS_WIN32)
130 printf( "PE module=%08x\n", pModule->module32 );
132 /* Dump the file info */
134 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
136 /* Dump the segment table */
138 printf( "\nSegment table:\n" );
139 pSeg = NE_SEG_TABLE( pModule );
140 for (i = 0; i < pModule->seg_count; i++, pSeg++)
141 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
142 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
143 pSeg->minsize, pSeg->selector );
145 /* Dump the resource table */
147 printf( "\nResource table:\n" );
148 if (pModule->res_table)
150 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
151 printf( "Alignment: %d\n", *pword++ );
152 while (*pword)
154 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
155 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
156 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
157 for (i = 0; i < ptr->count; i++, pname++)
158 printf( "offset=%d len=%d id=%04x\n",
159 pname->offset, pname->length, pname->id );
160 pword = (WORD *)pname;
163 else printf( "None\n" );
165 /* Dump the resident name table */
167 printf( "\nResident-name table:\n" );
168 pstr = (char *)pModule + pModule->name_table;
169 while (*pstr)
171 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
172 *(WORD *)(pstr + *pstr + 1) );
173 pstr += *pstr + 1 + sizeof(WORD);
176 /* Dump the module reference table */
178 printf( "\nModule ref table:\n" );
179 if (pModule->modref_table)
181 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
182 for (i = 0; i < pModule->modref_count; i++, pword++)
184 printf( "%d: %04x -> '%s'\n", i, *pword,
185 MODULE_GetModuleName(*pword));
188 else printf( "None\n" );
190 /* Dump the entry table */
192 printf( "\nEntry table:\n" );
193 pstr = (char *)pModule + pModule->entry_table;
194 ordinal = 1;
195 while (*pstr)
197 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
198 if (!pstr[1])
200 ordinal += *pstr;
201 pstr += 2;
203 else if ((BYTE)pstr[1] == 0xff) /* moveable */
205 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
206 for (i = 0; i < *pstr; i++, pe++)
207 printf( "%d: %02x:%04x (moveable)\n",
208 ordinal++, pe->seg_number, pe->offset );
209 pstr = (char *)pe;
211 else /* fixed */
213 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
214 for (i = 0; i < *pstr; i++, pe++)
215 printf( "%d: %04x (fixed)\n",
216 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
217 pstr = (char *)pe;
221 /* Dump the non-resident names table */
223 printf( "\nNon-resident names table:\n" );
224 if (pModule->nrname_handle)
226 pstr = (char *)GlobalLock16( pModule->nrname_handle );
227 while (*pstr)
229 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
230 *(WORD *)(pstr + *pstr + 1) );
231 pstr += *pstr + 1 + sizeof(WORD);
234 printf( "\n" );
238 /***********************************************************************
239 * MODULE_WalkModules
241 * Walk the module list and print the modules.
243 void MODULE_WalkModules(void)
245 HMODULE16 hModule = hFirstModule;
246 fprintf( stderr, "Module Flags Name\n" );
247 while (hModule)
249 NE_MODULE *pModule = MODULE_GetPtr( hModule );
250 if (!pModule)
252 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
253 return;
255 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
256 *((char *)pModule + pModule->name_table),
257 (char *)pModule + pModule->name_table + 1 );
258 hModule = pModule->next;
263 /***********************************************************************
264 * MODULE_OpenFile
266 int MODULE_OpenFile( HMODULE32 hModule )
268 NE_MODULE *pModule;
269 DOS_FULL_NAME full_name;
270 char *name;
272 static int cachedfd = -1;
274 hModule = MODULE_HANDLEtoHMODULE16(hModule);
275 TRACE(module, "(%04x) cache: mod=%04x fd=%d\n",
276 hModule, hCachedModule, cachedfd );
277 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
278 if (hCachedModule == hModule) return cachedfd;
279 close( cachedfd );
280 hCachedModule = hModule;
281 name = NE_MODULE_NAME( pModule );
282 if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
283 (cachedfd = open( full_name.long_name, O_RDONLY )) == -1)
284 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
285 name, hModule );
286 TRACE(module, "opened '%s' -> %d\n",
287 name, cachedfd );
288 return cachedfd;
292 /***********************************************************************
293 * MODULE_Ne2MemFlags
295 * This function translates NE segment flags to GlobalAlloc flags
297 static WORD MODULE_Ne2MemFlags(WORD flags)
299 WORD memflags = 0;
300 #if 0
301 if (flags & NE_SEGFLAGS_DISCARDABLE)
302 memflags |= GMEM_DISCARDABLE;
303 if (flags & NE_SEGFLAGS_MOVEABLE ||
304 ( ! (flags & NE_SEGFLAGS_DATA) &&
305 ! (flags & NE_SEGFLAGS_LOADED) &&
306 ! (flags & NE_SEGFLAGS_ALLOCATED)
309 memflags |= GMEM_MOVEABLE;
310 memflags |= GMEM_ZEROINIT;
311 #else
312 memflags = GMEM_ZEROINIT | GMEM_FIXED;
313 return memflags;
314 #endif
317 /***********************************************************************
318 * MODULE_AllocateSegment (WPROCS.26)
321 DWORD WINAPI MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
323 WORD size = wSize << wElem;
324 HANDLE16 hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
325 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
328 /***********************************************************************
329 * MODULE_CreateSegments
331 static BOOL32 MODULE_CreateSegments( HMODULE32 hModule )
333 SEGTABLEENTRY *pSegment;
334 NE_MODULE *pModule;
335 int i, minsize;
337 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
338 pSegment = NE_SEG_TABLE( pModule );
339 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
341 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
342 if (i == pModule->ss) minsize += pModule->stack_size;
343 /* The DGROUP is allocated by MODULE_CreateInstance */
344 if (i == pModule->dgroup) continue;
345 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
346 minsize, hModule,
347 !(pSegment->flags & NE_SEGFLAGS_DATA),
348 FALSE,
349 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
350 if (!pSegment->selector) return FALSE;
353 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
354 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
355 return TRUE;
359 /***********************************************************************
360 * MODULE_GetInstance
362 HINSTANCE16 MODULE_GetInstance( HMODULE32 hModule )
364 SEGTABLEENTRY *pSegment;
365 NE_MODULE *pModule;
367 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
368 if (pModule->dgroup == 0) return hModule;
370 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
372 return pSegment->selector;
376 /***********************************************************************
377 * MODULE_CreateInstance
379 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
381 SEGTABLEENTRY *pSegment;
382 NE_MODULE *pModule;
383 int minsize;
384 HINSTANCE16 hNewInstance, hPrevInstance;
386 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
387 if (pModule->dgroup == 0) return hModule;
389 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
390 hPrevInstance = pSegment->selector;
392 /* if it's a library, create a new instance only the first time */
393 if (hPrevInstance)
395 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
396 if (params == (LOADPARAMS*)-1) return hPrevInstance;
399 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
400 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
401 minsize += pModule->heap_size;
402 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
403 minsize, hModule, FALSE, FALSE, FALSE );
404 if (!hNewInstance) return 0;
405 pSegment->selector = hNewInstance;
406 return hNewInstance;
410 /***********************************************************************
411 * MODULE_CreateDummyModule
413 * Create a dummy NE module for Win32 or Winelib.
415 HMODULE32 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
417 HMODULE32 hModule;
418 NE_MODULE *pModule;
419 SEGTABLEENTRY *pSegment;
420 char *pStr,*s;
421 int len;
422 const char* basename;
424 INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
425 + strlen(ofs->szPathName) + 1;
426 INT32 size = sizeof(NE_MODULE) +
427 /* loaded file info */
428 of_size +
429 /* segment table: DS,CS */
430 2 * sizeof(SEGTABLEENTRY) +
431 /* name table */
433 /* several empty tables */
436 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
437 if (!hModule) return (HMODULE32)11; /* invalid exe */
439 FarSetOwner( hModule, hModule );
440 pModule = (NE_MODULE *)GlobalLock16( hModule );
442 /* Set all used entries */
443 pModule->magic = IMAGE_OS2_SIGNATURE;
444 pModule->count = 1;
445 pModule->next = 0;
446 pModule->flags = 0;
447 pModule->dgroup = 1;
448 pModule->ss = 1;
449 pModule->cs = 2;
450 pModule->heap_size = 0xe000;
451 pModule->stack_size = 0x1000;
452 pModule->seg_count = 2;
453 pModule->modref_count = 0;
454 pModule->nrname_size = 0;
455 pModule->fileinfo = sizeof(NE_MODULE);
456 pModule->os_flags = NE_OSFLAGS_WINDOWS;
457 pModule->expected_version = 0x030a;
458 pModule->self = hModule;
460 /* Set loaded file information */
461 memcpy( pModule + 1, ofs, of_size );
462 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
464 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
465 pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
466 /* Data segment */
467 pSegment->size = 0;
468 pSegment->flags = NE_SEGFLAGS_DATA;
469 pSegment->minsize = 0x1000;
470 pSegment++;
471 /* Code segment */
472 pSegment->flags = 0;
473 pSegment++;
475 /* Module name */
476 pStr = (char *)pSegment;
477 pModule->name_table = (int)pStr - (int)pModule;
478 basename = strrchr(ofs->szPathName,'\\');
479 if (!basename) basename = ofs->szPathName;
480 else basename++;
481 len = strlen(basename);
482 if ((s = strchr(basename,'.'))) len = s - basename;
483 if (len > 8) len = 8;
484 *pStr = len;
485 strncpy( pStr+1, basename, len );
486 if (len < 8) pStr[len+1] = 0;
487 pStr += 9;
489 /* All tables zero terminated */
490 pModule->res_table = pModule->import_table = pModule->entry_table =
491 (int)pStr - (int)pModule;
493 MODULE_RegisterModule( pModule );
494 return hModule;
498 /***********************************************************************
499 * MODULE_LoadExeHeader
501 static HMODULE32 MODULE_LoadExeHeader( HFILE32 hFile, OFSTRUCT *ofs )
503 IMAGE_DOS_HEADER mz_header;
504 IMAGE_OS2_HEADER ne_header;
505 int size;
506 HMODULE32 hModule;
507 NE_MODULE *pModule;
508 BYTE *pData;
509 char *buffer, *fastload = NULL;
510 int fastload_offset = 0, fastload_length = 0;
512 /* Read a block from either the file or the fast-load area. */
513 #define READ(offset,size,buffer) \
514 ((fastload && ((offset) >= fastload_offset) && \
515 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
516 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
517 (_llseek32( hFile, (offset), SEEK_SET), \
518 _lread32( hFile, (buffer), (size) ) == (size)))
520 _llseek32( hFile, 0, SEEK_SET );
521 if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
522 (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
523 return (HMODULE32)11; /* invalid exe */
525 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
526 if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
527 return (HMODULE32)11; /* invalid exe */
529 if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE32)21; /* win32 exe */
530 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE32)11; /* invalid exe */
532 if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
533 fprintf(stderr, "Sorry, this is an OS/2 linear executable (LX) file !\n");
534 return (HMODULE32)12;
536 /* We now have a valid NE header */
538 size = sizeof(NE_MODULE) +
539 /* loaded file info */
540 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
541 /* segment table */
542 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
543 /* resource table */
544 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
545 /* resident names table */
546 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
547 /* module ref table */
548 ne_header.n_mod_ref_tab * sizeof(WORD) +
549 /* imported names table */
550 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
551 /* entry table length */
552 ne_header.entry_tab_length;
554 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
555 if (!hModule) return (HMODULE32)11; /* invalid exe */
556 FarSetOwner( hModule, hModule );
557 pModule = (NE_MODULE *)GlobalLock16( hModule );
558 memcpy( pModule, &ne_header, sizeof(ne_header) );
559 pModule->count = 0;
560 pModule->module32 = 0;
561 pModule->self = hModule;
562 pModule->self_loading_sel = 0;
563 pData = (BYTE *)(pModule + 1);
565 /* Clear internal Wine flags in case they are set in the EXE file */
567 pModule->flags &= ~(NE_FFLAGS_BUILTIN|NE_FFLAGS_WIN32|NE_FFLAGS_IMPLICIT);
569 /* Read the fast-load area */
571 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
573 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
574 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
575 TRACE(module, "Using fast-load area offset=%x len=%d\n",
576 fastload_offset, fastload_length );
577 if ((fastload = HeapAlloc( SystemHeap, 0, fastload_length )) != NULL)
579 _llseek32( hFile, fastload_offset, SEEK_SET);
580 if (_lread32(hFile, fastload, fastload_length) != fastload_length)
582 HeapFree( SystemHeap, 0, fastload );
583 fprintf(stderr, "Error reading fast-load area !\n");
584 fastload = NULL;
589 /* Store the filename information */
591 pModule->fileinfo = (int)pData - (int)pModule;
592 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
593 memcpy( pData, ofs, size );
594 ((OFSTRUCT *)pData)->cBytes = size - 1;
595 pData += size;
597 /* Get the segment table */
599 pModule->seg_table = (int)pData - (int)pModule;
600 buffer = HeapAlloc( SystemHeap, 0, ne_header.n_segment_tab *
601 sizeof(struct ne_segment_table_entry_s));
602 if (buffer)
604 int i;
605 struct ne_segment_table_entry_s *pSeg;
607 if (!READ( mz_header.e_lfanew + ne_header.segment_tab_offset,
608 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
609 buffer ))
611 HeapFree( SystemHeap, 0, buffer );
612 if (fastload) HeapFree( SystemHeap, 0, fastload );
613 GlobalFree16( hModule );
614 return (HMODULE32)11; /* invalid exe */
616 pSeg = (struct ne_segment_table_entry_s *)buffer;
617 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
619 memcpy( pData, pSeg, sizeof(*pSeg) );
620 pData += sizeof(SEGTABLEENTRY);
622 HeapFree( SystemHeap, 0, buffer );
624 else
626 if (fastload) HeapFree( SystemHeap, 0, fastload );
627 GlobalFree16( hModule );
628 return (HMODULE32)11; /* invalid exe */
631 /* Get the resource table */
633 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
635 pModule->res_table = (int)pData - (int)pModule;
636 if (!READ(mz_header.e_lfanew + ne_header.resource_tab_offset,
637 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
638 pData )) return (HMODULE32)11; /* invalid exe */
639 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
640 NE_InitResourceHandler( hModule );
642 else pModule->res_table = 0; /* No resource table */
644 /* Get the resident names table */
646 pModule->name_table = (int)pData - (int)pModule;
647 if (!READ( mz_header.e_lfanew + ne_header.rname_tab_offset,
648 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
649 pData ))
651 if (fastload) HeapFree( SystemHeap, 0, fastload );
652 GlobalFree16( hModule );
653 return (HMODULE32)11; /* invalid exe */
655 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
657 /* Get the module references table */
659 if (ne_header.n_mod_ref_tab > 0)
661 pModule->modref_table = (int)pData - (int)pModule;
662 if (!READ( mz_header.e_lfanew + ne_header.moduleref_tab_offset,
663 ne_header.n_mod_ref_tab * sizeof(WORD),
664 pData ))
666 if (fastload) HeapFree( SystemHeap, 0, fastload );
667 GlobalFree16( hModule );
668 return (HMODULE32)11; /* invalid exe */
670 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
672 else pModule->modref_table = 0; /* No module references */
674 /* Get the imported names table */
676 pModule->import_table = (int)pData - (int)pModule;
677 if (!READ( mz_header.e_lfanew + ne_header.iname_tab_offset,
678 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
679 pData ))
681 if (fastload) HeapFree( SystemHeap, 0, fastload );
682 GlobalFree16( hModule );
683 return (HMODULE32)11; /* invalid exe */
685 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
687 /* Get the entry table */
689 pModule->entry_table = (int)pData - (int)pModule;
690 if (!READ( mz_header.e_lfanew + ne_header.entry_tab_offset,
691 ne_header.entry_tab_length,
692 pData ))
694 if (fastload) HeapFree( SystemHeap, 0, fastload );
695 GlobalFree16( hModule );
696 return (HMODULE32)11; /* invalid exe */
698 pData += ne_header.entry_tab_length;
700 /* Free the fast-load area */
702 #undef READ
703 if (fastload) HeapFree( SystemHeap, 0, fastload );
705 /* Get the non-resident names table */
707 if (ne_header.nrname_tab_length)
709 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
710 hModule, FALSE, FALSE, FALSE );
711 if (!pModule->nrname_handle)
713 GlobalFree16( hModule );
714 return (HMODULE32)11; /* invalid exe */
716 buffer = GlobalLock16( pModule->nrname_handle );
717 _llseek32( hFile, ne_header.nrname_tab_offset, SEEK_SET );
718 if (_lread32( hFile, buffer, ne_header.nrname_tab_length )
719 != ne_header.nrname_tab_length)
721 GlobalFree16( pModule->nrname_handle );
722 GlobalFree16( hModule );
723 return (HMODULE32)11; /* invalid exe */
726 else pModule->nrname_handle = 0;
728 /* Allocate a segment for the implicitly-loaded DLLs */
730 if (pModule->modref_count)
732 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
733 (pModule->modref_count+1)*sizeof(HMODULE32),
734 hModule, FALSE, FALSE, FALSE );
735 if (!pModule->dlls_to_init)
737 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
738 GlobalFree16( hModule );
739 return (HMODULE32)11; /* invalid exe */
742 else pModule->dlls_to_init = 0;
744 MODULE_RegisterModule( pModule );
745 return hModule;
749 /***********************************************************************
750 * MODULE_GetOrdinal
752 * Lookup the ordinal for a given name.
754 WORD MODULE_GetOrdinal( HMODULE32 hModule, const char *name )
756 unsigned char buffer[256], *cpnt;
757 BYTE len;
758 NE_MODULE *pModule;
760 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
762 TRACE(module, "(%04x,'%s')\n",
763 hModule, name );
765 /* First handle names of the form '#xxxx' */
767 if (name[0] == '#') return atoi( name + 1 );
769 /* Now copy and uppercase the string */
771 strcpy( buffer, name );
772 CharUpper32A( buffer );
773 len = strlen( buffer );
775 /* First search the resident names */
777 cpnt = (char *)pModule + pModule->name_table;
779 /* Skip the first entry (module name) */
780 cpnt += *cpnt + 1 + sizeof(WORD);
781 while (*cpnt)
783 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
785 TRACE(module, " Found: ordinal=%d\n",
786 *(WORD *)(cpnt + *cpnt + 1) );
787 return *(WORD *)(cpnt + *cpnt + 1);
789 cpnt += *cpnt + 1 + sizeof(WORD);
792 /* Now search the non-resident names table */
794 if (!pModule->nrname_handle) return 0; /* No non-resident table */
795 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
797 /* Skip the first entry (module description string) */
798 cpnt += *cpnt + 1 + sizeof(WORD);
799 while (*cpnt)
801 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
803 TRACE(module, " Found: ordinal=%d\n",
804 *(WORD *)(cpnt + *cpnt + 1) );
805 return *(WORD *)(cpnt + *cpnt + 1);
807 cpnt += *cpnt + 1 + sizeof(WORD);
809 return 0;
813 /***********************************************************************
814 * MODULE_GetEntryPoint
816 * Return the entry point for a given ordinal.
818 FARPROC16 MODULE_GetEntryPoint( HMODULE32 hModule, WORD ordinal )
820 NE_MODULE *pModule;
821 WORD curOrdinal = 1;
822 BYTE *p;
823 WORD sel, offset;
825 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
827 p = (BYTE *)pModule + pModule->entry_table;
828 while (*p && (curOrdinal + *p <= ordinal))
830 /* Skipping this bundle */
831 curOrdinal += *p;
832 switch(p[1])
834 case 0: p += 2; break; /* unused */
835 case 0xff: p += 2 + *p * 6; break; /* moveable */
836 default: p += 2 + *p * 3; break; /* fixed */
839 if (!*p) return 0;
841 switch(p[1])
843 case 0: /* unused */
844 return 0;
845 case 0xff: /* moveable */
846 p += 2 + 6 * (ordinal - curOrdinal);
847 sel = p[3];
848 offset = *(WORD *)(p + 4);
849 break;
850 default: /* fixed */
851 sel = p[1];
852 p += 2 + 3 * (ordinal - curOrdinal);
853 offset = *(WORD *)(p + 1);
854 break;
857 if (sel == 0xfe) sel = 0xffff; /* constant entry */
858 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
859 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
863 /***********************************************************************
864 * EntryAddrProc (WPROCS.27)
866 FARPROC16 WINAPI EntryAddrProc( HMODULE16 hModule, WORD ordinal )
868 return MODULE_GetEntryPoint( hModule, ordinal );
872 /***********************************************************************
873 * MODULE_SetEntryPoint
875 * Change the value of an entry point. Use with caution!
876 * It can only change the offset value, not the selector.
878 BOOL16 MODULE_SetEntryPoint( HMODULE32 hModule, WORD ordinal, WORD offset )
880 NE_MODULE *pModule;
881 WORD curOrdinal = 1;
882 BYTE *p;
884 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
886 p = (BYTE *)pModule + pModule->entry_table;
887 while (*p && (curOrdinal + *p <= ordinal))
889 /* Skipping this bundle */
890 curOrdinal += *p;
891 switch(p[1])
893 case 0: p += 2; break; /* unused */
894 case 0xff: p += 2 + *p * 6; break; /* moveable */
895 default: p += 2 + *p * 3; break; /* fixed */
898 if (!*p) return FALSE;
900 switch(p[1])
902 case 0: /* unused */
903 return FALSE;
904 case 0xff: /* moveable */
905 p += 2 + 6 * (ordinal - curOrdinal);
906 *(WORD *)(p + 4) = offset;
907 break;
908 default: /* fixed */
909 p += 2 + 3 * (ordinal - curOrdinal);
910 *(WORD *)(p + 1) = offset;
911 break;
913 return TRUE;
917 /***********************************************************************
918 * MODULE_GetWndProcEntry16 (not a Windows API function)
920 * Return an entry point from the WPROCS dll.
922 FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
924 FARPROC16 ret = NULL;
926 if (__winelib)
928 /* FIXME: hack for Winelib */
929 extern LRESULT ColorDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
930 extern LRESULT FileOpenDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
931 extern LRESULT FileSaveDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
932 extern LRESULT FindTextDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
933 extern LRESULT PrintDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
934 extern LRESULT PrintSetupDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
935 extern LRESULT ReplaceTextDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
937 if (!strcmp(name,"ColorDlgProc"))
938 return (FARPROC16)ColorDlgProc;
939 if (!strcmp(name,"FileOpenDlgProc"))
940 return (FARPROC16)FileOpenDlgProc;
941 if (!strcmp(name,"FileSaveDlgProc"))
942 return (FARPROC16)FileSaveDlgProc;
943 if (!strcmp(name,"FindTextDlgProc"))
944 return (FARPROC16)FindTextDlgProc;
945 if (!strcmp(name,"PrintDlgProc"))
946 return (FARPROC16)PrintDlgProc;
947 if (!strcmp(name,"PrintSetupDlgProc"))
948 return (FARPROC16)PrintSetupDlgProc;
949 if (!strcmp(name,"ReplaceTextDlgProc"))
950 return (FARPROC16)ReplaceTextDlgProc;
951 fprintf(stderr,"warning: No mapping for %s(), add one in library/miscstubs.c\n",name);
952 assert( FALSE );
953 return NULL;
955 else
957 WORD ordinal;
958 static HMODULE32 hModule = 0;
960 if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
961 ordinal = MODULE_GetOrdinal( hModule, name );
962 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
964 fprintf( stderr, "GetWndProc16: %s not found\n", name );
965 assert( FALSE );
968 return ret;
972 /***********************************************************************
973 * MODULE_GetModuleName
975 LPSTR MODULE_GetModuleName( HMODULE32 hModule )
977 NE_MODULE *pModule;
978 BYTE *p, len;
979 static char buffer[10];
981 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
982 p = (BYTE *)pModule + pModule->name_table;
983 len = MIN( *p, 8 );
984 memcpy( buffer, p + 1, len );
985 buffer[len] = '\0';
986 return buffer;
990 /**********************************************************************
991 * MODULE_RegisterModule
993 void MODULE_RegisterModule( NE_MODULE *pModule )
995 pModule->next = hFirstModule;
996 hFirstModule = pModule->self;
1000 /**********************************************************************
1001 * MODULE_FindModule
1003 * Find a module from a path name.
1005 HMODULE32 MODULE_FindModule( LPCSTR path )
1007 HMODULE32 hModule = hFirstModule;
1008 LPCSTR filename, dotptr, modulepath, modulename;
1009 BYTE len, *name_table;
1011 if (!(filename = strrchr( path, '\\' ))) filename = path;
1012 else filename++;
1013 if ((dotptr = strrchr( filename, '.' )) != NULL)
1014 len = (BYTE)(dotptr - filename);
1015 else len = strlen( filename );
1017 while(hModule)
1019 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1020 if (!pModule) break;
1021 modulepath = NE_MODULE_NAME(pModule);
1022 if (!(modulename = strrchr( modulepath, '\\' )))
1023 modulename = modulepath;
1024 else modulename++;
1025 if (!lstrcmpi32A( modulename, filename )) return hModule;
1027 name_table = (BYTE *)pModule + pModule->name_table;
1028 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
1029 return hModule;
1030 hModule = pModule->next;
1032 return 0;
1036 /**********************************************************************
1037 * MODULE_CallWEP
1039 * Call a DLL's WEP, allowing it to shut down.
1040 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
1042 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
1044 FARPROC16 WEP = (FARPROC16)0;
1045 WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
1047 if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
1048 if (!WEP)
1050 WARN(module, "module %04x doesn't have a WEP\n", hModule );
1051 return FALSE;
1053 return Callbacks->CallWindowsExitProc( WEP, WEP_FREE_DLL );
1057 /**********************************************************************
1058 * MODULE_FreeModule
1060 * Remove a module from memory.
1062 BOOL16 MODULE_FreeModule( HMODULE32 hModule, TDB* pTaskContext )
1064 HMODULE16 *hPrevModule;
1065 NE_MODULE *pModule;
1066 SEGTABLEENTRY *pSegment;
1067 HMODULE16 *pModRef;
1068 int i;
1070 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1071 hModule = pModule->self;
1073 if (((INT16)(--pModule->count)) > 0 ) return TRUE;
1074 else pModule->count = 0;
1076 if (pModule->flags & NE_FFLAGS_BUILTIN)
1077 return FALSE; /* Can't free built-in module */
1079 if (pModule->flags & NE_FFLAGS_LIBMODULE)
1081 MODULE_CallWEP( hModule );
1083 /* Free the objects owned by the DLL module */
1085 if( pTaskContext && pTaskContext->userhandler )
1087 pTaskContext->userhandler( hModule, USIG_DLL_UNLOAD, 0,
1088 pTaskContext->hInstance,
1089 pTaskContext->hQueue );
1092 /* Clear magic number just in case */
1094 pModule->magic = pModule->self = 0;
1096 /* Remove it from the linked list */
1098 hPrevModule = &hFirstModule;
1099 while (*hPrevModule && (*hPrevModule != hModule))
1101 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
1103 if (*hPrevModule) *hPrevModule = pModule->next;
1105 /* Free all the segments */
1107 pSegment = NE_SEG_TABLE( pModule );
1108 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
1110 GlobalFree16( pSegment->selector );
1113 /* Free the referenced modules */
1115 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
1116 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1118 FreeModule16( *pModRef );
1121 /* Free the module storage */
1123 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
1124 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
1125 GlobalFree16( hModule );
1127 /* Remove module from cache */
1129 if (hCachedModule == hModule) hCachedModule = 0;
1131 return TRUE;
1135 /**********************************************************************
1136 * MODULE_Load
1138 * Implementation of LoadModule()
1140 HINSTANCE16 MODULE_Load( LPCSTR name, LPVOID paramBlock, UINT16 uFlags)
1142 HMODULE32 hModule;
1143 HINSTANCE16 hInstance, hPrevInstance;
1144 NE_MODULE *pModule;
1145 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1146 OFSTRUCT ofs;
1147 HFILE32 hFile;
1149 if (__winelib)
1151 lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1152 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1153 pModule = (NE_MODULE *)GlobalLock16( hModule );
1154 hPrevInstance = 0;
1155 hInstance = MODULE_CreateInstance( hModule, params );
1157 else
1159 hModule = MODULE_FindModule( name );
1161 if (!hModule) /* We have to load the module */
1163 /* Try to load the built-in first if not disabled */
1164 if ((hModule = fnBUILTIN_LoadModule( name, FALSE )))
1165 return MODULE_HANDLEtoHMODULE16( hModule );
1167 if ((hFile = OpenFile32( name, &ofs, OF_READ )) == HFILE_ERROR32)
1169 /* Now try the built-in even if disabled */
1170 if ((hModule = fnBUILTIN_LoadModule( name, TRUE )))
1172 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1173 return MODULE_HANDLEtoHMODULE16( hModule );
1175 return 2; /* File not found */
1178 /* Create the module structure */
1180 hModule = MODULE_LoadExeHeader( hFile, &ofs );
1181 if (hModule < 32)
1183 if (hModule == 21)
1184 hModule = PE_LoadModule( hFile, &ofs, paramBlock );
1185 else _lclose32( hFile );
1187 if (hModule < 32)
1188 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1189 name, hModule );
1190 return hModule;
1192 _lclose32( hFile );
1193 pModule = MODULE_GetPtr( hModule );
1194 pModule->flags |= uFlags; /* stamp implicitly loaded modules */
1196 /* Allocate the segments for this module */
1198 MODULE_CreateSegments( hModule );
1199 hPrevInstance = 0;
1200 hInstance = MODULE_CreateInstance(hModule,(LOADPARAMS*)paramBlock);
1202 /* Load the referenced DLLs */
1204 if (!NE_LoadDLLs( pModule )) return 2; /* File not found */
1206 /* Load the segments */
1208 NE_LoadAllSegments( pModule );
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 /* Call initialization rountines for all loaded DLLs. Note that
1220 * when we load implicitly linked DLLs this will be done by InitTask().
1223 if ((pModule->flags & (NE_FFLAGS_LIBMODULE | NE_FFLAGS_IMPLICIT)) ==
1224 NE_FFLAGS_LIBMODULE )
1225 NE_InitializeDLLs( hModule );
1227 else /* module is already loaded, just create a new data segment if it's a task */
1229 pModule = MODULE_GetPtr( hModule );
1230 hPrevInstance = MODULE_GetInstance( hModule );
1231 hInstance = MODULE_CreateInstance( hModule, params );
1232 if (hInstance != hPrevInstance) /* not a library */
1233 NE_LoadSegment( pModule, pModule->dgroup );
1234 pModule->count++;
1236 } /* !winelib */
1238 /* Create a task for this instance */
1240 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1242 HTASK16 hTask;
1243 WORD showcmd;
1245 pModule->flags |= NE_FFLAGS_GUI;
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)) Yield16();
1261 return hInstance;
1265 /**********************************************************************
1266 * LoadModule16 (KERNEL.45)
1268 HINSTANCE16 LoadModule16( LPCSTR name, LPVOID paramBlock )
1270 return MODULE_Load( name, paramBlock, 0 );
1273 /**********************************************************************
1274 * LoadModule32 (KERNEL32.499)
1276 * FIXME
1278 * This should get implemented via CreateProcess -- MODULE_Load
1279 * is resolutely 16-bit.
1281 DWORD LoadModule32( LPCSTR name, LPVOID paramBlock )
1283 #ifdef 0
1284 LOADPARAMS32 *p = paramBlock;
1285 STARTUPINFO st;
1286 PROCESSINFORMATION pi;
1287 st.cb = sizeof(STARTUPINFO);
1288 st.wShowWindow = p->lpCmdShow[2] ; WRONG
1290 BOOL32 ret = CreateProcess32A( name, p->lpCmdLine,
1291 NULL, NULL, FALSE, 0, p->lpEnvAddress,
1292 NULL, &st, &pi);
1293 if (!ret) {
1294 /* handle errors appropriately */
1296 CloseHandle32(pi.hProcess);
1297 CloseHandle32(pi.hThread);
1299 #else
1300 return MODULE_Load( name, paramBlock, 0 );
1301 #endif
1305 /**********************************************************************
1306 * FreeModule16 (KERNEL.46)
1308 BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
1310 NE_MODULE *pModule;
1312 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1313 TRACE(module, "%s count %d\n",
1314 MODULE_GetModuleName(hModule), pModule->count );
1316 return MODULE_FreeModule( hModule, GlobalLock16(GetCurrentTask()) );
1320 /**********************************************************************
1321 * GetModuleHandle16 (KERNEL.47)
1323 HMODULE16 WINAPI WIN16_GetModuleHandle( SEGPTR name )
1325 if (HIWORD(name) == 0) return MODULE_HANDLEtoHMODULE16( (HINSTANCE16)name );
1326 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1329 HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
1331 return MODULE_FindModule( name );
1334 /***********************************************************************
1335 * GetModuleHandle (KERNEL32.237)
1337 HMODULE32 WINAPI GetModuleHandle32A(LPCSTR module)
1339 HMODULE32 hModule;
1341 TRACE(win32, "%s\n", module ? module : "NULL");
1342 /* Freecell uses the result of GetModuleHandleA(0) as the hInstance in
1343 all calls to e.g. CreateWindowEx. */
1344 if (module == NULL) {
1345 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1346 hModule = pTask->hInstance;
1347 } else
1348 hModule = MODULE_FindModule(module);
1349 return MODULE_HANDLEtoHMODULE32(hModule);
1352 HMODULE32 WINAPI GetModuleHandle32W(LPCWSTR module)
1354 HMODULE32 hModule;
1355 LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
1356 hModule = GetModuleHandle32A( modulea );
1357 HeapFree( GetProcessHeap(), 0, modulea );
1358 return hModule;
1362 /**********************************************************************
1363 * GetModuleUsage (KERNEL.48)
1365 INT16 WINAPI GetModuleUsage( HINSTANCE16 hModule )
1367 NE_MODULE *pModule;
1369 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1370 TRACE(module, "(%04x): returning %d\n",
1371 hModule, pModule->count );
1372 return pModule->count;
1376 /**********************************************************************
1377 * GetModuleFileName16 (KERNEL.49)
1379 INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
1380 INT16 nSize )
1382 NE_MODULE *pModule;
1384 if (!hModule) hModule = GetCurrentTask();
1385 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1386 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1387 TRACE(module, "%s\n", lpFileName );
1388 return strlen(lpFileName);
1392 /***********************************************************************
1393 * GetModuleFileName32A (KERNEL32.235)
1395 DWORD WINAPI GetModuleFileName32A( HMODULE32 hModule, LPSTR lpFileName,
1396 DWORD size )
1398 NE_MODULE *pModule;
1400 if (!hModule)
1402 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1403 hModule = pTask->hInstance;
1405 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1406 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
1407 TRACE(module, "%s\n", lpFileName );
1408 return strlen(lpFileName);
1412 /***********************************************************************
1413 * GetModuleFileName32W (KERNEL32.236)
1415 DWORD WINAPI GetModuleFileName32W( HMODULE32 hModule, LPWSTR lpFileName,
1416 DWORD size )
1418 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1419 DWORD res = GetModuleFileName32A( hModule, fnA, size );
1420 lstrcpynAtoW( lpFileName, fnA, size );
1421 HeapFree( GetProcessHeap(), 0, fnA );
1422 return res;
1426 /**********************************************************************
1427 * GetModuleName (KERNEL.27)
1429 BOOL16 WINAPI GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
1431 LPSTR name = MODULE_GetModuleName(hinst);
1433 if (!name) return FALSE;
1434 lstrcpyn32A( buf, name, nSize );
1435 return TRUE;
1439 /***********************************************************************
1440 * LoadLibraryEx32W (KERNEL.513)
1441 * FIXME
1443 HMODULE32 WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
1444 DWORD flags )
1446 fprintf(stderr,"LoadLibraryEx32W(%s,%d,%08lx)\n",libname,hf,flags);
1447 return LoadLibraryEx32A(libname, hf,flags);
1450 /***********************************************************************
1451 * LoadLibraryEx32A (KERNEL32)
1453 HMODULE32 WINAPI LoadLibraryEx32A(LPCSTR libname,HFILE32 hfile,DWORD flags)
1455 HMODULE32 hmod;
1457 hmod = PE_LoadLibraryEx32A(libname,PROCESS_Current(),hfile,flags);
1458 if (hmod <= 32) {
1459 char buffer[256];
1461 strcpy( buffer, libname );
1462 strcat( buffer, ".dll" );
1463 hmod = PE_LoadLibraryEx32A(buffer,PROCESS_Current(),hfile,flags);
1465 /* initialize all DLLs, which haven't been initialized yet. */
1466 PE_InitializeDLLs( PROCESS_Current(), DLL_PROCESS_ATTACH, NULL);
1467 return hmod;
1470 /***********************************************************************
1471 * LoadLibraryA (KERNEL32)
1473 HMODULE32 WINAPI LoadLibrary32A(LPCSTR libname) {
1474 return LoadLibraryEx32A(libname,0,0);
1477 /***********************************************************************
1478 * LoadLibraryW (KERNEL32)
1480 HMODULE32 WINAPI LoadLibrary32W(LPCWSTR libnameW)
1482 return LoadLibraryEx32W(libnameW,0,0);
1485 /***********************************************************************
1486 * LoadLibraryExW (KERNEL32)
1488 HMODULE32 WINAPI LoadLibraryEx32W(LPCWSTR libnameW,HFILE32 hfile,DWORD flags)
1490 LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
1491 HMODULE32 ret = LoadLibraryEx32A( libnameA , hfile, flags );
1493 HeapFree( GetProcessHeap(), 0, libnameA );
1494 return ret;
1497 /***********************************************************************
1498 * FreeLibrary
1500 BOOL32 WINAPI FreeLibrary32(HINSTANCE32 hLibModule)
1502 TRACE(module,"hLibModule=%08x\n", hLibModule);
1503 return MODULE_FreeModule(hLibModule,
1504 GlobalLock16(GetCurrentTask()) );
1508 /***********************************************************************
1509 * LoadLibrary (KERNEL.95)
1511 HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
1513 HINSTANCE16 handle;
1515 if (__winelib)
1517 fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1518 return 0;
1520 TRACE(module, "(%08x) %s\n", (int)libname, libname);
1522 handle = MODULE_Load( libname, (LPVOID)-1, 0 );
1523 if (handle == (HINSTANCE16)2) /* file not found */
1525 char buffer[256];
1526 lstrcpyn32A( buffer, libname, 252 );
1527 strcat( buffer, ".dll" );
1528 handle = MODULE_Load( buffer, (LPVOID)-1, 0 );
1530 return handle;
1534 /***********************************************************************
1535 * PrivateLoadLibrary (KERNEL32)
1537 * FIXME: rough guesswork, don't know what "Private" means
1539 HINSTANCE32 WINAPI PrivateLoadLibrary(LPCSTR libname)
1541 return (HINSTANCE32)LoadLibrary16(libname);
1545 /***********************************************************************
1546 * FreeLibrary16 (KERNEL.96)
1548 void WINAPI FreeLibrary16( HINSTANCE16 handle )
1550 TRACE(module,"%04x\n", handle );
1551 FreeModule16( handle );
1555 /***********************************************************************
1556 * PrivateFreeLibrary (KERNEL32)
1558 * FIXME: rough guesswork, don't know what "Private" means
1560 void WINAPI PrivateFreeLibrary(HINSTANCE32 handle)
1562 FreeLibrary16((HINSTANCE16)handle);
1566 /***********************************************************************
1567 * WinExec16 (KERNEL.166)
1569 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
1571 return WinExec32( lpCmdLine, nCmdShow );
1575 /***********************************************************************
1576 * WinExec32 (KERNEL32.566)
1578 HINSTANCE32 WINAPI WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow )
1580 LOADPARAMS params;
1581 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1582 HINSTANCE32 handle = 2;
1583 WORD *cmdShowPtr;
1584 char *p, *cmdline, filename[256];
1585 static int use_load_module = 1;
1586 int spacelimit = 0, exhausted = 0;
1588 if (!lpCmdLine)
1589 return 2; /* File not found */
1590 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1591 return 8; /* Out of memory */
1592 if (!(cmdLineHandle = GlobalAlloc16( 0, 2048 )))
1594 GlobalFree16( cmdShowHandle );
1595 return 8; /* Out of memory */
1598 /* Keep trying to load a file by trying different filenames; e.g.,
1599 for the cmdline "abcd efg hij", try "abcd" with args "efg hij",
1600 then "abcd efg" with arg "hij", and finally "abcd efg hij" with
1601 no args */
1603 while(!exhausted && handle == 2) {
1604 int spacecount = 0;
1606 /* Store nCmdShow */
1608 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1609 cmdShowPtr[0] = 2;
1610 cmdShowPtr[1] = nCmdShow;
1612 /* Build the filename and command-line */
1614 cmdline = (char *)GlobalLock16( cmdLineHandle );
1615 lstrcpyn32A(filename, lpCmdLine,
1616 sizeof(filename) - 4 /* for extension */);
1618 /* Keep grabbing characters until end-of-string, tab, or until the
1619 number of spaces is greater than the spacelimit */
1621 for (p = filename; ; p++) {
1622 if(*p == ' ') {
1623 ++spacecount;
1624 if(spacecount > spacelimit) {
1625 ++spacelimit;
1626 break;
1630 if(*p == '\0' || *p == '\t') {
1631 exhausted = 1;
1632 break;
1636 if (*p)
1637 lstrcpyn32A( cmdline + 1, p + 1, 255 );
1638 else
1639 cmdline[1] = '\0';
1641 cmdline[0] = strlen( cmdline + 1 );
1642 *p = '\0';
1643 /* this is a (hopefully acceptable hack to get the whole
1644 commandline for PROCESS_Create
1645 we put it after the processed one */
1646 lstrcpyn32A(cmdline + (unsigned char)cmdline[0] +2,
1647 lpCmdLine, 2048 - 256);
1649 /* Now load the executable file */
1651 if (use_load_module)
1653 /* Winelib: Use LoadModule() only for the program itself */
1654 if (__winelib) use_load_module = 0;
1655 params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
1656 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1657 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1658 params.reserved = 0;
1659 handle = LoadModule32( filename, &params );
1660 if (handle == 2) /* file not found */
1662 /* Check that the original file name did not have a suffix */
1663 p = strrchr(filename, '.');
1664 /* if there is a '.', check if either \ OR / follow */
1665 if (!p || strchr(p, '/') || strchr(p, '\\'))
1667 p = filename + strlen(filename);
1668 strcpy( p, ".exe" );
1669 handle = LoadModule16( filename, &params );
1670 *p = '\0'; /* Remove extension */
1674 else
1675 handle = 2; /* file not found */
1677 if (handle < 32)
1679 /* Try to start it as a unix program */
1680 if (!fork())
1682 /* Child process */
1683 DOS_FULL_NAME full_name;
1684 const char *unixfilename = NULL;
1685 const char *argv[256], **argptr;
1686 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1687 nCmdShow == SW_SHOWMINNOACTIVE);
1689 THREAD_InitDone = FALSE; /* we didn't init this process */
1690 /* get unixfilename */
1691 if (strchr(filename, '/') ||
1692 strchr(filename, ':') ||
1693 strchr(filename, '\\'))
1695 if (DOSFS_GetFullName( filename, TRUE, &full_name ))
1696 unixfilename = full_name.long_name;
1698 else unixfilename = filename;
1700 if (unixfilename)
1702 /* build argv */
1703 argptr = argv;
1704 if (iconic) *argptr++ = "-iconic";
1705 *argptr++ = unixfilename;
1706 p = cmdline + 1;
1707 while (1)
1709 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1710 if (!*p) break;
1711 *argptr++ = p;
1712 while (*p && *p != ' ' && *p != '\t') p++;
1714 *argptr++ = 0;
1716 /* Execute */
1717 execvp(argv[0], (char**)argv);
1720 /* Failed ! */
1722 if (__winelib)
1724 /* build argv */
1725 argptr = argv;
1726 *argptr++ = "wine";
1727 if (iconic) *argptr++ = "-iconic";
1728 *argptr++ = lpCmdLine;
1729 *argptr++ = 0;
1731 /* Execute */
1732 execvp(argv[0] , (char**)argv);
1734 /* Failed ! */
1735 fprintf(stderr, "WinExec: can't exec 'wine %s'\n",
1736 lpCmdLine);
1738 exit(1);
1741 } /* while (!exhausted && handle < 32) */
1743 GlobalFree16( cmdShowHandle );
1744 GlobalFree16( cmdLineHandle );
1745 return handle;
1749 /***********************************************************************
1750 * WIN32_GetProcAddress16 (KERNEL32.36)
1751 * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1753 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE32 hModule, LPSTR name )
1755 WORD ordinal;
1756 FARPROC16 ret;
1758 if (!hModule) {
1759 fprintf(stderr,"WIN32_GetProcAddress16: hModule may not be 0!\n");
1760 return (FARPROC16)0;
1762 hModule = MODULE_HANDLEtoHMODULE16(hModule);
1763 if (HIWORD(name)) {
1764 ordinal = MODULE_GetOrdinal( hModule, name );
1765 TRACE(module, "%04x '%s'\n",
1766 hModule, name );
1767 } else {
1768 ordinal = LOWORD(name);
1769 TRACE(module, "%04x %04x\n",
1770 hModule, ordinal );
1772 if (!ordinal) return (FARPROC16)0;
1773 ret = MODULE_GetEntryPoint( hModule, ordinal );
1774 TRACE(module,"returning %08x\n",(UINT32)ret);
1775 return ret;
1778 /***********************************************************************
1779 * GetProcAddress16 (KERNEL.50)
1781 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1783 WORD ordinal;
1784 FARPROC16 ret;
1786 if (!hModule) hModule = GetCurrentTask();
1787 hModule = MODULE_HANDLEtoHMODULE16( hModule );
1789 if (HIWORD(name) != 0)
1791 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1792 TRACE(module, "%04x '%s'\n",
1793 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1795 else
1797 ordinal = LOWORD(name);
1798 TRACE(module, "%04x %04x\n",
1799 hModule, ordinal );
1801 if (!ordinal) return (FARPROC16)0;
1803 ret = MODULE_GetEntryPoint( hModule, ordinal );
1805 TRACE(module, "returning %08x\n", (UINT32)ret );
1806 return ret;
1810 /***********************************************************************
1811 * GetProcAddress32 (KERNEL32.257)
1813 FARPROC32 WINAPI GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1815 NE_MODULE *pModule;
1817 if (HIWORD(function))
1818 TRACE(win32,"(%08lx,%s)\n",(DWORD)hModule,function);
1819 else
1820 TRACE(win32,"(%08lx,%p)\n",(DWORD)hModule,function);
1821 if (!(pModule = MODULE_GetPtr( hModule )))
1822 return (FARPROC32)0;
1823 if (!pModule->module32)
1825 fprintf(stderr,"Oops, Module 0x%08lx has got no module32?\n",
1826 (DWORD)MODULE_HANDLEtoHMODULE32(hModule)
1828 return (FARPROC32)0;
1830 return PE_FindExportedFunction( PROCESS_Current(), pModule->module32,
1831 function );
1834 /***********************************************************************
1835 * RtlImageNtHeaders (NTDLL)
1837 LPIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE32 hModule)
1839 /* basically:
1840 * return hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew);
1841 * but we could get HMODULE16 or the like (think builtin modules)
1844 NE_MODULE *pModule;
1846 if (!(pModule = MODULE_GetPtr( hModule )))
1847 return (LPIMAGE_NT_HEADERS)0;
1848 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->module32)
1849 return (LPIMAGE_NT_HEADERS)0;
1850 return PE_HEADER(pModule->module32);
1854 /**********************************************************************
1855 * GetExpWinVer (KERNEL.167)
1857 WORD WINAPI GetExpWinVer( HMODULE16 hModule )
1859 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1860 return pModule ? pModule->expected_version : 0;
1864 /**********************************************************************
1865 * IsSharedSelector (KERNEL.345)
1867 BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
1869 /* Check whether the selector belongs to a DLL */
1870 NE_MODULE *pModule = MODULE_GetPtr( selector );
1871 if (!pModule) return FALSE;
1872 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1876 /**********************************************************************
1877 * ModuleFirst (TOOLHELP.59)
1879 BOOL16 WINAPI ModuleFirst( MODULEENTRY *lpme )
1881 lpme->wNext = hFirstModule;
1882 return ModuleNext( lpme );
1886 /**********************************************************************
1887 * ModuleNext (TOOLHELP.60)
1889 BOOL16 WINAPI ModuleNext( MODULEENTRY *lpme )
1891 NE_MODULE *pModule;
1892 char *name;
1894 if (!lpme->wNext) return FALSE;
1895 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1896 name = (char *)pModule + pModule->name_table;
1897 memcpy( lpme->szModule, name + 1, *name );
1898 lpme->szModule[(BYTE)*name] = '\0';
1899 lpme->hModule = lpme->wNext;
1900 lpme->wcUsage = pModule->count;
1901 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1902 lpme->szExePath[MAX_PATH] = '\0';
1903 lpme->wNext = pModule->next;
1904 return TRUE;
1908 /**********************************************************************
1909 * ModuleFindName (TOOLHELP.61)
1911 BOOL16 WINAPI ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1913 lpme->wNext = GetModuleHandle16( name );
1914 return ModuleNext( lpme );
1918 /**********************************************************************
1919 * ModuleFindHandle (TOOLHELP.62)
1921 BOOL16 WINAPI ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1923 hModule = MODULE_HANDLEtoHMODULE16( hModule );
1924 lpme->wNext = hModule;
1925 return ModuleNext( lpme );