Release 971221
[wine/multimedia.git] / loader / module.c
blobcebaea00dae78ad962a080bcfd338797cc530eec
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 "hook.h"
20 #include "module.h"
21 #include "neexe.h"
22 #include "resource.h"
23 #include "selectors.h"
24 #include "stackframe.h"
25 #include "task.h"
26 #include "toolhelp.h"
27 #include "stddebug.h"
28 #include "debug.h"
29 #include "callback.h"
31 extern HINSTANCE16 PE_LoadModule( HFILE32 hf, OFSTRUCT *ofs, LOADPARAMS* params );
33 static HMODULE16 hFirstModule = 0;
34 static HMODULE16 hCachedModule = 0; /* Module cached by MODULE_OpenFile */
37 /***********************************************************************
38 * MODULE_GetPtr
40 NE_MODULE *MODULE_GetPtr( HMODULE32 hModule )
42 HMODULE16 hnd =MODULE_HANDLEtoHMODULE16(hModule);
44 if (!hnd)
45 return NULL;
46 return (NE_MODULE*)GlobalLock16(hnd);
49 /***********************************************************************
50 * MODULE_HANDLEtoHMODULE16
52 HMODULE16
53 MODULE_HANDLEtoHMODULE16(HANDLE32 handle) {
54 NE_MODULE *pModule;
56 if (HIWORD(handle))
58 /* this is a HMODULE32 */
60 /* walk the list looking for the correct startaddress */
61 pModule = (NE_MODULE *)GlobalLock16( hFirstModule );
62 while (pModule)
64 if (pModule->module32 == handle) return pModule->self;
65 pModule = (NE_MODULE*)GlobalLock16(pModule->next);
67 return 0;
69 return GetExePtr(handle);
72 /***********************************************************************
73 * MODULE_HANDLEtoHMODULE32
74 * return HMODULE32, if possible, HMODULE16 otherwise
76 HMODULE32
77 MODULE_HANDLEtoHMODULE32(HANDLE32 handle) {
78 NE_MODULE *pModule;
80 if (HIWORD(handle))
81 return (HMODULE32)handle;
82 else {
83 handle = GetExePtr(handle);
84 if (!handle)
85 return 0;
86 pModule = (NE_MODULE *)GlobalLock16( handle );
87 if (!pModule)
88 return 0;
90 if (pModule->module32) return pModule->module32;
91 return handle;
95 /***********************************************************************
96 * MODULE_DumpModule
98 void MODULE_DumpModule( HMODULE32 hModule )
100 int i, ordinal;
101 SEGTABLEENTRY *pSeg;
102 BYTE *pstr;
103 WORD *pword;
104 NE_MODULE *pModule;
106 if (!(pModule = MODULE_GetPtr( hModule )))
108 fprintf( stderr, "**** %04x is not a module handle\n", hModule );
109 return;
112 /* Dump the module info */
114 printf( "Module %04x:\n", hModule );
115 printf( "count=%d flags=%04x heap=%d stack=%d\n",
116 pModule->count, pModule->flags,
117 pModule->heap_size, pModule->stack_size );
118 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
119 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
120 pModule->seg_count, pModule->modref_count );
121 printf( "os_flags=%d swap_area=%d version=%04x\n",
122 pModule->os_flags, pModule->min_swap_area,
123 pModule->expected_version );
124 if (pModule->flags & NE_FFLAGS_WIN32)
125 printf( "PE module=%08x\n", pModule->module32 );
127 /* Dump the file info */
129 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
131 /* Dump the segment table */
133 printf( "\nSegment table:\n" );
134 pSeg = NE_SEG_TABLE( pModule );
135 for (i = 0; i < pModule->seg_count; i++, pSeg++)
136 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
137 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
138 pSeg->minsize, pSeg->selector );
140 /* Dump the resource table */
142 printf( "\nResource table:\n" );
143 if (pModule->res_table)
145 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
146 printf( "Alignment: %d\n", *pword++ );
147 while (*pword)
149 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
150 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
151 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
152 for (i = 0; i < ptr->count; i++, pname++)
153 printf( "offset=%d len=%d id=%04x\n",
154 pname->offset, pname->length, pname->id );
155 pword = (WORD *)pname;
158 else printf( "None\n" );
160 /* Dump the resident name table */
162 printf( "\nResident-name table:\n" );
163 pstr = (char *)pModule + pModule->name_table;
164 while (*pstr)
166 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
167 *(WORD *)(pstr + *pstr + 1) );
168 pstr += *pstr + 1 + sizeof(WORD);
171 /* Dump the module reference table */
173 printf( "\nModule ref table:\n" );
174 if (pModule->modref_table)
176 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
177 for (i = 0; i < pModule->modref_count; i++, pword++)
179 printf( "%d: %04x -> '%s'\n", i, *pword,
180 MODULE_GetModuleName(*pword));
183 else printf( "None\n" );
185 /* Dump the entry table */
187 printf( "\nEntry table:\n" );
188 pstr = (char *)pModule + pModule->entry_table;
189 ordinal = 1;
190 while (*pstr)
192 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
193 if (!pstr[1])
195 ordinal += *pstr;
196 pstr += 2;
198 else if ((BYTE)pstr[1] == 0xff) /* moveable */
200 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
201 for (i = 0; i < *pstr; i++, pe++)
202 printf( "%d: %02x:%04x (moveable)\n",
203 ordinal++, pe->seg_number, pe->offset );
204 pstr = (char *)pe;
206 else /* fixed */
208 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
209 for (i = 0; i < *pstr; i++, pe++)
210 printf( "%d: %04x (fixed)\n",
211 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
212 pstr = (char *)pe;
216 /* Dump the non-resident names table */
218 printf( "\nNon-resident names table:\n" );
219 if (pModule->nrname_handle)
221 pstr = (char *)GlobalLock16( pModule->nrname_handle );
222 while (*pstr)
224 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
225 *(WORD *)(pstr + *pstr + 1) );
226 pstr += *pstr + 1 + sizeof(WORD);
229 printf( "\n" );
233 /***********************************************************************
234 * MODULE_WalkModules
236 * Walk the module list and print the modules.
238 void MODULE_WalkModules(void)
240 HMODULE16 hModule = hFirstModule;
241 fprintf( stderr, "Module Flags Name\n" );
242 while (hModule)
244 NE_MODULE *pModule = MODULE_GetPtr( hModule );
245 if (!pModule)
247 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
248 return;
250 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
251 *((char *)pModule + pModule->name_table),
252 (char *)pModule + pModule->name_table + 1 );
253 hModule = pModule->next;
258 /***********************************************************************
259 * MODULE_OpenFile
261 int MODULE_OpenFile( HMODULE32 hModule )
263 NE_MODULE *pModule;
264 DOS_FULL_NAME full_name;
265 char *name;
267 static int cachedfd = -1;
269 hModule = MODULE_HANDLEtoHMODULE16(hModule);
270 dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
271 hModule, hCachedModule, cachedfd );
272 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
273 if (hCachedModule == hModule) return cachedfd;
274 close( cachedfd );
275 hCachedModule = hModule;
276 name = NE_MODULE_NAME( pModule );
277 if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
278 (cachedfd = open( full_name.long_name, O_RDONLY )) == -1)
279 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
280 name, hModule );
281 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
282 name, cachedfd );
283 return cachedfd;
287 /***********************************************************************
288 * MODULE_Ne2MemFlags
290 * This function translates NE segment flags to GlobalAlloc flags
292 static WORD MODULE_Ne2MemFlags(WORD flags)
294 WORD memflags = 0;
295 #if 0
296 if (flags & NE_SEGFLAGS_DISCARDABLE)
297 memflags |= GMEM_DISCARDABLE;
298 if (flags & NE_SEGFLAGS_MOVEABLE ||
299 ( ! (flags & NE_SEGFLAGS_DATA) &&
300 ! (flags & NE_SEGFLAGS_LOADED) &&
301 ! (flags & NE_SEGFLAGS_ALLOCATED)
304 memflags |= GMEM_MOVEABLE;
305 memflags |= GMEM_ZEROINIT;
306 #else
307 memflags = GMEM_ZEROINIT | GMEM_FIXED;
308 return memflags;
309 #endif
312 /***********************************************************************
313 * MODULE_AllocateSegment (WPROCS.26)
316 DWORD WINAPI MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
318 WORD size = wSize << wElem;
319 HANDLE16 hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
320 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
323 /***********************************************************************
324 * MODULE_CreateSegments
326 static BOOL32 MODULE_CreateSegments( HMODULE32 hModule )
328 SEGTABLEENTRY *pSegment;
329 NE_MODULE *pModule;
330 int i, minsize;
332 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
333 pSegment = NE_SEG_TABLE( pModule );
334 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
336 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
337 if (i == pModule->ss) minsize += pModule->stack_size;
338 /* The DGROUP is allocated by MODULE_CreateInstance */
339 if (i == pModule->dgroup) continue;
340 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
341 minsize, hModule,
342 !(pSegment->flags & NE_SEGFLAGS_DATA),
343 FALSE,
344 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
345 if (!pSegment->selector) return FALSE;
348 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
349 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
350 return TRUE;
354 /***********************************************************************
355 * MODULE_GetInstance
357 HINSTANCE16 MODULE_GetInstance( HMODULE32 hModule )
359 SEGTABLEENTRY *pSegment;
360 NE_MODULE *pModule;
362 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
363 if (pModule->dgroup == 0) return hModule;
365 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
367 return pSegment->selector;
371 /***********************************************************************
372 * MODULE_CreateInstance
374 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
376 SEGTABLEENTRY *pSegment;
377 NE_MODULE *pModule;
378 int minsize;
379 HINSTANCE16 hNewInstance, hPrevInstance;
381 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
382 if (pModule->dgroup == 0) return hModule;
384 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
385 hPrevInstance = pSegment->selector;
387 /* if it's a library, create a new instance only the first time */
388 if (hPrevInstance)
390 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
391 if (params == (LOADPARAMS*)-1) return hPrevInstance;
394 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
395 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
396 minsize += pModule->heap_size;
397 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
398 minsize, hModule, FALSE, FALSE, FALSE );
399 if (!hNewInstance) return 0;
400 pSegment->selector = hNewInstance;
401 return hNewInstance;
405 /***********************************************************************
406 * MODULE_CreateDummyModule
408 * Create a dummy NE module for Win32 or Winelib.
410 HMODULE32 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
412 HMODULE32 hModule;
413 NE_MODULE *pModule;
414 SEGTABLEENTRY *pSegment;
415 char *pStr,*s;
416 int len;
417 const char* basename;
419 INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
420 + strlen(ofs->szPathName) + 1;
421 INT32 size = sizeof(NE_MODULE) +
422 /* loaded file info */
423 of_size +
424 /* segment table: DS,CS */
425 2 * sizeof(SEGTABLEENTRY) +
426 /* name table */
428 /* several empty tables */
431 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
432 if (!hModule) return (HMODULE32)11; /* invalid exe */
434 FarSetOwner( hModule, hModule );
435 pModule = (NE_MODULE *)GlobalLock16( hModule );
437 /* Set all used entries */
438 pModule->magic = IMAGE_OS2_SIGNATURE;
439 pModule->count = 1;
440 pModule->next = 0;
441 pModule->flags = 0;
442 pModule->dgroup = 1;
443 pModule->ss = 1;
444 pModule->cs = 2;
445 pModule->heap_size = 0xe000;
446 pModule->stack_size = 0x1000;
447 pModule->seg_count = 2;
448 pModule->modref_count = 0;
449 pModule->nrname_size = 0;
450 pModule->fileinfo = sizeof(NE_MODULE);
451 pModule->os_flags = NE_OSFLAGS_WINDOWS;
452 pModule->expected_version = 0x030a;
453 pModule->self = hModule;
455 /* Set loaded file information */
456 memcpy( pModule + 1, ofs, of_size );
457 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
459 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
460 pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
461 /* Data segment */
462 pSegment->size = 0;
463 pSegment->flags = NE_SEGFLAGS_DATA;
464 pSegment->minsize = 0x1000;
465 pSegment++;
466 /* Code segment */
467 pSegment->flags = 0;
468 pSegment++;
470 /* Module name */
471 pStr = (char *)pSegment;
472 pModule->name_table = (int)pStr - (int)pModule;
473 basename = strrchr(ofs->szPathName,'\\');
474 if (!basename) basename = ofs->szPathName;
475 else basename++;
476 len = strlen(basename);
477 if ((s = strchr(basename,'.'))) len = s - basename;
478 if (len > 8) len = 8;
479 *pStr = len;
480 strncpy( pStr+1, basename, len );
481 if (len < 8) pStr[len+1] = 0;
482 pStr += 9;
484 /* All tables zero terminated */
485 pModule->res_table = pModule->import_table = pModule->entry_table =
486 (int)pStr - (int)pModule;
488 MODULE_RegisterModule( pModule );
489 return hModule;
493 /***********************************************************************
494 * MODULE_LoadExeHeader
496 static HMODULE32 MODULE_LoadExeHeader( HFILE32 hFile, OFSTRUCT *ofs )
498 IMAGE_DOS_HEADER mz_header;
499 IMAGE_OS2_HEADER ne_header;
500 int size;
501 HMODULE32 hModule;
502 NE_MODULE *pModule;
503 BYTE *pData;
504 char *buffer, *fastload = NULL;
505 int fastload_offset = 0, fastload_length = 0;
507 /* Read a block from either the file or the fast-load area. */
508 #define READ(offset,size,buffer) \
509 ((fastload && ((offset) >= fastload_offset) && \
510 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
511 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
512 (_llseek32( hFile, (offset), SEEK_SET), \
513 _lread32( hFile, (buffer), (size) ) == (size)))
515 _llseek32( hFile, 0, SEEK_SET );
516 if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
517 (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
518 return (HMODULE32)11; /* invalid exe */
520 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
521 if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
522 return (HMODULE32)11; /* invalid exe */
524 if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE32)21; /* win32 exe */
525 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE32)11; /* invalid exe */
527 if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
528 fprintf(stderr, "Sorry, this is an OS/2 linear executable (LX) file !\n");
529 return (HMODULE32)12;
531 /* We now have a valid NE header */
533 size = sizeof(NE_MODULE) +
534 /* loaded file info */
535 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
536 /* segment table */
537 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
538 /* resource table */
539 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
540 /* resident names table */
541 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
542 /* module ref table */
543 ne_header.n_mod_ref_tab * sizeof(WORD) +
544 /* imported names table */
545 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
546 /* entry table length */
547 ne_header.entry_tab_length;
549 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
550 if (!hModule) return (HMODULE32)11; /* invalid exe */
551 FarSetOwner( hModule, hModule );
552 pModule = (NE_MODULE *)GlobalLock16( hModule );
553 memcpy( pModule, &ne_header, sizeof(ne_header) );
554 pModule->count = 0;
555 pModule->module32 = 0;
556 pModule->self = hModule;
557 pModule->self_loading_sel = 0;
558 pData = (BYTE *)(pModule + 1);
560 /* Clear internal Wine flags in case they are set in the EXE file */
562 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
564 /* Read the fast-load area */
566 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
568 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
569 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
570 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
571 fastload_offset, fastload_length );
572 if ((fastload = HeapAlloc( SystemHeap, 0, fastload_length )) != NULL)
574 _llseek32( hFile, fastload_offset, SEEK_SET);
575 if (_lread32(hFile, fastload, fastload_length) != fastload_length)
577 HeapFree( SystemHeap, 0, fastload );
578 fprintf(stderr, "Error reading fast-load area !\n");
579 fastload = NULL;
584 /* Store the filename information */
586 pModule->fileinfo = (int)pData - (int)pModule;
587 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
588 memcpy( pData, ofs, size );
589 ((OFSTRUCT *)pData)->cBytes = size - 1;
590 pData += size;
592 /* Get the segment table */
594 pModule->seg_table = (int)pData - (int)pModule;
595 buffer = HeapAlloc( SystemHeap, 0, ne_header.n_segment_tab *
596 sizeof(struct ne_segment_table_entry_s));
597 if (buffer)
599 int i;
600 struct ne_segment_table_entry_s *pSeg;
602 if (!READ( mz_header.e_lfanew + ne_header.segment_tab_offset,
603 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
604 buffer ))
606 HeapFree( SystemHeap, 0, buffer );
607 if (fastload) HeapFree( SystemHeap, 0, fastload );
608 GlobalFree16( hModule );
609 return (HMODULE32)11; /* invalid exe */
611 pSeg = (struct ne_segment_table_entry_s *)buffer;
612 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
614 memcpy( pData, pSeg, sizeof(*pSeg) );
615 pData += sizeof(SEGTABLEENTRY);
617 HeapFree( SystemHeap, 0, buffer );
619 else
621 if (fastload) HeapFree( SystemHeap, 0, fastload );
622 GlobalFree16( hModule );
623 return (HMODULE32)11; /* invalid exe */
626 /* Get the resource table */
628 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
630 pModule->res_table = (int)pData - (int)pModule;
631 if (!READ(mz_header.e_lfanew + ne_header.resource_tab_offset,
632 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
633 pData )) return (HMODULE32)11; /* invalid exe */
634 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
635 NE_InitResourceHandler( hModule );
637 else pModule->res_table = 0; /* No resource table */
639 /* Get the resident names table */
641 pModule->name_table = (int)pData - (int)pModule;
642 if (!READ( mz_header.e_lfanew + ne_header.rname_tab_offset,
643 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
644 pData ))
646 if (fastload) HeapFree( SystemHeap, 0, fastload );
647 GlobalFree16( hModule );
648 return (HMODULE32)11; /* invalid exe */
650 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
652 /* Get the module references table */
654 if (ne_header.n_mod_ref_tab > 0)
656 pModule->modref_table = (int)pData - (int)pModule;
657 if (!READ( mz_header.e_lfanew + ne_header.moduleref_tab_offset,
658 ne_header.n_mod_ref_tab * sizeof(WORD),
659 pData ))
661 if (fastload) HeapFree( SystemHeap, 0, fastload );
662 GlobalFree16( hModule );
663 return (HMODULE32)11; /* invalid exe */
665 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
667 else pModule->modref_table = 0; /* No module references */
669 /* Get the imported names table */
671 pModule->import_table = (int)pData - (int)pModule;
672 if (!READ( mz_header.e_lfanew + ne_header.iname_tab_offset,
673 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
674 pData ))
676 if (fastload) HeapFree( SystemHeap, 0, fastload );
677 GlobalFree16( hModule );
678 return (HMODULE32)11; /* invalid exe */
680 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
682 /* Get the entry table */
684 pModule->entry_table = (int)pData - (int)pModule;
685 if (!READ( mz_header.e_lfanew + ne_header.entry_tab_offset,
686 ne_header.entry_tab_length,
687 pData ))
689 if (fastload) HeapFree( SystemHeap, 0, fastload );
690 GlobalFree16( hModule );
691 return (HMODULE32)11; /* invalid exe */
693 pData += ne_header.entry_tab_length;
695 /* Free the fast-load area */
697 #undef READ
698 if (fastload) HeapFree( SystemHeap, 0, fastload );
700 /* Get the non-resident names table */
702 if (ne_header.nrname_tab_length)
704 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
705 hModule, FALSE, FALSE, FALSE );
706 if (!pModule->nrname_handle)
708 GlobalFree16( hModule );
709 return (HMODULE32)11; /* invalid exe */
711 buffer = GlobalLock16( pModule->nrname_handle );
712 _llseek32( hFile, ne_header.nrname_tab_offset, SEEK_SET );
713 if (_lread32( hFile, buffer, ne_header.nrname_tab_length )
714 != ne_header.nrname_tab_length)
716 GlobalFree16( pModule->nrname_handle );
717 GlobalFree16( hModule );
718 return (HMODULE32)11; /* invalid exe */
721 else pModule->nrname_handle = 0;
723 /* Allocate a segment for the implicitly-loaded DLLs */
725 if (pModule->modref_count)
727 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
728 (pModule->modref_count+1)*sizeof(HMODULE32),
729 hModule, FALSE, FALSE, FALSE );
730 if (!pModule->dlls_to_init)
732 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
733 GlobalFree16( hModule );
734 return (HMODULE32)11; /* invalid exe */
737 else pModule->dlls_to_init = 0;
739 MODULE_RegisterModule( pModule );
740 return hModule;
744 /***********************************************************************
745 * MODULE_GetOrdinal
747 * Lookup the ordinal for a given name.
749 WORD MODULE_GetOrdinal( HMODULE32 hModule, const char *name )
751 unsigned char buffer[256], *cpnt;
752 BYTE len;
753 NE_MODULE *pModule;
755 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
757 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
758 hModule, name );
760 /* First handle names of the form '#xxxx' */
762 if (name[0] == '#') return atoi( name + 1 );
764 /* Now copy and uppercase the string */
766 strcpy( buffer, name );
767 CharUpper32A( buffer );
768 len = strlen( buffer );
770 /* First search the resident names */
772 cpnt = (char *)pModule + pModule->name_table;
774 /* Skip the first entry (module name) */
775 cpnt += *cpnt + 1 + sizeof(WORD);
776 while (*cpnt)
778 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
780 dprintf_module( stddeb, " Found: ordinal=%d\n",
781 *(WORD *)(cpnt + *cpnt + 1) );
782 return *(WORD *)(cpnt + *cpnt + 1);
784 cpnt += *cpnt + 1 + sizeof(WORD);
787 /* Now search the non-resident names table */
789 if (!pModule->nrname_handle) return 0; /* No non-resident table */
790 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
792 /* Skip the first entry (module description string) */
793 cpnt += *cpnt + 1 + sizeof(WORD);
794 while (*cpnt)
796 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
798 dprintf_module( stddeb, " Found: ordinal=%d\n",
799 *(WORD *)(cpnt + *cpnt + 1) );
800 return *(WORD *)(cpnt + *cpnt + 1);
802 cpnt += *cpnt + 1 + sizeof(WORD);
804 return 0;
808 /***********************************************************************
809 * MODULE_GetEntryPoint
811 * Return the entry point for a given ordinal.
813 FARPROC16 MODULE_GetEntryPoint( HMODULE32 hModule, WORD ordinal )
815 NE_MODULE *pModule;
816 WORD curOrdinal = 1;
817 BYTE *p;
818 WORD sel, offset;
820 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
822 p = (BYTE *)pModule + pModule->entry_table;
823 while (*p && (curOrdinal + *p <= ordinal))
825 /* Skipping this bundle */
826 curOrdinal += *p;
827 switch(p[1])
829 case 0: p += 2; break; /* unused */
830 case 0xff: p += 2 + *p * 6; break; /* moveable */
831 default: p += 2 + *p * 3; break; /* fixed */
834 if (!*p) return 0;
836 switch(p[1])
838 case 0: /* unused */
839 return 0;
840 case 0xff: /* moveable */
841 p += 2 + 6 * (ordinal - curOrdinal);
842 sel = p[3];
843 offset = *(WORD *)(p + 4);
844 break;
845 default: /* fixed */
846 sel = p[1];
847 p += 2 + 3 * (ordinal - curOrdinal);
848 offset = *(WORD *)(p + 1);
849 break;
852 if (sel == 0xfe) sel = 0xffff; /* constant entry */
853 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
854 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
858 /***********************************************************************
859 * EntryAddrProc (WPROCS.27)
861 FARPROC16 WINAPI EntryAddrProc( HMODULE16 hModule, WORD ordinal )
863 return MODULE_GetEntryPoint( hModule, ordinal );
867 /***********************************************************************
868 * MODULE_SetEntryPoint
870 * Change the value of an entry point. Use with caution!
871 * It can only change the offset value, not the selector.
873 BOOL16 MODULE_SetEntryPoint( HMODULE32 hModule, WORD ordinal, WORD offset )
875 NE_MODULE *pModule;
876 WORD curOrdinal = 1;
877 BYTE *p;
879 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
881 p = (BYTE *)pModule + pModule->entry_table;
882 while (*p && (curOrdinal + *p <= ordinal))
884 /* Skipping this bundle */
885 curOrdinal += *p;
886 switch(p[1])
888 case 0: p += 2; break; /* unused */
889 case 0xff: p += 2 + *p * 6; break; /* moveable */
890 default: p += 2 + *p * 3; break; /* fixed */
893 if (!*p) return FALSE;
895 switch(p[1])
897 case 0: /* unused */
898 return FALSE;
899 case 0xff: /* moveable */
900 p += 2 + 6 * (ordinal - curOrdinal);
901 *(WORD *)(p + 4) = offset;
902 break;
903 default: /* fixed */
904 p += 2 + 3 * (ordinal - curOrdinal);
905 *(WORD *)(p + 1) = offset;
906 break;
908 return TRUE;
912 /***********************************************************************
913 * MODULE_GetWndProcEntry16 (not a Windows API function)
915 * Return an entry point from the WPROCS dll.
917 FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
919 FARPROC16 ret = NULL;
921 if (__winelib)
923 /* FIXME: hack for Winelib */
924 extern LRESULT ColorDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
925 extern LRESULT FileOpenDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
926 extern LRESULT FileSaveDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
927 extern LRESULT FindTextDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
928 extern LRESULT PrintDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
929 extern LRESULT PrintSetupDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
930 extern LRESULT ReplaceTextDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
932 if (!strcmp(name,"ColorDlgProc"))
933 return (FARPROC16)ColorDlgProc;
934 if (!strcmp(name,"FileOpenDlgProc"))
935 return (FARPROC16)FileOpenDlgProc;
936 if (!strcmp(name,"FileSaveDlgProc"))
937 return (FARPROC16)FileSaveDlgProc;
938 if (!strcmp(name,"FindTextDlgProc"))
939 return (FARPROC16)FindTextDlgProc;
940 if (!strcmp(name,"PrintDlgProc"))
941 return (FARPROC16)PrintDlgProc;
942 if (!strcmp(name,"PrintSetupDlgProc"))
943 return (FARPROC16)PrintSetupDlgProc;
944 if (!strcmp(name,"ReplaceTextDlgProc"))
945 return (FARPROC16)ReplaceTextDlgProc;
946 fprintf(stderr,"warning: No mapping for %s(), add one in library/miscstubs.c\n",name);
947 assert( FALSE );
948 return NULL;
950 else
952 WORD ordinal;
953 static HMODULE32 hModule = 0;
955 if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
956 ordinal = MODULE_GetOrdinal( hModule, name );
957 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
959 fprintf( stderr, "GetWndProc16: %s not found\n", name );
960 assert( FALSE );
963 return ret;
967 /***********************************************************************
968 * MODULE_GetModuleName
970 LPSTR MODULE_GetModuleName( HMODULE32 hModule )
972 NE_MODULE *pModule;
973 BYTE *p, len;
974 static char buffer[10];
976 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
977 p = (BYTE *)pModule + pModule->name_table;
978 len = MIN( *p, 8 );
979 memcpy( buffer, p + 1, len );
980 buffer[len] = '\0';
981 return buffer;
985 /**********************************************************************
986 * MODULE_RegisterModule
988 void MODULE_RegisterModule( NE_MODULE *pModule )
990 pModule->next = hFirstModule;
991 hFirstModule = pModule->self;
995 /**********************************************************************
996 * MODULE_FindModule
998 * Find a module from a path name.
1000 HMODULE32 MODULE_FindModule( LPCSTR path )
1002 HMODULE32 hModule = hFirstModule;
1003 LPCSTR filename, dotptr, modulepath, modulename;
1004 BYTE len, *name_table;
1006 if (!(filename = strrchr( path, '\\' ))) filename = path;
1007 else filename++;
1008 if ((dotptr = strrchr( filename, '.' )) != NULL)
1009 len = (BYTE)(dotptr - filename);
1010 else len = strlen( filename );
1012 while(hModule)
1014 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1015 if (!pModule) break;
1016 modulepath = NE_MODULE_NAME(pModule);
1017 if (!(modulename = strrchr( modulepath, '\\' )))
1018 modulename = modulepath;
1019 else modulename++;
1020 if (!lstrcmpi32A( modulename, filename )) return hModule;
1022 name_table = (BYTE *)pModule + pModule->name_table;
1023 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
1024 return hModule;
1025 hModule = pModule->next;
1027 return 0;
1031 /**********************************************************************
1032 * MODULE_CallWEP
1034 * Call a DLL's WEP, allowing it to shut down.
1035 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
1037 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
1039 FARPROC16 WEP = (FARPROC16)0;
1040 WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
1042 if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
1043 if (!WEP)
1045 dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
1046 return FALSE;
1048 return Callbacks->CallWindowsExitProc( WEP, WEP_FREE_DLL );
1052 /**********************************************************************
1053 * MODULE_FreeModule
1055 * Remove a module from memory.
1057 BOOL16 MODULE_FreeModule( HMODULE32 hModule, TDB* pTaskContext )
1059 HMODULE16 *hPrevModule;
1060 NE_MODULE *pModule;
1061 SEGTABLEENTRY *pSegment;
1062 HMODULE16 *pModRef;
1063 int i;
1065 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1066 hModule = pModule->self;
1068 if (((INT16)(--pModule->count)) > 0 ) return TRUE;
1069 else pModule->count = 0;
1071 if (pModule->flags & NE_FFLAGS_BUILTIN)
1072 return FALSE; /* Can't free built-in module */
1074 if (pModule->flags & NE_FFLAGS_LIBMODULE)
1076 MODULE_CallWEP( hModule );
1078 /* Free the objects owned by the DLL module */
1080 if( pTaskContext && pTaskContext->userhandler )
1082 pTaskContext->userhandler( hModule, USIG_DLL_UNLOAD, 0,
1083 pTaskContext->hInstance,
1084 pTaskContext->hQueue );
1087 /* Clear magic number just in case */
1089 pModule->magic = pModule->self = 0;
1091 /* Remove it from the linked list */
1093 hPrevModule = &hFirstModule;
1094 while (*hPrevModule && (*hPrevModule != hModule))
1096 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
1098 if (*hPrevModule) *hPrevModule = pModule->next;
1100 /* Free all the segments */
1102 pSegment = NE_SEG_TABLE( pModule );
1103 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
1105 GlobalFree16( pSegment->selector );
1108 /* Free the referenced modules */
1110 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
1111 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1113 FreeModule16( *pModRef );
1116 /* Free the module storage */
1118 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
1119 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
1120 GlobalFree16( hModule );
1122 /* Remove module from cache */
1124 if (hCachedModule == hModule) hCachedModule = 0;
1126 return TRUE;
1130 /**********************************************************************
1131 * MODULE_Load
1133 * Implementation of LoadModule()
1135 HINSTANCE16 MODULE_Load( LPCSTR name, LPVOID paramBlock, UINT16 uFlags)
1137 HMODULE32 hModule;
1138 HINSTANCE16 hInstance, hPrevInstance;
1139 NE_MODULE *pModule;
1140 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1141 OFSTRUCT ofs;
1142 HFILE32 hFile;
1144 if (__winelib)
1146 lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1147 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1148 pModule = (NE_MODULE *)GlobalLock16( hModule );
1149 hPrevInstance = 0;
1150 hInstance = MODULE_CreateInstance( hModule, params );
1152 else
1154 hModule = MODULE_FindModule( name );
1156 if (!hModule) /* We have to load the module */
1158 /* Try to load the built-in first if not disabled */
1159 if ((hModule = BUILTIN_LoadModule( name, FALSE )))
1160 return MODULE_HANDLEtoHMODULE16( hModule );
1162 if ((hFile = OpenFile32( name, &ofs, OF_READ )) == HFILE_ERROR32)
1164 /* Now try the built-in even if disabled */
1165 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
1167 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1168 return MODULE_HANDLEtoHMODULE16( hModule );
1170 return 2; /* File not found */
1173 /* Create the module structure */
1175 hModule = MODULE_LoadExeHeader( hFile, &ofs );
1176 if (hModule < 32)
1178 if (hModule == 21)
1179 hModule = PE_LoadModule( hFile, &ofs, paramBlock );
1180 else _lclose32( hFile );
1182 if (hModule < 32)
1183 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1184 name, hModule );
1185 return hModule;
1187 _lclose32( hFile );
1188 pModule = MODULE_GetPtr( hModule );
1189 pModule->flags |= uFlags; /* stamp implicitly loaded modules */
1191 /* Allocate the segments for this module */
1193 MODULE_CreateSegments( hModule );
1194 hPrevInstance = 0;
1195 hInstance = MODULE_CreateInstance(hModule,(LOADPARAMS*)paramBlock);
1197 /* Load the referenced DLLs */
1199 if (!NE_LoadDLLs( pModule )) return 2; /* File not found */
1201 /* Load the segments */
1203 NE_LoadAllSegments( pModule );
1205 /* Fixup the functions prologs */
1207 NE_FixupPrologs( pModule );
1209 /* Make sure the usage count is 1 on the first loading of */
1210 /* the module, even if it contains circular DLL references */
1212 pModule->count = 1;
1214 /* Call initialization rountines for all loaded DLLs. Note that
1215 * when we load implicitly linked DLLs this will be done by InitTask().
1218 if ((pModule->flags & (NE_FFLAGS_LIBMODULE | NE_FFLAGS_IMPLICIT)) ==
1219 NE_FFLAGS_LIBMODULE )
1220 NE_InitializeDLLs( hModule );
1222 else /* module is already loaded, just create a new data segment if it's a task */
1224 pModule = MODULE_GetPtr( hModule );
1225 hPrevInstance = MODULE_GetInstance( hModule );
1226 hInstance = MODULE_CreateInstance( hModule, params );
1227 if (hInstance != hPrevInstance) /* not a library */
1228 NE_LoadSegment( pModule, pModule->dgroup );
1229 pModule->count++;
1231 } /* !winelib */
1233 /* Create a task for this instance */
1235 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1237 HTASK16 hTask;
1238 WORD showcmd;
1240 pModule->flags |= NE_FFLAGS_GUI;
1242 /* PowerPoint passes NULL as showCmd */
1243 if (params->showCmd)
1244 showcmd = *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1);
1245 else
1246 showcmd = 0; /* FIXME: correct */
1248 hTask = TASK_CreateTask( hModule, hInstance, hPrevInstance,
1249 params->hEnvironment,
1250 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1251 showcmd );
1253 if( hTask && TASK_GetNextTask(hTask)) Yield16();
1256 return hInstance;
1260 /**********************************************************************
1261 * LoadModule16 (KERNEL.45)
1263 HINSTANCE16 LoadModule16( LPCSTR name, LPVOID paramBlock )
1265 return MODULE_Load( name, paramBlock, 0 );
1268 /**********************************************************************
1269 * LoadModule32 (KERNEL32)
1270 * FIXME: check this function
1272 DWORD LoadModule32( LPCSTR name, LPVOID paramBlock )
1274 return MODULE_Load( name, paramBlock, 0 );
1278 /**********************************************************************
1279 * FreeModule16 (KERNEL.46)
1281 BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
1283 NE_MODULE *pModule;
1285 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1286 dprintf_module( stddeb, "FreeModule16: %s count %d\n",
1287 MODULE_GetModuleName(hModule), pModule->count );
1289 return MODULE_FreeModule( hModule, GlobalLock16(GetCurrentTask()) );
1293 /**********************************************************************
1294 * GetModuleHandle16 (KERNEL.47)
1296 HMODULE16 WINAPI WIN16_GetModuleHandle( SEGPTR name )
1298 if (HIWORD(name) == 0) return MODULE_HANDLEtoHMODULE16( (HINSTANCE16)name );
1299 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1302 HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
1304 return MODULE_FindModule( name );
1307 /***********************************************************************
1308 * GetModuleHandle (KERNEL32.237)
1310 HMODULE32 WINAPI GetModuleHandle32A(LPCSTR module)
1312 HMODULE32 hModule;
1314 dprintf_win32(stddeb, "GetModuleHandleA: %s\n", module ? module : "NULL");
1315 /* Freecell uses the result of GetModuleHandleA(0) as the hInstance in
1316 all calls to e.g. CreateWindowEx. */
1317 if (module == NULL) {
1318 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1319 hModule = pTask->hInstance;
1320 } else
1321 hModule = MODULE_FindModule(module);
1322 return MODULE_HANDLEtoHMODULE32(hModule);
1325 HMODULE32 WINAPI GetModuleHandle32W(LPCWSTR module)
1327 HMODULE32 hModule;
1328 LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
1329 hModule = GetModuleHandle32A( modulea );
1330 HeapFree( GetProcessHeap(), 0, modulea );
1331 return hModule;
1335 /**********************************************************************
1336 * GetModuleUsage (KERNEL.48)
1338 INT16 WINAPI GetModuleUsage( HINSTANCE16 hModule )
1340 NE_MODULE *pModule;
1342 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1343 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1344 hModule, pModule->count );
1345 return pModule->count;
1349 /**********************************************************************
1350 * GetModuleFileName16 (KERNEL.49)
1352 INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
1353 INT16 nSize )
1355 NE_MODULE *pModule;
1357 if (!hModule) hModule = GetCurrentTask();
1358 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1359 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1360 dprintf_module( stddeb, "GetModuleFileName16: %s\n", lpFileName );
1361 return strlen(lpFileName);
1365 /***********************************************************************
1366 * GetModuleFileName32A (KERNEL32.235)
1368 DWORD WINAPI GetModuleFileName32A( HMODULE32 hModule, LPSTR lpFileName,
1369 DWORD size )
1371 NE_MODULE *pModule;
1373 if (!hModule)
1375 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1376 hModule = pTask->hInstance;
1378 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1379 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
1380 dprintf_module( stddeb, "GetModuleFileName32A: %s\n", lpFileName );
1381 return strlen(lpFileName);
1385 /***********************************************************************
1386 * GetModuleFileName32W (KERNEL32.236)
1388 DWORD WINAPI GetModuleFileName32W( HMODULE32 hModule, LPWSTR lpFileName,
1389 DWORD size )
1391 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1392 DWORD res = GetModuleFileName32A( hModule, fnA, size );
1393 lstrcpynAtoW( lpFileName, fnA, size );
1394 HeapFree( GetProcessHeap(), 0, fnA );
1395 return res;
1399 /**********************************************************************
1400 * GetModuleName (KERNEL.27)
1402 BOOL16 WINAPI GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
1404 LPSTR name = MODULE_GetModuleName(hinst);
1406 if (!name) return FALSE;
1407 lstrcpyn32A( buf, name, nSize );
1408 return TRUE;
1412 /***********************************************************************
1413 * LoadLibraryEx32W (KERNEL.513)
1414 * FIXME
1416 HMODULE32 WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
1417 DWORD flags )
1419 fprintf(stderr,"LoadLibraryEx32W(%s,%d,%08lx)\n",libname,hf,flags);
1420 return LoadLibraryEx32A(libname,hf,flags);
1423 /***********************************************************************
1424 * LoadLibraryEx32A (KERNEL32)
1426 HMODULE32 WINAPI LoadLibraryEx32A(LPCSTR libname,HFILE32 hfile,DWORD flags)
1428 HMODULE32 hmod;
1430 hmod = PE_LoadLibraryEx32A(libname,hfile,flags);
1431 if (hmod <= 32) {
1432 char buffer[256];
1434 strcpy( buffer, libname );
1435 strcat( buffer, ".dll" );
1436 hmod = PE_LoadLibraryEx32A(buffer,hfile,flags);
1438 /* initialize all DLLs, which haven't been initialized yet. */
1439 PE_InitializeDLLs( GetCurrentProcessId(), DLL_PROCESS_ATTACH, NULL);
1440 return hmod;
1443 /***********************************************************************
1444 * LoadLibraryA (KERNEL32)
1446 HMODULE32 WINAPI LoadLibrary32A(LPCSTR libname) {
1447 return LoadLibraryEx32A(libname,0,0);
1450 /***********************************************************************
1451 * LoadLibraryW (KERNEL32)
1453 HMODULE32 WINAPI LoadLibrary32W(LPCWSTR libnameW)
1455 return LoadLibraryEx32W(libnameW,0,0);
1458 /***********************************************************************
1459 * LoadLibraryExW (KERNEL32)
1461 HMODULE32 WINAPI LoadLibraryEx32W(LPCWSTR libnameW,HFILE32 hfile,DWORD flags)
1463 LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
1464 HMODULE32 ret = LoadLibraryEx32A( libnameA , hfile, flags );
1466 HeapFree( GetProcessHeap(), 0, libnameA );
1467 return ret;
1470 /***********************************************************************
1471 * FreeLibrary
1473 BOOL32 WINAPI FreeLibrary32(HINSTANCE32 hLibModule)
1475 fprintf(stderr,"FreeLibrary: empty stub\n");
1476 return TRUE;
1480 /***********************************************************************
1481 * LoadLibrary (KERNEL.95)
1483 HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
1485 HINSTANCE16 handle;
1487 if (__winelib)
1489 fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1490 return 0;
1492 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1494 handle = MODULE_Load( libname, (LPVOID)-1, 0 );
1495 if (handle == (HINSTANCE16)2) /* file not found */
1497 char buffer[256];
1498 lstrcpyn32A( buffer, libname, 252 );
1499 strcat( buffer, ".dll" );
1500 handle = MODULE_Load( buffer, (LPVOID)-1, 0 );
1502 return handle;
1506 /***********************************************************************
1507 * PrivateLoadLibrary (KERNEL32)
1509 * FIXME: rough guesswork, don't know what "Private" means
1511 HINSTANCE32 WINAPI PrivateLoadLibrary(LPCSTR libname)
1513 return (HINSTANCE32)LoadLibrary16(libname);
1517 /***********************************************************************
1518 * FreeLibrary16 (KERNEL.96)
1520 void WINAPI FreeLibrary16( HINSTANCE16 handle )
1522 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1523 FreeModule16( handle );
1527 /***********************************************************************
1528 * PrivateFreeLibrary (KERNEL32)
1530 * FIXME: rough guesswork, don't know what "Private" means
1532 void WINAPI PrivateFreeLibrary(HINSTANCE32 handle)
1534 FreeLibrary16((HINSTANCE16)handle);
1538 /***********************************************************************
1539 * WinExec16 (KERNEL.166)
1541 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
1543 return WinExec32( lpCmdLine, nCmdShow );
1547 /***********************************************************************
1548 * WinExec32 (KERNEL32.566)
1550 HINSTANCE32 WINAPI WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow )
1552 LOADPARAMS params;
1553 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1554 HINSTANCE16 handle = 2;
1555 WORD *cmdShowPtr;
1556 char *p, *cmdline, filename[256];
1557 static int use_load_module = 1;
1558 int spacelimit = 0, exhausted = 0;
1560 if (!lpCmdLine)
1561 return 2; /* File not found */
1562 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1563 return 8; /* Out of memory */
1564 if (!(cmdLineHandle = GlobalAlloc16( 0, 2048 )))
1566 GlobalFree16( cmdShowHandle );
1567 return 8; /* Out of memory */
1570 /* Keep trying to load a file by trying different filenames; e.g.,
1571 for the cmdline "abcd efg hij", try "abcd" with args "efg hij",
1572 then "abcd efg" with arg "hij", and finally "abcd efg hij" with
1573 no args */
1575 while(!exhausted && handle == 2) {
1576 int spacecount = 0;
1578 /* Store nCmdShow */
1580 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1581 cmdShowPtr[0] = 2;
1582 cmdShowPtr[1] = nCmdShow;
1584 /* Build the filename and command-line */
1586 cmdline = (char *)GlobalLock16( cmdLineHandle );
1587 lstrcpyn32A(filename, lpCmdLine,
1588 sizeof(filename) - 4 /* for extension */);
1590 /* Keep grabbing characters until end-of-string, tab, or until the
1591 number of spaces is greater than the spacelimit */
1593 for (p = filename; ; p++) {
1594 if(*p == ' ') {
1595 ++spacecount;
1596 if(spacecount > spacelimit) {
1597 ++spacelimit;
1598 break;
1602 if(*p == '\0' || *p == '\t') {
1603 exhausted = 1;
1604 break;
1608 if (*p)
1609 lstrcpyn32A( cmdline + 1, p + 1, 255 );
1610 else
1611 cmdline[1] = '\0';
1613 cmdline[0] = strlen( cmdline + 1 );
1614 *p = '\0';
1615 /* this is a (hopefully acceptable hack to get the whole
1616 commandline for PROCESS_Create
1617 we put it after the processed one */
1618 lstrcpyn32A(cmdline + (unsigned char)cmdline[0] +2,
1619 lpCmdLine, 2048 - 256);
1621 /* Now load the executable file */
1623 if (use_load_module)
1625 /* Winelib: Use LoadModule() only for the program itself */
1626 if (__winelib) use_load_module = 0;
1627 params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
1628 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1629 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1630 params.reserved = 0;
1631 handle = LoadModule16( filename, &params );
1632 if (handle == 2) /* file not found */
1634 /* Check that the original file name did not have a suffix */
1635 p = strrchr(filename, '.');
1636 /* if there is a '.', check if either \ OR / follow */
1637 if (!p || strchr(p, '/') || strchr(p, '\\'))
1639 p = filename + strlen(filename);
1640 strcpy( p, ".exe" );
1641 handle = LoadModule16( filename, &params );
1642 *p = '\0'; /* Remove extension */
1646 else
1647 handle = 2; /* file not found */
1649 if (handle < 32)
1651 /* Try to start it as a unix program */
1652 if (!fork())
1654 /* Child process */
1655 DOS_FULL_NAME full_name;
1656 const char *unixfilename = NULL;
1657 const char *argv[256], **argptr;
1658 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1659 nCmdShow == SW_SHOWMINNOACTIVE);
1661 /* get unixfilename */
1662 if (strchr(filename, '/') ||
1663 strchr(filename, ':') ||
1664 strchr(filename, '\\'))
1666 if (DOSFS_GetFullName( filename, TRUE, &full_name ))
1667 unixfilename = full_name.long_name;
1669 else unixfilename = filename;
1671 if (unixfilename)
1673 /* build argv */
1674 argptr = argv;
1675 if (iconic) *argptr++ = "-iconic";
1676 *argptr++ = unixfilename;
1677 p = cmdline + 1;
1678 while (1)
1680 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1681 if (!*p) break;
1682 *argptr++ = p;
1683 while (*p && *p != ' ' && *p != '\t') p++;
1685 *argptr++ = 0;
1687 /* Execute */
1688 execvp(argv[0], (char**)argv);
1691 /* Failed ! */
1693 if (__winelib)
1695 /* build argv */
1696 argptr = argv;
1697 *argptr++ = "wine";
1698 if (iconic) *argptr++ = "-iconic";
1699 *argptr++ = lpCmdLine;
1700 *argptr++ = 0;
1702 /* Execute */
1703 execvp(argv[0] , (char**)argv);
1705 /* Failed ! */
1706 fprintf(stderr, "WinExec: can't exec 'wine %s'\n",
1707 lpCmdLine);
1709 exit(1);
1712 } /* while (!exhausted && handle < 32) */
1714 GlobalFree16( cmdShowHandle );
1715 GlobalFree16( cmdLineHandle );
1716 return handle;
1720 /***********************************************************************
1721 * WIN32_GetProcAddress16 (KERNEL32.36)
1722 * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1724 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE32 hModule, LPSTR name )
1726 WORD ordinal;
1727 FARPROC16 ret;
1729 if (!hModule) {
1730 fprintf(stderr,"WIN32_GetProcAddress16: hModule may not be 0!\n");
1731 return (FARPROC16)0;
1733 hModule = MODULE_HANDLEtoHMODULE16(hModule);
1734 if (HIWORD(name)) {
1735 ordinal = MODULE_GetOrdinal( hModule, name );
1736 dprintf_module( stddeb, "WIN32_GetProcAddress16: %04x '%s'\n",
1737 hModule, name );
1738 } else {
1739 ordinal = LOWORD(name);
1740 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1741 hModule, ordinal );
1743 if (!ordinal) return (FARPROC16)0;
1744 ret = MODULE_GetEntryPoint( hModule, ordinal );
1745 dprintf_module(stddeb,"WIN32_GetProcAddress16: returning %08x\n",(UINT32)ret);
1746 return ret;
1749 /***********************************************************************
1750 * GetProcAddress16 (KERNEL.50)
1752 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1754 WORD ordinal;
1755 FARPROC16 ret;
1757 if (!hModule) hModule = GetCurrentTask();
1758 hModule = MODULE_HANDLEtoHMODULE16( hModule );
1760 if (HIWORD(name) != 0)
1762 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1763 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1764 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1766 else
1768 ordinal = LOWORD(name);
1769 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1770 hModule, ordinal );
1772 if (!ordinal) return (FARPROC16)0;
1774 ret = MODULE_GetEntryPoint( hModule, ordinal );
1776 dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1777 return ret;
1781 /***********************************************************************
1782 * GetProcAddress32 (KERNEL32.257)
1784 FARPROC32 WINAPI GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1786 NE_MODULE *pModule;
1788 if (HIWORD(function))
1789 dprintf_win32(stddeb,"GetProcAddress32(%08lx,%s)\n",(DWORD)hModule,function);
1790 else
1791 dprintf_win32(stddeb,"GetProcAddress32(%08lx,%p)\n",(DWORD)hModule,function);
1792 if (!(pModule = MODULE_GetPtr( hModule )))
1793 return (FARPROC32)0;
1794 if (!pModule->module32)
1796 fprintf(stderr,"Oops, Module 0x%08lx has got no module32?\n",
1797 (DWORD)MODULE_HANDLEtoHMODULE32(hModule)
1799 return (FARPROC32)0;
1801 return PE_FindExportedFunction( pModule->module32, function );
1804 /***********************************************************************
1805 * RtlImageNtHeaders (NTDLL)
1807 LPIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE32 hModule)
1809 /* basically:
1810 * return hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew);
1811 * but we could get HMODULE16 or the like (think builtin modules)
1814 NE_MODULE *pModule;
1816 if (!(pModule = MODULE_GetPtr( hModule )))
1817 return (LPIMAGE_NT_HEADERS)0;
1818 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->module32)
1819 return (LPIMAGE_NT_HEADERS)0;
1820 return PE_HEADER(pModule->module32);
1824 /**********************************************************************
1825 * GetExpWinVer (KERNEL.167)
1827 WORD WINAPI GetExpWinVer( HMODULE16 hModule )
1829 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1830 return pModule ? pModule->expected_version : 0;
1834 /**********************************************************************
1835 * IsSharedSelector (KERNEL.345)
1837 BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
1839 /* Check whether the selector belongs to a DLL */
1840 NE_MODULE *pModule = MODULE_GetPtr( selector );
1841 if (!pModule) return FALSE;
1842 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1846 /**********************************************************************
1847 * ModuleFirst (TOOLHELP.59)
1849 BOOL16 WINAPI ModuleFirst( MODULEENTRY *lpme )
1851 lpme->wNext = hFirstModule;
1852 return ModuleNext( lpme );
1856 /**********************************************************************
1857 * ModuleNext (TOOLHELP.60)
1859 BOOL16 WINAPI ModuleNext( MODULEENTRY *lpme )
1861 NE_MODULE *pModule;
1862 char *name;
1864 if (!lpme->wNext) return FALSE;
1865 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1866 name = (char *)pModule + pModule->name_table;
1867 memcpy( lpme->szModule, name + 1, *name );
1868 lpme->szModule[(BYTE)*name] = '\0';
1869 lpme->hModule = lpme->wNext;
1870 lpme->wcUsage = pModule->count;
1871 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1872 lpme->szExePath[MAX_PATH] = '\0';
1873 lpme->wNext = pModule->next;
1874 return TRUE;
1878 /**********************************************************************
1879 * ModuleFindName (TOOLHELP.61)
1881 BOOL16 WINAPI ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1883 lpme->wNext = GetModuleHandle16( name );
1884 return ModuleNext( lpme );
1888 /**********************************************************************
1889 * ModuleFindHandle (TOOLHELP.62)
1891 BOOL16 WINAPI ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1893 hModule = MODULE_HANDLEtoHMODULE16( hModule );
1894 lpme->wNext = hModule;
1895 return ModuleNext( lpme );