Release 980215
[wine/multimedia.git] / loader / module.c
blobc7216e61983fc3720cb32a72c2f6aafc46ce8be3
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 "process.h"
23 #include "resource.h"
24 #include "selectors.h"
25 #include "stackframe.h"
26 #include "task.h"
27 #include "toolhelp.h"
28 #include "stddebug.h"
29 #include "debug.h"
30 #include "callback.h"
32 extern HINSTANCE16 PE_LoadModule( HFILE32 hf, OFSTRUCT *ofs, LOADPARAMS* params );
34 static HMODULE16 hFirstModule = 0;
35 static HMODULE16 hCachedModule = 0; /* Module cached by MODULE_OpenFile */
38 /***********************************************************************
39 * MODULE_GetPtr
41 NE_MODULE *MODULE_GetPtr( HMODULE32 hModule )
43 HMODULE16 hnd =MODULE_HANDLEtoHMODULE16(hModule);
45 if (!hnd)
46 return NULL;
47 return (NE_MODULE*)GlobalLock16(hnd);
50 /***********************************************************************
51 * MODULE_HANDLEtoHMODULE16
53 HMODULE16
54 MODULE_HANDLEtoHMODULE16(HANDLE32 handle) {
55 NE_MODULE *pModule;
57 if (HIWORD(handle))
59 /* this is a HMODULE32 */
61 /* walk the list looking for the correct startaddress */
62 pModule = (NE_MODULE *)GlobalLock16( hFirstModule );
63 while (pModule)
65 if (pModule->module32 == handle) return pModule->self;
66 pModule = (NE_MODULE*)GlobalLock16(pModule->next);
68 return 0;
70 return GetExePtr(handle);
73 /***********************************************************************
74 * MODULE_HANDLEtoHMODULE32
75 * return HMODULE32, if possible, HMODULE16 otherwise
77 HMODULE32
78 MODULE_HANDLEtoHMODULE32(HANDLE32 handle) {
79 NE_MODULE *pModule;
81 if (HIWORD(handle))
82 return (HMODULE32)handle;
83 else {
84 handle = GetExePtr(handle);
85 if (!handle)
86 return 0;
87 pModule = (NE_MODULE *)GlobalLock16( handle );
88 if (!pModule)
89 return 0;
91 if (pModule->module32) return pModule->module32;
92 return handle;
96 /***********************************************************************
97 * MODULE_DumpModule
99 void MODULE_DumpModule( HMODULE32 hModule )
101 int i, ordinal;
102 SEGTABLEENTRY *pSeg;
103 BYTE *pstr;
104 WORD *pword;
105 NE_MODULE *pModule;
107 if (!(pModule = MODULE_GetPtr( hModule )))
109 fprintf( stderr, "**** %04x is not a module handle\n", hModule );
110 return;
113 /* Dump the module info */
115 printf( "Module %04x:\n", hModule );
116 printf( "count=%d flags=%04x heap=%d stack=%d\n",
117 pModule->count, pModule->flags,
118 pModule->heap_size, pModule->stack_size );
119 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
120 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
121 pModule->seg_count, pModule->modref_count );
122 printf( "os_flags=%d swap_area=%d version=%04x\n",
123 pModule->os_flags, pModule->min_swap_area,
124 pModule->expected_version );
125 if (pModule->flags & NE_FFLAGS_WIN32)
126 printf( "PE module=%08x\n", pModule->module32 );
128 /* Dump the file info */
130 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
132 /* Dump the segment table */
134 printf( "\nSegment table:\n" );
135 pSeg = NE_SEG_TABLE( pModule );
136 for (i = 0; i < pModule->seg_count; i++, pSeg++)
137 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
138 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
139 pSeg->minsize, pSeg->selector );
141 /* Dump the resource table */
143 printf( "\nResource table:\n" );
144 if (pModule->res_table)
146 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
147 printf( "Alignment: %d\n", *pword++ );
148 while (*pword)
150 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
151 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
152 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
153 for (i = 0; i < ptr->count; i++, pname++)
154 printf( "offset=%d len=%d id=%04x\n",
155 pname->offset, pname->length, pname->id );
156 pword = (WORD *)pname;
159 else printf( "None\n" );
161 /* Dump the resident name table */
163 printf( "\nResident-name table:\n" );
164 pstr = (char *)pModule + pModule->name_table;
165 while (*pstr)
167 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
168 *(WORD *)(pstr + *pstr + 1) );
169 pstr += *pstr + 1 + sizeof(WORD);
172 /* Dump the module reference table */
174 printf( "\nModule ref table:\n" );
175 if (pModule->modref_table)
177 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
178 for (i = 0; i < pModule->modref_count; i++, pword++)
180 printf( "%d: %04x -> '%s'\n", i, *pword,
181 MODULE_GetModuleName(*pword));
184 else printf( "None\n" );
186 /* Dump the entry table */
188 printf( "\nEntry table:\n" );
189 pstr = (char *)pModule + pModule->entry_table;
190 ordinal = 1;
191 while (*pstr)
193 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
194 if (!pstr[1])
196 ordinal += *pstr;
197 pstr += 2;
199 else if ((BYTE)pstr[1] == 0xff) /* moveable */
201 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
202 for (i = 0; i < *pstr; i++, pe++)
203 printf( "%d: %02x:%04x (moveable)\n",
204 ordinal++, pe->seg_number, pe->offset );
205 pstr = (char *)pe;
207 else /* fixed */
209 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
210 for (i = 0; i < *pstr; i++, pe++)
211 printf( "%d: %04x (fixed)\n",
212 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
213 pstr = (char *)pe;
217 /* Dump the non-resident names table */
219 printf( "\nNon-resident names table:\n" );
220 if (pModule->nrname_handle)
222 pstr = (char *)GlobalLock16( pModule->nrname_handle );
223 while (*pstr)
225 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
226 *(WORD *)(pstr + *pstr + 1) );
227 pstr += *pstr + 1 + sizeof(WORD);
230 printf( "\n" );
234 /***********************************************************************
235 * MODULE_WalkModules
237 * Walk the module list and print the modules.
239 void MODULE_WalkModules(void)
241 HMODULE16 hModule = hFirstModule;
242 fprintf( stderr, "Module Flags Name\n" );
243 while (hModule)
245 NE_MODULE *pModule = MODULE_GetPtr( hModule );
246 if (!pModule)
248 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
249 return;
251 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
252 *((char *)pModule + pModule->name_table),
253 (char *)pModule + pModule->name_table + 1 );
254 hModule = pModule->next;
259 /***********************************************************************
260 * MODULE_OpenFile
262 int MODULE_OpenFile( HMODULE32 hModule )
264 NE_MODULE *pModule;
265 DOS_FULL_NAME full_name;
266 char *name;
268 static int cachedfd = -1;
270 hModule = MODULE_HANDLEtoHMODULE16(hModule);
271 dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
272 hModule, hCachedModule, cachedfd );
273 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
274 if (hCachedModule == hModule) return cachedfd;
275 close( cachedfd );
276 hCachedModule = hModule;
277 name = NE_MODULE_NAME( pModule );
278 if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
279 (cachedfd = open( full_name.long_name, O_RDONLY )) == -1)
280 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
281 name, hModule );
282 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
283 name, cachedfd );
284 return cachedfd;
288 /***********************************************************************
289 * MODULE_Ne2MemFlags
291 * This function translates NE segment flags to GlobalAlloc flags
293 static WORD MODULE_Ne2MemFlags(WORD flags)
295 WORD memflags = 0;
296 #if 0
297 if (flags & NE_SEGFLAGS_DISCARDABLE)
298 memflags |= GMEM_DISCARDABLE;
299 if (flags & NE_SEGFLAGS_MOVEABLE ||
300 ( ! (flags & NE_SEGFLAGS_DATA) &&
301 ! (flags & NE_SEGFLAGS_LOADED) &&
302 ! (flags & NE_SEGFLAGS_ALLOCATED)
305 memflags |= GMEM_MOVEABLE;
306 memflags |= GMEM_ZEROINIT;
307 #else
308 memflags = GMEM_ZEROINIT | GMEM_FIXED;
309 return memflags;
310 #endif
313 /***********************************************************************
314 * MODULE_AllocateSegment (WPROCS.26)
317 DWORD WINAPI MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
319 WORD size = wSize << wElem;
320 HANDLE16 hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
321 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
324 /***********************************************************************
325 * MODULE_CreateSegments
327 static BOOL32 MODULE_CreateSegments( HMODULE32 hModule )
329 SEGTABLEENTRY *pSegment;
330 NE_MODULE *pModule;
331 int i, minsize;
333 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
334 pSegment = NE_SEG_TABLE( pModule );
335 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
337 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
338 if (i == pModule->ss) minsize += pModule->stack_size;
339 /* The DGROUP is allocated by MODULE_CreateInstance */
340 if (i == pModule->dgroup) continue;
341 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
342 minsize, hModule,
343 !(pSegment->flags & NE_SEGFLAGS_DATA),
344 FALSE,
345 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
346 if (!pSegment->selector) return FALSE;
349 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
350 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
351 return TRUE;
355 /***********************************************************************
356 * MODULE_GetInstance
358 HINSTANCE16 MODULE_GetInstance( HMODULE32 hModule )
360 SEGTABLEENTRY *pSegment;
361 NE_MODULE *pModule;
363 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
364 if (pModule->dgroup == 0) return hModule;
366 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
368 return pSegment->selector;
372 /***********************************************************************
373 * MODULE_CreateInstance
375 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
377 SEGTABLEENTRY *pSegment;
378 NE_MODULE *pModule;
379 int minsize;
380 HINSTANCE16 hNewInstance, hPrevInstance;
382 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
383 if (pModule->dgroup == 0) return hModule;
385 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
386 hPrevInstance = pSegment->selector;
388 /* if it's a library, create a new instance only the first time */
389 if (hPrevInstance)
391 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
392 if (params == (LOADPARAMS*)-1) return hPrevInstance;
395 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
396 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
397 minsize += pModule->heap_size;
398 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
399 minsize, hModule, FALSE, FALSE, FALSE );
400 if (!hNewInstance) return 0;
401 pSegment->selector = hNewInstance;
402 return hNewInstance;
406 /***********************************************************************
407 * MODULE_CreateDummyModule
409 * Create a dummy NE module for Win32 or Winelib.
411 HMODULE32 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
413 HMODULE32 hModule;
414 NE_MODULE *pModule;
415 SEGTABLEENTRY *pSegment;
416 char *pStr,*s;
417 int len;
418 const char* basename;
420 INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
421 + strlen(ofs->szPathName) + 1;
422 INT32 size = sizeof(NE_MODULE) +
423 /* loaded file info */
424 of_size +
425 /* segment table: DS,CS */
426 2 * sizeof(SEGTABLEENTRY) +
427 /* name table */
429 /* several empty tables */
432 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
433 if (!hModule) return (HMODULE32)11; /* invalid exe */
435 FarSetOwner( hModule, hModule );
436 pModule = (NE_MODULE *)GlobalLock16( hModule );
438 /* Set all used entries */
439 pModule->magic = IMAGE_OS2_SIGNATURE;
440 pModule->count = 1;
441 pModule->next = 0;
442 pModule->flags = 0;
443 pModule->dgroup = 1;
444 pModule->ss = 1;
445 pModule->cs = 2;
446 pModule->heap_size = 0xe000;
447 pModule->stack_size = 0x1000;
448 pModule->seg_count = 2;
449 pModule->modref_count = 0;
450 pModule->nrname_size = 0;
451 pModule->fileinfo = sizeof(NE_MODULE);
452 pModule->os_flags = NE_OSFLAGS_WINDOWS;
453 pModule->expected_version = 0x030a;
454 pModule->self = hModule;
456 /* Set loaded file information */
457 memcpy( pModule + 1, ofs, of_size );
458 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
460 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
461 pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
462 /* Data segment */
463 pSegment->size = 0;
464 pSegment->flags = NE_SEGFLAGS_DATA;
465 pSegment->minsize = 0x1000;
466 pSegment++;
467 /* Code segment */
468 pSegment->flags = 0;
469 pSegment++;
471 /* Module name */
472 pStr = (char *)pSegment;
473 pModule->name_table = (int)pStr - (int)pModule;
474 basename = strrchr(ofs->szPathName,'\\');
475 if (!basename) basename = ofs->szPathName;
476 else basename++;
477 len = strlen(basename);
478 if ((s = strchr(basename,'.'))) len = s - basename;
479 if (len > 8) len = 8;
480 *pStr = len;
481 strncpy( pStr+1, basename, len );
482 if (len < 8) pStr[len+1] = 0;
483 pStr += 9;
485 /* All tables zero terminated */
486 pModule->res_table = pModule->import_table = pModule->entry_table =
487 (int)pStr - (int)pModule;
489 MODULE_RegisterModule( pModule );
490 return hModule;
494 /***********************************************************************
495 * MODULE_LoadExeHeader
497 static HMODULE32 MODULE_LoadExeHeader( HFILE32 hFile, OFSTRUCT *ofs )
499 IMAGE_DOS_HEADER mz_header;
500 IMAGE_OS2_HEADER ne_header;
501 int size;
502 HMODULE32 hModule;
503 NE_MODULE *pModule;
504 BYTE *pData;
505 char *buffer, *fastload = NULL;
506 int fastload_offset = 0, fastload_length = 0;
508 /* Read a block from either the file or the fast-load area. */
509 #define READ(offset,size,buffer) \
510 ((fastload && ((offset) >= fastload_offset) && \
511 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
512 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
513 (_llseek32( hFile, (offset), SEEK_SET), \
514 _lread32( hFile, (buffer), (size) ) == (size)))
516 _llseek32( hFile, 0, SEEK_SET );
517 if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
518 (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
519 return (HMODULE32)11; /* invalid exe */
521 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
522 if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
523 return (HMODULE32)11; /* invalid exe */
525 if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE32)21; /* win32 exe */
526 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE32)11; /* invalid exe */
528 if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
529 fprintf(stderr, "Sorry, this is an OS/2 linear executable (LX) file !\n");
530 return (HMODULE32)12;
532 /* We now have a valid NE header */
534 size = sizeof(NE_MODULE) +
535 /* loaded file info */
536 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
537 /* segment table */
538 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
539 /* resource table */
540 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
541 /* resident names table */
542 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
543 /* module ref table */
544 ne_header.n_mod_ref_tab * sizeof(WORD) +
545 /* imported names table */
546 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
547 /* entry table length */
548 ne_header.entry_tab_length;
550 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
551 if (!hModule) return (HMODULE32)11; /* invalid exe */
552 FarSetOwner( hModule, hModule );
553 pModule = (NE_MODULE *)GlobalLock16( hModule );
554 memcpy( pModule, &ne_header, sizeof(ne_header) );
555 pModule->count = 0;
556 pModule->module32 = 0;
557 pModule->self = hModule;
558 pModule->self_loading_sel = 0;
559 pData = (BYTE *)(pModule + 1);
561 /* Clear internal Wine flags in case they are set in the EXE file */
563 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
565 /* Read the fast-load area */
567 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
569 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
570 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
571 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
572 fastload_offset, fastload_length );
573 if ((fastload = HeapAlloc( SystemHeap, 0, fastload_length )) != NULL)
575 _llseek32( hFile, fastload_offset, SEEK_SET);
576 if (_lread32(hFile, fastload, fastload_length) != fastload_length)
578 HeapFree( SystemHeap, 0, fastload );
579 fprintf(stderr, "Error reading fast-load area !\n");
580 fastload = NULL;
585 /* Store the filename information */
587 pModule->fileinfo = (int)pData - (int)pModule;
588 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
589 memcpy( pData, ofs, size );
590 ((OFSTRUCT *)pData)->cBytes = size - 1;
591 pData += size;
593 /* Get the segment table */
595 pModule->seg_table = (int)pData - (int)pModule;
596 buffer = HeapAlloc( SystemHeap, 0, ne_header.n_segment_tab *
597 sizeof(struct ne_segment_table_entry_s));
598 if (buffer)
600 int i;
601 struct ne_segment_table_entry_s *pSeg;
603 if (!READ( mz_header.e_lfanew + ne_header.segment_tab_offset,
604 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
605 buffer ))
607 HeapFree( SystemHeap, 0, buffer );
608 if (fastload) HeapFree( SystemHeap, 0, fastload );
609 GlobalFree16( hModule );
610 return (HMODULE32)11; /* invalid exe */
612 pSeg = (struct ne_segment_table_entry_s *)buffer;
613 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
615 memcpy( pData, pSeg, sizeof(*pSeg) );
616 pData += sizeof(SEGTABLEENTRY);
618 HeapFree( SystemHeap, 0, buffer );
620 else
622 if (fastload) HeapFree( SystemHeap, 0, fastload );
623 GlobalFree16( hModule );
624 return (HMODULE32)11; /* invalid exe */
627 /* Get the resource table */
629 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
631 pModule->res_table = (int)pData - (int)pModule;
632 if (!READ(mz_header.e_lfanew + ne_header.resource_tab_offset,
633 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
634 pData )) return (HMODULE32)11; /* invalid exe */
635 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
636 NE_InitResourceHandler( hModule );
638 else pModule->res_table = 0; /* No resource table */
640 /* Get the resident names table */
642 pModule->name_table = (int)pData - (int)pModule;
643 if (!READ( mz_header.e_lfanew + ne_header.rname_tab_offset,
644 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
645 pData ))
647 if (fastload) HeapFree( SystemHeap, 0, fastload );
648 GlobalFree16( hModule );
649 return (HMODULE32)11; /* invalid exe */
651 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
653 /* Get the module references table */
655 if (ne_header.n_mod_ref_tab > 0)
657 pModule->modref_table = (int)pData - (int)pModule;
658 if (!READ( mz_header.e_lfanew + ne_header.moduleref_tab_offset,
659 ne_header.n_mod_ref_tab * sizeof(WORD),
660 pData ))
662 if (fastload) HeapFree( SystemHeap, 0, fastload );
663 GlobalFree16( hModule );
664 return (HMODULE32)11; /* invalid exe */
666 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
668 else pModule->modref_table = 0; /* No module references */
670 /* Get the imported names table */
672 pModule->import_table = (int)pData - (int)pModule;
673 if (!READ( mz_header.e_lfanew + ne_header.iname_tab_offset,
674 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
675 pData ))
677 if (fastload) HeapFree( SystemHeap, 0, fastload );
678 GlobalFree16( hModule );
679 return (HMODULE32)11; /* invalid exe */
681 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
683 /* Get the entry table */
685 pModule->entry_table = (int)pData - (int)pModule;
686 if (!READ( mz_header.e_lfanew + ne_header.entry_tab_offset,
687 ne_header.entry_tab_length,
688 pData ))
690 if (fastload) HeapFree( SystemHeap, 0, fastload );
691 GlobalFree16( hModule );
692 return (HMODULE32)11; /* invalid exe */
694 pData += ne_header.entry_tab_length;
696 /* Free the fast-load area */
698 #undef READ
699 if (fastload) HeapFree( SystemHeap, 0, fastload );
701 /* Get the non-resident names table */
703 if (ne_header.nrname_tab_length)
705 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
706 hModule, FALSE, FALSE, FALSE );
707 if (!pModule->nrname_handle)
709 GlobalFree16( hModule );
710 return (HMODULE32)11; /* invalid exe */
712 buffer = GlobalLock16( pModule->nrname_handle );
713 _llseek32( hFile, ne_header.nrname_tab_offset, SEEK_SET );
714 if (_lread32( hFile, buffer, ne_header.nrname_tab_length )
715 != ne_header.nrname_tab_length)
717 GlobalFree16( pModule->nrname_handle );
718 GlobalFree16( hModule );
719 return (HMODULE32)11; /* invalid exe */
722 else pModule->nrname_handle = 0;
724 /* Allocate a segment for the implicitly-loaded DLLs */
726 if (pModule->modref_count)
728 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
729 (pModule->modref_count+1)*sizeof(HMODULE32),
730 hModule, FALSE, FALSE, FALSE );
731 if (!pModule->dlls_to_init)
733 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
734 GlobalFree16( hModule );
735 return (HMODULE32)11; /* invalid exe */
738 else pModule->dlls_to_init = 0;
740 MODULE_RegisterModule( pModule );
741 return hModule;
745 /***********************************************************************
746 * MODULE_GetOrdinal
748 * Lookup the ordinal for a given name.
750 WORD MODULE_GetOrdinal( HMODULE32 hModule, const char *name )
752 unsigned char buffer[256], *cpnt;
753 BYTE len;
754 NE_MODULE *pModule;
756 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
758 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
759 hModule, name );
761 /* First handle names of the form '#xxxx' */
763 if (name[0] == '#') return atoi( name + 1 );
765 /* Now copy and uppercase the string */
767 strcpy( buffer, name );
768 CharUpper32A( buffer );
769 len = strlen( buffer );
771 /* First search the resident names */
773 cpnt = (char *)pModule + pModule->name_table;
775 /* Skip the first entry (module name) */
776 cpnt += *cpnt + 1 + sizeof(WORD);
777 while (*cpnt)
779 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
781 dprintf_module( stddeb, " Found: ordinal=%d\n",
782 *(WORD *)(cpnt + *cpnt + 1) );
783 return *(WORD *)(cpnt + *cpnt + 1);
785 cpnt += *cpnt + 1 + sizeof(WORD);
788 /* Now search the non-resident names table */
790 if (!pModule->nrname_handle) return 0; /* No non-resident table */
791 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
793 /* Skip the first entry (module description string) */
794 cpnt += *cpnt + 1 + sizeof(WORD);
795 while (*cpnt)
797 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
799 dprintf_module( stddeb, " Found: ordinal=%d\n",
800 *(WORD *)(cpnt + *cpnt + 1) );
801 return *(WORD *)(cpnt + *cpnt + 1);
803 cpnt += *cpnt + 1 + sizeof(WORD);
805 return 0;
809 /***********************************************************************
810 * MODULE_GetEntryPoint
812 * Return the entry point for a given ordinal.
814 FARPROC16 MODULE_GetEntryPoint( HMODULE32 hModule, WORD ordinal )
816 NE_MODULE *pModule;
817 WORD curOrdinal = 1;
818 BYTE *p;
819 WORD sel, offset;
821 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
823 p = (BYTE *)pModule + pModule->entry_table;
824 while (*p && (curOrdinal + *p <= ordinal))
826 /* Skipping this bundle */
827 curOrdinal += *p;
828 switch(p[1])
830 case 0: p += 2; break; /* unused */
831 case 0xff: p += 2 + *p * 6; break; /* moveable */
832 default: p += 2 + *p * 3; break; /* fixed */
835 if (!*p) return 0;
837 switch(p[1])
839 case 0: /* unused */
840 return 0;
841 case 0xff: /* moveable */
842 p += 2 + 6 * (ordinal - curOrdinal);
843 sel = p[3];
844 offset = *(WORD *)(p + 4);
845 break;
846 default: /* fixed */
847 sel = p[1];
848 p += 2 + 3 * (ordinal - curOrdinal);
849 offset = *(WORD *)(p + 1);
850 break;
853 if (sel == 0xfe) sel = 0xffff; /* constant entry */
854 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
855 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
859 /***********************************************************************
860 * EntryAddrProc (WPROCS.27)
862 FARPROC16 WINAPI EntryAddrProc( HMODULE16 hModule, WORD ordinal )
864 return MODULE_GetEntryPoint( hModule, ordinal );
868 /***********************************************************************
869 * MODULE_SetEntryPoint
871 * Change the value of an entry point. Use with caution!
872 * It can only change the offset value, not the selector.
874 BOOL16 MODULE_SetEntryPoint( HMODULE32 hModule, WORD ordinal, WORD offset )
876 NE_MODULE *pModule;
877 WORD curOrdinal = 1;
878 BYTE *p;
880 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
882 p = (BYTE *)pModule + pModule->entry_table;
883 while (*p && (curOrdinal + *p <= ordinal))
885 /* Skipping this bundle */
886 curOrdinal += *p;
887 switch(p[1])
889 case 0: p += 2; break; /* unused */
890 case 0xff: p += 2 + *p * 6; break; /* moveable */
891 default: p += 2 + *p * 3; break; /* fixed */
894 if (!*p) return FALSE;
896 switch(p[1])
898 case 0: /* unused */
899 return FALSE;
900 case 0xff: /* moveable */
901 p += 2 + 6 * (ordinal - curOrdinal);
902 *(WORD *)(p + 4) = offset;
903 break;
904 default: /* fixed */
905 p += 2 + 3 * (ordinal - curOrdinal);
906 *(WORD *)(p + 1) = offset;
907 break;
909 return TRUE;
913 /***********************************************************************
914 * MODULE_GetWndProcEntry16 (not a Windows API function)
916 * Return an entry point from the WPROCS dll.
918 FARPROC16 MODULE_GetWndProcEntry16( LPCSTR name )
920 FARPROC16 ret = NULL;
922 if (__winelib)
924 /* FIXME: hack for Winelib */
925 extern LRESULT ColorDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
926 extern LRESULT FileOpenDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
927 extern LRESULT FileSaveDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
928 extern LRESULT FindTextDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
929 extern LRESULT PrintDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
930 extern LRESULT PrintSetupDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
931 extern LRESULT ReplaceTextDlgProc(HWND16,UINT16,WPARAM16,LPARAM);
933 if (!strcmp(name,"ColorDlgProc"))
934 return (FARPROC16)ColorDlgProc;
935 if (!strcmp(name,"FileOpenDlgProc"))
936 return (FARPROC16)FileOpenDlgProc;
937 if (!strcmp(name,"FileSaveDlgProc"))
938 return (FARPROC16)FileSaveDlgProc;
939 if (!strcmp(name,"FindTextDlgProc"))
940 return (FARPROC16)FindTextDlgProc;
941 if (!strcmp(name,"PrintDlgProc"))
942 return (FARPROC16)PrintDlgProc;
943 if (!strcmp(name,"PrintSetupDlgProc"))
944 return (FARPROC16)PrintSetupDlgProc;
945 if (!strcmp(name,"ReplaceTextDlgProc"))
946 return (FARPROC16)ReplaceTextDlgProc;
947 fprintf(stderr,"warning: No mapping for %s(), add one in library/miscstubs.c\n",name);
948 assert( FALSE );
949 return NULL;
951 else
953 WORD ordinal;
954 static HMODULE32 hModule = 0;
956 if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
957 ordinal = MODULE_GetOrdinal( hModule, name );
958 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
960 fprintf( stderr, "GetWndProc16: %s not found\n", name );
961 assert( FALSE );
964 return ret;
968 /***********************************************************************
969 * MODULE_GetModuleName
971 LPSTR MODULE_GetModuleName( HMODULE32 hModule )
973 NE_MODULE *pModule;
974 BYTE *p, len;
975 static char buffer[10];
977 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
978 p = (BYTE *)pModule + pModule->name_table;
979 len = MIN( *p, 8 );
980 memcpy( buffer, p + 1, len );
981 buffer[len] = '\0';
982 return buffer;
986 /**********************************************************************
987 * MODULE_RegisterModule
989 void MODULE_RegisterModule( NE_MODULE *pModule )
991 pModule->next = hFirstModule;
992 hFirstModule = pModule->self;
996 /**********************************************************************
997 * MODULE_FindModule
999 * Find a module from a path name.
1001 HMODULE32 MODULE_FindModule( LPCSTR path )
1003 HMODULE32 hModule = hFirstModule;
1004 LPCSTR filename, dotptr, modulepath, modulename;
1005 BYTE len, *name_table;
1007 if (!(filename = strrchr( path, '\\' ))) filename = path;
1008 else filename++;
1009 if ((dotptr = strrchr( filename, '.' )) != NULL)
1010 len = (BYTE)(dotptr - filename);
1011 else len = strlen( filename );
1013 while(hModule)
1015 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1016 if (!pModule) break;
1017 modulepath = NE_MODULE_NAME(pModule);
1018 if (!(modulename = strrchr( modulepath, '\\' )))
1019 modulename = modulepath;
1020 else modulename++;
1021 if (!lstrcmpi32A( modulename, filename )) return hModule;
1023 name_table = (BYTE *)pModule + pModule->name_table;
1024 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
1025 return hModule;
1026 hModule = pModule->next;
1028 return 0;
1032 /**********************************************************************
1033 * MODULE_CallWEP
1035 * Call a DLL's WEP, allowing it to shut down.
1036 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
1038 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
1040 FARPROC16 WEP = (FARPROC16)0;
1041 WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
1043 if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
1044 if (!WEP)
1046 dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
1047 return FALSE;
1049 return Callbacks->CallWindowsExitProc( WEP, WEP_FREE_DLL );
1053 /**********************************************************************
1054 * MODULE_FreeModule
1056 * Remove a module from memory.
1058 BOOL16 MODULE_FreeModule( HMODULE32 hModule, TDB* pTaskContext )
1060 HMODULE16 *hPrevModule;
1061 NE_MODULE *pModule;
1062 SEGTABLEENTRY *pSegment;
1063 HMODULE16 *pModRef;
1064 int i;
1066 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1067 hModule = pModule->self;
1069 if (((INT16)(--pModule->count)) > 0 ) return TRUE;
1070 else pModule->count = 0;
1072 if (pModule->flags & NE_FFLAGS_BUILTIN)
1073 return FALSE; /* Can't free built-in module */
1075 if (pModule->flags & NE_FFLAGS_LIBMODULE)
1077 MODULE_CallWEP( hModule );
1079 /* Free the objects owned by the DLL module */
1081 if( pTaskContext && pTaskContext->userhandler )
1083 pTaskContext->userhandler( hModule, USIG_DLL_UNLOAD, 0,
1084 pTaskContext->hInstance,
1085 pTaskContext->hQueue );
1088 /* Clear magic number just in case */
1090 pModule->magic = pModule->self = 0;
1092 /* Remove it from the linked list */
1094 hPrevModule = &hFirstModule;
1095 while (*hPrevModule && (*hPrevModule != hModule))
1097 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
1099 if (*hPrevModule) *hPrevModule = pModule->next;
1101 /* Free all the segments */
1103 pSegment = NE_SEG_TABLE( pModule );
1104 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
1106 GlobalFree16( pSegment->selector );
1109 /* Free the referenced modules */
1111 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
1112 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1114 FreeModule16( *pModRef );
1117 /* Free the module storage */
1119 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
1120 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
1121 GlobalFree16( hModule );
1123 /* Remove module from cache */
1125 if (hCachedModule == hModule) hCachedModule = 0;
1127 return TRUE;
1131 /**********************************************************************
1132 * MODULE_Load
1134 * Implementation of LoadModule()
1136 HINSTANCE16 MODULE_Load( LPCSTR name, LPVOID paramBlock, UINT16 uFlags)
1138 HMODULE32 hModule;
1139 HINSTANCE16 hInstance, hPrevInstance;
1140 NE_MODULE *pModule;
1141 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1142 OFSTRUCT ofs;
1143 HFILE32 hFile;
1145 if (__winelib)
1147 lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1148 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1149 pModule = (NE_MODULE *)GlobalLock16( hModule );
1150 hPrevInstance = 0;
1151 hInstance = MODULE_CreateInstance( hModule, params );
1153 else
1155 hModule = MODULE_FindModule( name );
1157 if (!hModule) /* We have to load the module */
1159 /* Try to load the built-in first if not disabled */
1160 if ((hModule = BUILTIN_LoadModule( name, FALSE )))
1161 return MODULE_HANDLEtoHMODULE16( hModule );
1163 if ((hFile = OpenFile32( name, &ofs, OF_READ )) == HFILE_ERROR32)
1165 /* Now try the built-in even if disabled */
1166 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
1168 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1169 return MODULE_HANDLEtoHMODULE16( hModule );
1171 return 2; /* File not found */
1174 /* Create the module structure */
1176 hModule = MODULE_LoadExeHeader( hFile, &ofs );
1177 if (hModule < 32)
1179 if (hModule == 21)
1180 hModule = PE_LoadModule( hFile, &ofs, paramBlock );
1181 else _lclose32( hFile );
1183 if (hModule < 32)
1184 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1185 name, hModule );
1186 return hModule;
1188 _lclose32( hFile );
1189 pModule = MODULE_GetPtr( hModule );
1190 pModule->flags |= uFlags; /* stamp implicitly loaded modules */
1192 /* Allocate the segments for this module */
1194 MODULE_CreateSegments( hModule );
1195 hPrevInstance = 0;
1196 hInstance = MODULE_CreateInstance(hModule,(LOADPARAMS*)paramBlock);
1198 /* Load the referenced DLLs */
1200 if (!NE_LoadDLLs( pModule )) return 2; /* File not found */
1202 /* Load the segments */
1204 NE_LoadAllSegments( pModule );
1206 /* Fixup the functions prologs */
1208 NE_FixupPrologs( pModule );
1210 /* Make sure the usage count is 1 on the first loading of */
1211 /* the module, even if it contains circular DLL references */
1213 pModule->count = 1;
1215 /* Call initialization rountines for all loaded DLLs. Note that
1216 * when we load implicitly linked DLLs this will be done by InitTask().
1219 if ((pModule->flags & (NE_FFLAGS_LIBMODULE | NE_FFLAGS_IMPLICIT)) ==
1220 NE_FFLAGS_LIBMODULE )
1221 NE_InitializeDLLs( hModule );
1223 else /* module is already loaded, just create a new data segment if it's a task */
1225 pModule = MODULE_GetPtr( hModule );
1226 hPrevInstance = MODULE_GetInstance( hModule );
1227 hInstance = MODULE_CreateInstance( hModule, params );
1228 if (hInstance != hPrevInstance) /* not a library */
1229 NE_LoadSegment( pModule, pModule->dgroup );
1230 pModule->count++;
1232 } /* !winelib */
1234 /* Create a task for this instance */
1236 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1238 HTASK16 hTask;
1239 WORD showcmd;
1241 pModule->flags |= NE_FFLAGS_GUI;
1243 /* PowerPoint passes NULL as showCmd */
1244 if (params->showCmd)
1245 showcmd = *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1);
1246 else
1247 showcmd = 0; /* FIXME: correct */
1249 hTask = TASK_CreateTask( hModule, hInstance, hPrevInstance,
1250 params->hEnvironment,
1251 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1252 showcmd );
1254 if( hTask && TASK_GetNextTask(hTask)) Yield16();
1257 return hInstance;
1261 /**********************************************************************
1262 * LoadModule16 (KERNEL.45)
1264 HINSTANCE16 LoadModule16( LPCSTR name, LPVOID paramBlock )
1266 return MODULE_Load( name, paramBlock, 0 );
1269 /**********************************************************************
1270 * LoadModule32 (KERNEL32)
1271 * FIXME: check this function
1273 DWORD LoadModule32( LPCSTR name, LPVOID paramBlock )
1275 return MODULE_Load( name, paramBlock, 0 );
1279 /**********************************************************************
1280 * FreeModule16 (KERNEL.46)
1282 BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
1284 NE_MODULE *pModule;
1286 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1287 dprintf_module( stddeb, "FreeModule16: %s count %d\n",
1288 MODULE_GetModuleName(hModule), pModule->count );
1290 return MODULE_FreeModule( hModule, GlobalLock16(GetCurrentTask()) );
1294 /**********************************************************************
1295 * GetModuleHandle16 (KERNEL.47)
1297 HMODULE16 WINAPI WIN16_GetModuleHandle( SEGPTR name )
1299 if (HIWORD(name) == 0) return MODULE_HANDLEtoHMODULE16( (HINSTANCE16)name );
1300 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1303 HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
1305 return MODULE_FindModule( name );
1308 /***********************************************************************
1309 * GetModuleHandle (KERNEL32.237)
1311 HMODULE32 WINAPI GetModuleHandle32A(LPCSTR module)
1313 HMODULE32 hModule;
1315 dprintf_win32(stddeb, "GetModuleHandleA: %s\n", module ? module : "NULL");
1316 /* Freecell uses the result of GetModuleHandleA(0) as the hInstance in
1317 all calls to e.g. CreateWindowEx. */
1318 if (module == NULL) {
1319 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1320 hModule = pTask->hInstance;
1321 } else
1322 hModule = MODULE_FindModule(module);
1323 return MODULE_HANDLEtoHMODULE32(hModule);
1326 HMODULE32 WINAPI GetModuleHandle32W(LPCWSTR module)
1328 HMODULE32 hModule;
1329 LPSTR modulea = HEAP_strdupWtoA( GetProcessHeap(), 0, module );
1330 hModule = GetModuleHandle32A( modulea );
1331 HeapFree( GetProcessHeap(), 0, modulea );
1332 return hModule;
1336 /**********************************************************************
1337 * GetModuleUsage (KERNEL.48)
1339 INT16 WINAPI GetModuleUsage( HINSTANCE16 hModule )
1341 NE_MODULE *pModule;
1343 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1344 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1345 hModule, pModule->count );
1346 return pModule->count;
1350 /**********************************************************************
1351 * GetModuleFileName16 (KERNEL.49)
1353 INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
1354 INT16 nSize )
1356 NE_MODULE *pModule;
1358 if (!hModule) hModule = GetCurrentTask();
1359 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1360 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1361 dprintf_module( stddeb, "GetModuleFileName16: %s\n", lpFileName );
1362 return strlen(lpFileName);
1366 /***********************************************************************
1367 * GetModuleFileName32A (KERNEL32.235)
1369 DWORD WINAPI GetModuleFileName32A( HMODULE32 hModule, LPSTR lpFileName,
1370 DWORD size )
1372 NE_MODULE *pModule;
1374 if (!hModule)
1376 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1377 hModule = pTask->hInstance;
1379 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1380 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
1381 dprintf_module( stddeb, "GetModuleFileName32A: %s\n", lpFileName );
1382 return strlen(lpFileName);
1386 /***********************************************************************
1387 * GetModuleFileName32W (KERNEL32.236)
1389 DWORD WINAPI GetModuleFileName32W( HMODULE32 hModule, LPWSTR lpFileName,
1390 DWORD size )
1392 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1393 DWORD res = GetModuleFileName32A( hModule, fnA, size );
1394 lstrcpynAtoW( lpFileName, fnA, size );
1395 HeapFree( GetProcessHeap(), 0, fnA );
1396 return res;
1400 /**********************************************************************
1401 * GetModuleName (KERNEL.27)
1403 BOOL16 WINAPI GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
1405 LPSTR name = MODULE_GetModuleName(hinst);
1407 if (!name) return FALSE;
1408 lstrcpyn32A( buf, name, nSize );
1409 return TRUE;
1413 /***********************************************************************
1414 * LoadLibraryEx32W (KERNEL.513)
1415 * FIXME
1417 HMODULE32 WINAPI LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf,
1418 DWORD flags )
1420 fprintf(stderr,"LoadLibraryEx32W(%s,%d,%08lx)\n",libname,hf,flags);
1421 return LoadLibraryEx32A(libname, hf,flags);
1424 /***********************************************************************
1425 * LoadLibraryEx32A (KERNEL32)
1427 HMODULE32 WINAPI LoadLibraryEx32A(LPCSTR libname,HFILE32 hfile,DWORD flags)
1429 HMODULE32 hmod;
1431 hmod = PE_LoadLibraryEx32A(libname,PROCESS_Current(),hfile,flags);
1432 if (hmod <= 32) {
1433 char buffer[256];
1435 strcpy( buffer, libname );
1436 strcat( buffer, ".dll" );
1437 hmod = PE_LoadLibraryEx32A(buffer,PROCESS_Current(),hfile,flags);
1439 /* initialize all DLLs, which haven't been initialized yet. */
1440 PE_InitializeDLLs( PROCESS_Current(), DLL_PROCESS_ATTACH, NULL);
1441 return hmod;
1444 /***********************************************************************
1445 * LoadLibraryA (KERNEL32)
1447 HMODULE32 WINAPI LoadLibrary32A(LPCSTR libname) {
1448 return LoadLibraryEx32A(libname,0,0);
1451 /***********************************************************************
1452 * LoadLibraryW (KERNEL32)
1454 HMODULE32 WINAPI LoadLibrary32W(LPCWSTR libnameW)
1456 return LoadLibraryEx32W(libnameW,0,0);
1459 /***********************************************************************
1460 * LoadLibraryExW (KERNEL32)
1462 HMODULE32 WINAPI LoadLibraryEx32W(LPCWSTR libnameW,HFILE32 hfile,DWORD flags)
1464 LPSTR libnameA = HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW );
1465 HMODULE32 ret = LoadLibraryEx32A( libnameA , hfile, flags );
1467 HeapFree( GetProcessHeap(), 0, libnameA );
1468 return ret;
1471 /***********************************************************************
1472 * FreeLibrary
1474 BOOL32 WINAPI FreeLibrary32(HINSTANCE32 hLibModule)
1476 dprintf_module(stddeb,"FreeLibrary: hLibModule: %08x\n", hLibModule);
1477 return MODULE_FreeModule(hLibModule,
1478 GlobalLock16(GetCurrentTask()) );
1482 /***********************************************************************
1483 * LoadLibrary (KERNEL.95)
1485 HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
1487 HINSTANCE16 handle;
1489 if (__winelib)
1491 fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1492 return 0;
1494 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1496 handle = MODULE_Load( libname, (LPVOID)-1, 0 );
1497 if (handle == (HINSTANCE16)2) /* file not found */
1499 char buffer[256];
1500 lstrcpyn32A( buffer, libname, 252 );
1501 strcat( buffer, ".dll" );
1502 handle = MODULE_Load( buffer, (LPVOID)-1, 0 );
1504 return handle;
1508 /***********************************************************************
1509 * PrivateLoadLibrary (KERNEL32)
1511 * FIXME: rough guesswork, don't know what "Private" means
1513 HINSTANCE32 WINAPI PrivateLoadLibrary(LPCSTR libname)
1515 return (HINSTANCE32)LoadLibrary16(libname);
1519 /***********************************************************************
1520 * FreeLibrary16 (KERNEL.96)
1522 void WINAPI FreeLibrary16( HINSTANCE16 handle )
1524 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1525 FreeModule16( handle );
1529 /***********************************************************************
1530 * PrivateFreeLibrary (KERNEL32)
1532 * FIXME: rough guesswork, don't know what "Private" means
1534 void WINAPI PrivateFreeLibrary(HINSTANCE32 handle)
1536 FreeLibrary16((HINSTANCE16)handle);
1540 /***********************************************************************
1541 * WinExec16 (KERNEL.166)
1543 HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
1545 return WinExec32( lpCmdLine, nCmdShow );
1549 /***********************************************************************
1550 * WinExec32 (KERNEL32.566)
1552 HINSTANCE32 WINAPI WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow )
1554 LOADPARAMS params;
1555 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1556 HINSTANCE16 handle = 2;
1557 WORD *cmdShowPtr;
1558 char *p, *cmdline, filename[256];
1559 static int use_load_module = 1;
1560 int spacelimit = 0, exhausted = 0;
1562 if (!lpCmdLine)
1563 return 2; /* File not found */
1564 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1565 return 8; /* Out of memory */
1566 if (!(cmdLineHandle = GlobalAlloc16( 0, 2048 )))
1568 GlobalFree16( cmdShowHandle );
1569 return 8; /* Out of memory */
1572 /* Keep trying to load a file by trying different filenames; e.g.,
1573 for the cmdline "abcd efg hij", try "abcd" with args "efg hij",
1574 then "abcd efg" with arg "hij", and finally "abcd efg hij" with
1575 no args */
1577 while(!exhausted && handle == 2) {
1578 int spacecount = 0;
1580 /* Store nCmdShow */
1582 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1583 cmdShowPtr[0] = 2;
1584 cmdShowPtr[1] = nCmdShow;
1586 /* Build the filename and command-line */
1588 cmdline = (char *)GlobalLock16( cmdLineHandle );
1589 lstrcpyn32A(filename, lpCmdLine,
1590 sizeof(filename) - 4 /* for extension */);
1592 /* Keep grabbing characters until end-of-string, tab, or until the
1593 number of spaces is greater than the spacelimit */
1595 for (p = filename; ; p++) {
1596 if(*p == ' ') {
1597 ++spacecount;
1598 if(spacecount > spacelimit) {
1599 ++spacelimit;
1600 break;
1604 if(*p == '\0' || *p == '\t') {
1605 exhausted = 1;
1606 break;
1610 if (*p)
1611 lstrcpyn32A( cmdline + 1, p + 1, 255 );
1612 else
1613 cmdline[1] = '\0';
1615 cmdline[0] = strlen( cmdline + 1 );
1616 *p = '\0';
1617 /* this is a (hopefully acceptable hack to get the whole
1618 commandline for PROCESS_Create
1619 we put it after the processed one */
1620 lstrcpyn32A(cmdline + (unsigned char)cmdline[0] +2,
1621 lpCmdLine, 2048 - 256);
1623 /* Now load the executable file */
1625 if (use_load_module)
1627 /* Winelib: Use LoadModule() only for the program itself */
1628 if (__winelib) use_load_module = 0;
1629 params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
1630 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1631 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1632 params.reserved = 0;
1633 handle = LoadModule16( filename, &params );
1634 if (handle == 2) /* file not found */
1636 /* Check that the original file name did not have a suffix */
1637 p = strrchr(filename, '.');
1638 /* if there is a '.', check if either \ OR / follow */
1639 if (!p || strchr(p, '/') || strchr(p, '\\'))
1641 p = filename + strlen(filename);
1642 strcpy( p, ".exe" );
1643 handle = LoadModule16( filename, &params );
1644 *p = '\0'; /* Remove extension */
1648 else
1649 handle = 2; /* file not found */
1651 if (handle < 32)
1653 /* Try to start it as a unix program */
1654 if (!fork())
1656 /* Child process */
1657 DOS_FULL_NAME full_name;
1658 const char *unixfilename = NULL;
1659 const char *argv[256], **argptr;
1660 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1661 nCmdShow == SW_SHOWMINNOACTIVE);
1663 /* get unixfilename */
1664 if (strchr(filename, '/') ||
1665 strchr(filename, ':') ||
1666 strchr(filename, '\\'))
1668 if (DOSFS_GetFullName( filename, TRUE, &full_name ))
1669 unixfilename = full_name.long_name;
1671 else unixfilename = filename;
1673 if (unixfilename)
1675 /* build argv */
1676 argptr = argv;
1677 if (iconic) *argptr++ = "-iconic";
1678 *argptr++ = unixfilename;
1679 p = cmdline + 1;
1680 while (1)
1682 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1683 if (!*p) break;
1684 *argptr++ = p;
1685 while (*p && *p != ' ' && *p != '\t') p++;
1687 *argptr++ = 0;
1689 /* Execute */
1690 execvp(argv[0], (char**)argv);
1693 /* Failed ! */
1695 if (__winelib)
1697 /* build argv */
1698 argptr = argv;
1699 *argptr++ = "wine";
1700 if (iconic) *argptr++ = "-iconic";
1701 *argptr++ = lpCmdLine;
1702 *argptr++ = 0;
1704 /* Execute */
1705 execvp(argv[0] , (char**)argv);
1707 /* Failed ! */
1708 fprintf(stderr, "WinExec: can't exec 'wine %s'\n",
1709 lpCmdLine);
1711 exit(1);
1714 } /* while (!exhausted && handle < 32) */
1716 GlobalFree16( cmdShowHandle );
1717 GlobalFree16( cmdLineHandle );
1718 return handle;
1722 /***********************************************************************
1723 * WIN32_GetProcAddress16 (KERNEL32.36)
1724 * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1726 FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE32 hModule, LPSTR name )
1728 WORD ordinal;
1729 FARPROC16 ret;
1731 if (!hModule) {
1732 fprintf(stderr,"WIN32_GetProcAddress16: hModule may not be 0!\n");
1733 return (FARPROC16)0;
1735 hModule = MODULE_HANDLEtoHMODULE16(hModule);
1736 if (HIWORD(name)) {
1737 ordinal = MODULE_GetOrdinal( hModule, name );
1738 dprintf_module( stddeb, "WIN32_GetProcAddress16: %04x '%s'\n",
1739 hModule, name );
1740 } else {
1741 ordinal = LOWORD(name);
1742 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1743 hModule, ordinal );
1745 if (!ordinal) return (FARPROC16)0;
1746 ret = MODULE_GetEntryPoint( hModule, ordinal );
1747 dprintf_module(stddeb,"WIN32_GetProcAddress16: returning %08x\n",(UINT32)ret);
1748 return ret;
1751 /***********************************************************************
1752 * GetProcAddress16 (KERNEL.50)
1754 FARPROC16 WINAPI GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1756 WORD ordinal;
1757 FARPROC16 ret;
1759 if (!hModule) hModule = GetCurrentTask();
1760 hModule = MODULE_HANDLEtoHMODULE16( hModule );
1762 if (HIWORD(name) != 0)
1764 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1765 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1766 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1768 else
1770 ordinal = LOWORD(name);
1771 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1772 hModule, ordinal );
1774 if (!ordinal) return (FARPROC16)0;
1776 ret = MODULE_GetEntryPoint( hModule, ordinal );
1778 dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1779 return ret;
1783 /***********************************************************************
1784 * GetProcAddress32 (KERNEL32.257)
1786 FARPROC32 WINAPI GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1788 NE_MODULE *pModule;
1790 if (HIWORD(function))
1791 dprintf_win32(stddeb,"GetProcAddress32(%08lx,%s)\n",(DWORD)hModule,function);
1792 else
1793 dprintf_win32(stddeb,"GetProcAddress32(%08lx,%p)\n",(DWORD)hModule,function);
1794 if (!(pModule = MODULE_GetPtr( hModule )))
1795 return (FARPROC32)0;
1796 if (!pModule->module32)
1798 fprintf(stderr,"Oops, Module 0x%08lx has got no module32?\n",
1799 (DWORD)MODULE_HANDLEtoHMODULE32(hModule)
1801 return (FARPROC32)0;
1803 return PE_FindExportedFunction( PROCESS_Current(), pModule->module32,
1804 function );
1807 /***********************************************************************
1808 * RtlImageNtHeaders (NTDLL)
1810 LPIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE32 hModule)
1812 /* basically:
1813 * return hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew);
1814 * but we could get HMODULE16 or the like (think builtin modules)
1817 NE_MODULE *pModule;
1819 if (!(pModule = MODULE_GetPtr( hModule )))
1820 return (LPIMAGE_NT_HEADERS)0;
1821 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->module32)
1822 return (LPIMAGE_NT_HEADERS)0;
1823 return PE_HEADER(pModule->module32);
1827 /**********************************************************************
1828 * GetExpWinVer (KERNEL.167)
1830 WORD WINAPI GetExpWinVer( HMODULE16 hModule )
1832 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1833 return pModule ? pModule->expected_version : 0;
1837 /**********************************************************************
1838 * IsSharedSelector (KERNEL.345)
1840 BOOL16 WINAPI IsSharedSelector( HANDLE16 selector )
1842 /* Check whether the selector belongs to a DLL */
1843 NE_MODULE *pModule = MODULE_GetPtr( selector );
1844 if (!pModule) return FALSE;
1845 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1849 /**********************************************************************
1850 * ModuleFirst (TOOLHELP.59)
1852 BOOL16 WINAPI ModuleFirst( MODULEENTRY *lpme )
1854 lpme->wNext = hFirstModule;
1855 return ModuleNext( lpme );
1859 /**********************************************************************
1860 * ModuleNext (TOOLHELP.60)
1862 BOOL16 WINAPI ModuleNext( MODULEENTRY *lpme )
1864 NE_MODULE *pModule;
1865 char *name;
1867 if (!lpme->wNext) return FALSE;
1868 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1869 name = (char *)pModule + pModule->name_table;
1870 memcpy( lpme->szModule, name + 1, *name );
1871 lpme->szModule[(BYTE)*name] = '\0';
1872 lpme->hModule = lpme->wNext;
1873 lpme->wcUsage = pModule->count;
1874 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1875 lpme->szExePath[MAX_PATH] = '\0';
1876 lpme->wNext = pModule->next;
1877 return TRUE;
1881 /**********************************************************************
1882 * ModuleFindName (TOOLHELP.61)
1884 BOOL16 WINAPI ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1886 lpme->wNext = GetModuleHandle16( name );
1887 return ModuleNext( lpme );
1891 /**********************************************************************
1892 * ModuleFindHandle (TOOLHELP.62)
1894 BOOL16 WINAPI ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1896 hModule = MODULE_HANDLEtoHMODULE16( hModule );
1897 lpme->wNext = hModule;
1898 return ModuleNext( lpme );