4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
22 #include "stackframe.h"
31 extern HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
33 static HMODULE hFirstModule = 0;
34 static HMODULE hCachedModule = 0; /* Module cached by MODULE_OpenFile */
37 static HANDLE hInitialStack32 = 0;
41 /***********************************************************************
44 NE_MODULE *MODULE_GetPtr( HMODULE hModule )
46 NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule );
47 if (!pModule || (pModule->magic != NE_SIGNATURE) ||
48 (pModule->self != hModule)) return NULL;
53 /***********************************************************************
56 void MODULE_DumpModule( HMODULE hmodule )
64 if (!(pModule = MODULE_GetPtr( hmodule )))
66 fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
70 /* Dump the module info */
72 printf( "Module %04x:\n", hmodule );
73 printf( "count=%d flags=%04x heap=%d stack=%d\n",
74 pModule->count, pModule->flags,
75 pModule->heap_size, pModule->stack_size );
76 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
77 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
78 pModule->seg_count, pModule->modref_count );
79 printf( "os_flags=%d swap_area=%d version=%04x\n",
80 pModule->os_flags, pModule->min_swap_area,
81 pModule->expected_version );
82 if (pModule->flags & NE_FFLAGS_WIN32)
83 printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
85 /* Dump the file info */
87 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
89 /* Dump the segment table */
91 printf( "\nSegment table:\n" );
92 pSeg = NE_SEG_TABLE( pModule );
93 for (i = 0; i < pModule->seg_count; i++, pSeg++)
94 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
95 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
96 pSeg->minsize, pSeg->selector );
98 /* Dump the resource table */
100 printf( "\nResource table:\n" );
101 if (pModule->res_table)
103 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
104 printf( "Alignment: %d\n", *pword++ );
107 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
108 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
109 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
110 for (i = 0; i < ptr->count; i++, pname++)
111 printf( "offset=%d len=%d id=%04x\n",
112 pname->offset, pname->length, pname->id );
113 pword = (WORD *)pname;
116 else printf( "None\n" );
118 /* Dump the resident name table */
120 printf( "\nResident-name table:\n" );
121 pstr = (char *)pModule + pModule->name_table;
124 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
125 *(WORD *)(pstr + *pstr + 1) );
126 pstr += *pstr + 1 + sizeof(WORD);
129 /* Dump the module reference table */
131 printf( "\nModule ref table:\n" );
132 if (pModule->modref_table)
134 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
135 for (i = 0; i < pModule->modref_count; i++, pword++)
137 char *name = (char *)pModule + pModule->import_table + *pword;
138 printf( "%d: %04x -> '%*.*s'\n",
139 i, *pword, *name, *name, name + 1 );
142 else printf( "None\n" );
144 /* Dump the entry table */
146 printf( "\nEntry table:\n" );
147 pstr = (char *)pModule + pModule->entry_table;
151 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
157 else if ((BYTE)pstr[1] == 0xff) /* moveable */
159 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
160 for (i = 0; i < *pstr; i++, pe++)
161 printf( "%d: %02x:%04x (moveable)\n",
162 ordinal++, pe->seg_number, pe->offset );
167 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
168 for (i = 0; i < *pstr; i++, pe++)
169 printf( "%d: %04x (fixed)\n",
170 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
175 /* Dump the non-resident names table */
177 printf( "\nNon-resident names table:\n" );
178 if (pModule->nrname_handle)
180 pstr = (char *)GlobalLock16( pModule->nrname_handle );
183 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
184 *(WORD *)(pstr + *pstr + 1) );
185 pstr += *pstr + 1 + sizeof(WORD);
192 /***********************************************************************
195 * Walk the module list and print the modules.
197 void MODULE_WalkModules(void)
199 HMODULE hModule = hFirstModule;
200 fprintf( stderr, "Module Flags Name\n" );
203 NE_MODULE *pModule = MODULE_GetPtr( hModule );
206 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
209 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
210 *((char *)pModule + pModule->name_table),
211 (char *)pModule + pModule->name_table + 1 );
212 hModule = pModule->next;
217 /***********************************************************************
220 int MODULE_OpenFile( HMODULE hModule )
224 const char *unixName;
226 static int cachedfd = -1;
228 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
229 dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
230 hModule, hCachedModule, cachedfd );
231 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
232 if (hCachedModule == hModule) return cachedfd;
234 hCachedModule = hModule;
235 name = NE_MODULE_NAME( pModule );
236 if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
237 (cachedfd = open( unixName, O_RDONLY )) == -1)
238 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
240 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
246 /***********************************************************************
249 * This function translates NE segment flags to GlobalAlloc flags
251 static WORD MODULE_Ne2MemFlags(WORD flags)
255 if (flags & NE_SEGFLAGS_DISCARDABLE)
256 memflags |= GMEM_DISCARDABLE;
257 if (flags & NE_SEGFLAGS_MOVEABLE ||
258 ( ! (flags & NE_SEGFLAGS_DATA) &&
259 ! (flags & NE_SEGFLAGS_LOADED) &&
260 ! (flags & NE_SEGFLAGS_ALLOCATED)
263 memflags |= GMEM_MOVEABLE;
264 memflags |= GMEM_ZEROINIT;
266 memflags = GMEM_ZEROINIT | GMEM_FIXED;
271 /***********************************************************************
272 * MODULE_AllocateSegment (WPROCS.26)
275 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
277 WORD size = wSize << wElem;
278 HANDLE hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
280 return (DWORD)GlobalLock16(hMem);
282 WORD selector = HIWORD(WIN16_GlobalLock16(hMem));
283 return MAKELONG(hMem, selector);
287 /***********************************************************************
288 * MODULE_CreateSegments
291 static BOOL MODULE_CreateSegments( HMODULE hModule )
293 SEGTABLEENTRY *pSegment;
297 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
298 pSegment = NE_SEG_TABLE( pModule );
299 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
301 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
302 if (i == pModule->ss) minsize += pModule->stack_size;
303 /* The DGROUP is allocated by MODULE_CreateInstance */
304 if (i == pModule->dgroup) continue;
305 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
307 !(pSegment->flags & NE_SEGFLAGS_DATA),
309 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
310 if (!pSegment->selector) return FALSE;
313 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
314 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
320 /***********************************************************************
324 HINSTANCE MODULE_GetInstance( HMODULE hModule )
326 SEGTABLEENTRY *pSegment;
329 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
330 if (pModule->dgroup == 0) return hModule;
332 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
334 return pSegment->selector;
339 /***********************************************************************
340 * MODULE_CreateInstance
342 HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
344 SEGTABLEENTRY *pSegment;
347 HINSTANCE hNewInstance, hPrevInstance;
349 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
350 if (pModule->dgroup == 0) return hModule;
352 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
353 hPrevInstance = pSegment->selector;
355 /* if it's a library, create a new instance only the first time */
358 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
359 if (params == (LOADPARAMS*)-1) return hPrevInstance;
362 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
363 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
364 minsize += pModule->heap_size;
365 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
366 minsize, hModule, FALSE, FALSE, FALSE );
367 if (!hNewInstance) return 0;
368 pSegment->selector = hNewInstance;
373 /***********************************************************************
374 * MODULE_LoadExeHeader
376 static HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
378 struct mz_header_s mz_header;
379 struct ne_header_s ne_header;
384 char *buffer, *fastload = NULL;
385 int fastload_offset = 0, fastload_length = 0;
387 /* Read a block from either the file or the fast-load area. */
388 #define READ(offset,size,buffer) \
389 ((fastload && ((offset) >= fastload_offset) && \
390 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
391 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
392 (_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
393 FILE_Read( hFile, (buffer), (size) ) == (size)))
395 _llseek( hFile, 0, SEEK_SET );
396 if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
397 (mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11; /* invalid exe */
399 _llseek( hFile, mz_header.ne_offset, SEEK_SET );
400 if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
401 return (HMODULE)11; /* invalid exe */
403 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21; /* win32 exe */
404 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE)11; /* invalid exe */
406 /* We now have a valid NE header */
408 size = sizeof(NE_MODULE) +
409 /* loaded file info */
410 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
412 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
414 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
415 /* resident names table */
416 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
417 /* module ref table */
418 ne_header.n_mod_ref_tab * sizeof(WORD) +
419 /* imported names table */
420 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
421 /* entry table length */
422 ne_header.entry_tab_length;
424 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
425 if (!hModule) return (HMODULE)11; /* invalid exe */
426 FarSetOwner( hModule, hModule );
427 pModule = (NE_MODULE *)GlobalLock16( hModule );
428 memcpy( pModule, &ne_header, sizeof(ne_header) );
430 pModule->pe_module = NULL;
431 pModule->self = hModule;
432 pModule->self_loading_sel = 0;
433 pData = (BYTE *)(pModule + 1);
435 /* Clear internal Wine flags in case they are set in the EXE file */
437 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
439 /* Read the fast-load area */
441 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
443 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
444 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
445 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
446 fastload_offset, fastload_length );
447 if ((fastload = (char *)malloc( fastload_length )) != NULL)
449 _llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET );
450 if (FILE_Read( hFile, fastload, fastload_length ) != fastload_length)
458 /* Store the filename information */
460 pModule->fileinfo = (int)pData - (int)pModule;
461 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
462 memcpy( pData, ofs, size );
463 ((OFSTRUCT *)pData)->cBytes = size - 1;
466 /* Get the segment table */
468 pModule->seg_table = (int)pData - (int)pModule;
469 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
473 struct ne_segment_table_entry_s *pSeg;
475 if (!READ( ne_header.segment_tab_offset,
476 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
477 buffer )) return (HMODULE)11; /* invalid exe */
478 pSeg = (struct ne_segment_table_entry_s *)buffer;
479 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
481 memcpy( pData, pSeg, sizeof(*pSeg) );
482 pData += sizeof(SEGTABLEENTRY);
488 GlobalFree16( hModule );
489 return (HMODULE)11; /* invalid exe */
492 /* Get the resource table */
494 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
496 pModule->res_table = (int)pData - (int)pModule;
497 if (!READ(ne_header.resource_tab_offset,
498 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
499 pData )) return (HMODULE)11; /* invalid exe */
500 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
502 else pModule->res_table = 0; /* No resource table */
504 /* Get the resident names table */
506 pModule->name_table = (int)pData - (int)pModule;
507 if (!READ( ne_header.rname_tab_offset,
508 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
511 GlobalFree16( hModule );
512 return (HMODULE)11; /* invalid exe */
514 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
516 /* Get the module references table */
518 if (ne_header.n_mod_ref_tab > 0)
520 pModule->modref_table = (int)pData - (int)pModule;
521 if (!READ( ne_header.moduleref_tab_offset,
522 ne_header.n_mod_ref_tab * sizeof(WORD),
523 pData )) return (HMODULE)11; /* invalid exe */
524 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
526 else pModule->modref_table = 0; /* No module references */
528 /* Get the imported names table */
530 pModule->import_table = (int)pData - (int)pModule;
531 if (!READ( ne_header.iname_tab_offset,
532 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
535 GlobalFree16( hModule );
536 return (HMODULE)11; /* invalid exe */
538 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
540 /* Get the entry table */
542 pModule->entry_table = (int)pData - (int)pModule;
543 if (!READ( ne_header.entry_tab_offset,
544 ne_header.entry_tab_length,
547 GlobalFree16( hModule );
548 return (HMODULE)11; /* invalid exe */
550 pData += ne_header.entry_tab_length;
552 /* Get the non-resident names table */
554 if (ne_header.nrname_tab_length)
556 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
557 hModule, FALSE, FALSE, FALSE );
558 if (!pModule->nrname_handle)
560 GlobalFree16( hModule );
561 return (HMODULE)11; /* invalid exe */
563 buffer = GlobalLock16( pModule->nrname_handle );
564 _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
565 if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length )
566 != ne_header.nrname_tab_length)
568 GlobalFree16( pModule->nrname_handle );
569 GlobalFree16( hModule );
570 return (HMODULE)11; /* invalid exe */
573 else pModule->nrname_handle = 0;
575 /* Allocate a segment for the implicitly-loaded DLLs */
577 if (pModule->modref_count)
579 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
580 (pModule->modref_count+1)*sizeof(HMODULE),
581 hModule, FALSE, FALSE, FALSE );
582 if (!pModule->dlls_to_init)
584 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
585 GlobalFree16( hModule );
586 return (HMODULE)11; /* invalid exe */
589 else pModule->dlls_to_init = 0;
591 MODULE_RegisterModule( pModule );
597 /***********************************************************************
600 * Lookup the ordinal for a given name.
602 WORD MODULE_GetOrdinal( HMODULE hModule, const char *name )
604 char buffer[256], *cpnt;
608 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
610 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
613 /* First handle names of the form '#xxxx' */
615 if (name[0] == '#') return atoi( name + 1 );
617 /* Now copy and uppercase the string */
619 strcpy( buffer, name );
621 len = strlen( buffer );
623 /* First search the resident names */
625 cpnt = (char *)pModule + pModule->name_table;
627 /* Skip the first entry (module name) */
628 cpnt += *cpnt + 1 + sizeof(WORD);
631 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
633 dprintf_module( stddeb, " Found: ordinal=%d\n",
634 *(WORD *)(cpnt + *cpnt + 1) );
635 return *(WORD *)(cpnt + *cpnt + 1);
637 cpnt += *cpnt + 1 + sizeof(WORD);
640 /* Now search the non-resident names table */
642 if (!pModule->nrname_handle) return 0; /* No non-resident table */
643 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
645 /* Skip the first entry (module description string) */
646 cpnt += *cpnt + 1 + sizeof(WORD);
649 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
651 dprintf_module( stddeb, " Found: ordinal=%d\n",
652 *(WORD *)(cpnt + *cpnt + 1) );
653 return *(WORD *)(cpnt + *cpnt + 1);
655 cpnt += *cpnt + 1 + sizeof(WORD);
661 /***********************************************************************
662 * MODULE_GetEntryPoint
664 * Return the entry point for a given ordinal.
666 SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
673 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
675 p = (BYTE *)pModule + pModule->entry_table;
676 while (*p && (curOrdinal + *p <= ordinal))
678 /* Skipping this bundle */
682 case 0: p += 2; break; /* unused */
683 case 0xff: p += 2 + *p * 6; break; /* moveable */
684 default: p += 2 + *p * 3; break; /* fixed */
693 case 0xff: /* moveable */
694 p += 2 + 6 * (ordinal - curOrdinal);
696 offset = *(WORD *)(p + 4);
700 p += 2 + 3 * (ordinal - curOrdinal);
701 offset = *(WORD *)(p + 1);
705 if (sel == 0xfe) sel = 0xffff; /* constant entry */
706 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
707 return PTR_SEG_OFF_TO_SEGPTR( sel, offset );
711 /***********************************************************************
712 * MODULE_SetEntryPoint
714 * Change the value of an entry point. Use with caution!
715 * It can only change the offset value, not the selector.
717 BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset )
723 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
725 p = (BYTE *)pModule + pModule->entry_table;
726 while (*p && (curOrdinal + *p <= ordinal))
728 /* Skipping this bundle */
732 case 0: p += 2; break; /* unused */
733 case 0xff: p += 2 + *p * 6; break; /* moveable */
734 default: p += 2 + *p * 3; break; /* fixed */
737 if (!*p) return FALSE;
743 case 0xff: /* moveable */
744 p += 2 + 6 * (ordinal - curOrdinal);
745 *(WORD *)(p + 4) = offset;
748 p += 2 + 3 * (ordinal - curOrdinal);
749 *(WORD *)(p + 1) = offset;
756 /***********************************************************************
757 * MODULE_GetWndProcEntry16 (not a Windows API function)
759 * Return an entry point from the WPROCS dll.
762 FARPROC16 MODULE_GetWndProcEntry16( const char *name )
765 static HMODULE hModule = 0;
767 if (!hModule) hModule = GetModuleHandle( "WPROCS" );
768 ordinal = MODULE_GetOrdinal( hModule, name );
769 return MODULE_GetEntryPoint( hModule, ordinal );
774 /***********************************************************************
775 * MODULE_GetWndProcEntry32 (not a Windows API function)
777 * Return an entry point from the WPROCS32 dll.
780 FARPROC32 MODULE_GetWndProcEntry32( const char *name )
782 static HMODULE hModule = 0;
784 if (!hModule) hModule = GetModuleHandle( "WPROCS32" );
785 return PE_GetProcAddress( hModule, name );
790 /***********************************************************************
791 * MODULE_GetModuleName
793 LPSTR MODULE_GetModuleName( HMODULE hModule )
797 static char buffer[10];
799 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
800 p = (BYTE *)pModule + pModule->name_table;
802 memcpy( buffer, p + 1, len );
808 /**********************************************************************
809 * MODULE_RegisterModule
811 void MODULE_RegisterModule( NE_MODULE *pModule )
813 pModule->next = hFirstModule;
814 hFirstModule = pModule->self;
818 /**********************************************************************
821 * Find a module from a path name.
823 HMODULE MODULE_FindModule( LPCSTR path )
825 HMODULE hModule = hFirstModule;
826 LPCSTR filename, dotptr, modulepath, modulename;
827 BYTE len, *name_table;
829 if (!(filename = strrchr( path, '\\' ))) filename = path;
831 if ((dotptr = strrchr( filename, '.' )) != NULL)
832 len = (BYTE)(dotptr - filename);
833 else len = strlen( filename );
837 NE_MODULE *pModule = MODULE_GetPtr( hModule );
839 modulepath = NE_MODULE_NAME(pModule);
840 if (!(modulename = strrchr( modulepath, '\\' )))
841 modulename = modulepath;
843 if (!lstrcmpi( modulename, filename )) return hModule;
845 name_table = (BYTE *)pModule + pModule->name_table;
846 if ((*name_table == len) && !lstrncmpi(filename, name_table+1, len))
848 hModule = pModule->next;
854 /**********************************************************************
857 * Remove a module from memory.
859 static void MODULE_FreeModule( HMODULE hModule )
861 HMODULE *hPrevModule;
863 SEGTABLEENTRY *pSegment;
867 if (!(pModule = MODULE_GetPtr( hModule ))) return;
868 if (pModule->flags & NE_FFLAGS_BUILTIN)
869 return; /* Can't free built-in module */
871 /* FIXME: should call the exit code for the library here */
873 /* Free the objects owned by the module */
875 HOOK_FreeModuleHooks( hModule );
876 CLASS_FreeModuleClasses( hModule );
878 /* Clear magic number just in case */
880 pModule->magic = pModule->self = 0;
882 /* Remove it from the linked list */
884 hPrevModule = &hFirstModule;
885 while (*hPrevModule && (*hPrevModule != hModule))
887 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
889 if (*hPrevModule) *hPrevModule = pModule->next;
891 /* Free all the segments */
893 pSegment = NE_SEG_TABLE( pModule );
894 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
896 GlobalFree16( pSegment->selector );
899 /* Free the referenced modules */
901 pModRef = (HMODULE*)NE_MODULE_TABLE( pModule );
902 for (i = 0; i < pModule->modref_count; i++, pModRef++)
904 FreeModule( *pModRef );
907 /* Free the module storage */
909 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
910 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
911 GlobalFree16( hModule );
913 /* Remove module from cache */
915 if (hCachedModule == hModule) hCachedModule = 0;
919 /**********************************************************************
920 * LoadModule (KERNEL.45)
922 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
925 HANDLE hInstance, hPrevInstance;
927 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
929 WORD *pModRef, *pDLLs;
933 hModule = MODULE_FindModule( name );
935 if (!hModule) /* We have to load the module */
939 /* Try to load the built-in first if not disabled */
940 if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
942 if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR)
944 /* Now try the built-in even if disabled */
945 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
947 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
950 return 2; /* File not found */
953 /* Create the module structure */
955 hModule = MODULE_LoadExeHeader( hFile, &ofs );
958 /* FIXME: Hack because PE_LoadModule is recursive */
959 int fd = dup( FILE_GetUnixHandle(hFile) );
961 if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
964 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
969 pModule = MODULE_GetPtr( hModule );
971 /* Allocate the segments for this module */
973 MODULE_CreateSegments( hModule );
976 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
978 /* Load the referenced DLLs */
980 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
981 pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
982 for (i = 0; i < pModule->modref_count; i++, pModRef++)
985 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
986 memcpy( buffer, pstr + 1, *pstr );
987 strcpy( buffer + *pstr, ".dll" );
988 dprintf_module( stddeb, "Loading '%s'\n", buffer );
989 if (!(*pModRef = MODULE_FindModule( buffer )))
991 /* If the DLL is not loaded yet, load it and store */
992 /* its handle in the list of DLLs to initialize. */
995 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
999 /* Try with prepending the path of the current module */
1000 GetModuleFileName( hModule, buffer, 256 );
1001 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1002 memcpy( p + 1, pstr + 1, *pstr );
1003 strcpy( p + 1 + *pstr, ".dll" );
1004 hDLL = LoadModule( buffer, (LPVOID)-1 );
1008 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1009 buffer, name, hDLL );
1010 return 2; /* file not found */
1012 *pModRef = GetExePtr( hDLL );
1013 *pDLLs++ = *pModRef;
1015 else /* Increment the reference count of the DLL */
1017 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
1018 if (pOldDLL) pOldDLL->count++;
1022 /* Load the segments */
1024 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1027 /* Handle self loading modules */
1028 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1029 SELFLOADHEADER *selfloadheader;
1030 HMODULE hselfload = GetModuleHandle("WPROCS");
1031 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1032 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1033 "Support for self-loading modules is very experimental\n",
1034 *((BYTE*)pModule + pModule->name_table),
1035 *((BYTE*)pModule + pModule->name_table),
1036 (char *)pModule + pModule->name_table + 1);
1037 NE_LoadSegment( hModule, 1 );
1038 selfloadheader = (SELFLOADHEADER *)
1039 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1040 selfloadheader->EntryAddrProc =
1041 MODULE_GetEntryPoint(hselfload,27);
1042 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1043 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1044 pModule->self_loading_sel = GlobalHandleToSel(
1045 GLOBAL_Alloc (GMEM_ZEROINIT,
1046 0xFF00, hModule, FALSE, FALSE, FALSE)
1048 oldss = IF1632_Saved16_ss;
1049 oldsp = IF1632_Saved16_sp;
1050 IF1632_Saved16_ss = pModule->self_loading_sel;
1051 IF1632_Saved16_sp = 0xFF00;
1052 if (!IF1632_Stack32_base) {
1053 STACK32FRAME* frame32;
1055 /* Setup an initial 32 bit stack frame */
1056 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1057 hModule, FALSE, FALSE,
1060 /* Create the 32-bit stack frame */
1062 *(DWORD *)GlobalLock16(hInitialStack32) = 0xDEADBEEF;
1063 stack32Top = (char*)GlobalLock16(hInitialStack32) +
1065 frame32 = (STACK32FRAME *)stack32Top - 1;
1066 frame32->saved_esp = (DWORD)stack32Top;
1073 frame32->retaddr = 0;
1074 frame32->codeselector = WINE_CODE_SELECTOR;
1075 /* pTask->esp = (DWORD)frame32; */
1076 IF1632_Stack32_base = WIN16_GlobalLock16(hInitialStack32);
1079 /* FIXME: we probably need a DOS handle here */
1080 fd = MODULE_OpenFile( hModule );
1081 CallTo16_word_ww (selfloadheader->BootApp,
1082 pModule->self_loading_sel, hModule, fd);
1083 /* some BootApp procs overwrite the selector of dgroup */
1084 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1085 IF1632_Saved16_ss = oldss;
1086 IF1632_Saved16_sp = oldsp;
1087 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1088 if (hInitialStack32){
1089 GlobalFree16(hInitialStack32);
1090 IF1632_Stack32_base = hInitialStack32 = 0;
1095 for (i = 1; i <= pModule->seg_count; i++)
1096 NE_LoadSegment( hModule, i );
1099 /* Fixup the functions prologs */
1101 NE_FixupPrologs( pModule );
1103 /* Make sure the usage count is 1 on the first loading of */
1104 /* the module, even if it contains circular DLL references */
1110 pModule = MODULE_GetPtr( hModule );
1111 hPrevInstance = MODULE_GetInstance( hModule );
1112 hInstance = MODULE_CreateInstance( hModule, params );
1113 if (hInstance != hPrevInstance) /* not a library */
1114 NE_LoadSegment( hModule, pModule->dgroup );
1118 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE));
1119 pModule = (NE_MODULE *)GlobalLock16( hModule );
1121 pModule->magic = NE_SIGNATURE;
1122 pModule->self = hModule;
1124 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1125 #endif /* WINELIB */
1127 /* Create a task for this instance */
1129 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1131 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1132 params->hEnvironment,
1133 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1134 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1141 /**********************************************************************
1142 * FreeModule (KERNEL.46)
1144 BOOL FreeModule( HANDLE hModule )
1148 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1149 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1151 dprintf_module( stddeb, "FreeModule: %s count %d\n",
1152 MODULE_GetModuleName(hModule), pModule->count );
1153 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1158 /**********************************************************************
1159 * GetModuleHandle (KERNEL.47)
1161 HMODULE WIN16_GetModuleHandle( SEGPTR name )
1163 if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
1164 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1167 HMODULE GetModuleHandle( LPCSTR name )
1169 return MODULE_FindModule( name );
1173 /**********************************************************************
1174 * GetModuleUsage (KERNEL.48)
1176 int GetModuleUsage( HANDLE hModule )
1180 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1181 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1182 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1183 hModule, pModule->count );
1184 return pModule->count;
1188 /**********************************************************************
1189 * GetModuleFileName (KERNEL.49)
1191 int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1195 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1196 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1197 lstrcpyn( lpFileName, NE_MODULE_NAME(pModule), nSize );
1198 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1199 return strlen(lpFileName);
1203 /***********************************************************************
1204 * LoadLibrary (KERNEL.95)
1206 HANDLE LoadLibrary( LPCSTR libname )
1209 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1210 WINELIB_UNIMP("LoadLibrary()");
1215 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1217 /* This does not increment the module reference count, and will
1218 * therefore cause crashes on FreeLibrary calls.
1219 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1221 handle = LoadModule( libname, (LPVOID)-1 );
1222 if (handle == (HANDLE)2) /* file not found */
1225 lstrcpyn( buffer, libname, 252 );
1226 strcat( buffer, ".dll" );
1227 handle = LoadModule( buffer, (LPVOID)-1 );
1229 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
1235 /***********************************************************************
1236 * FreeLibrary (KERNEL.96)
1238 void FreeLibrary( HANDLE handle )
1240 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1241 FreeModule( handle );
1245 /***********************************************************************
1246 * WinExec (KERNEL.166)
1248 HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1251 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1254 char *p, *cmdline, filename[256];
1255 static int use_load_module = 1;
1257 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) ))) return 0;
1258 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 ))) return 0;
1260 /* Store nCmdShow */
1262 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1264 cmdShowPtr[1] = nCmdShow;
1266 /* Build the filename and command-line */
1268 cmdline = (char *)GlobalLock16( cmdLineHandle );
1269 lstrcpyn( filename, lpCmdLine, sizeof(filename) - 4 /* for extension */ );
1270 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1271 if (*p) lstrcpyn( cmdline, p + 1, 128 );
1272 else cmdline[0] = '\0';
1275 /* Now load the executable file */
1277 if (use_load_module)
1280 /* WINELIB: Use LoadModule() only for the program itself */
1281 use_load_module = 0;
1282 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1284 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1285 #endif /* WINELIB */
1286 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1287 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1288 params.reserved = 0;
1289 handle = LoadModule( filename, ¶ms );
1290 if (handle == 2) /* file not found */
1292 /* Check that the original file name did not have a suffix */
1293 p = strrchr(filename, '.');
1294 if (!p || (strchr(p, '/') && strchr(p, '\\')))
1296 p = filename + strlen(filename);
1297 strcpy( p, ".exe" );
1298 handle = LoadModule( filename, ¶ms );
1299 *p = '\0'; /* Remove extension */
1307 /* Try to start it as a unix program */
1311 const char *unixfilename;
1312 const char *argv[256], **argptr;
1313 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1314 nCmdShow == SW_SHOWMINNOACTIVE);
1316 /* get unixfilename */
1317 if (strchr(filename, '/') ||
1318 strchr(filename, ':') ||
1319 strchr(filename, '\\'))
1320 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1321 else unixfilename = filename;
1327 if (iconic) *argptr++ = "-iconic";
1328 *argptr++ = unixfilename;
1332 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1335 while (*p && *p != ' ' && *p != '\t') p++;
1340 execvp(argv[0], (char**)argv);
1348 if (iconic) *argptr++ = "-iconic";
1349 *argptr++ = lpCmdLine;
1353 execvp(argv[0] , (char**)argv);
1356 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1362 GlobalFree16( cmdShowHandle );
1363 GlobalFree16( cmdLineHandle );
1366 if (handle < (HANDLE)32) /* Error? */
1369 /* FIXME: Yield never returns!
1370 We may want to run more applications or start the debugger
1371 before calling Yield. If we don't Yield will be called immdiately
1372 after returning. Why is it needed for Word anyway? */
1373 Yield(); /* program is executed immediately ....needed for word */
1380 /***********************************************************************
1381 * GetProcAddress (KERNEL.50)
1383 FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
1388 if (!hModule) hModule = GetCurrentTask();
1389 hModule = GetExePtr( hModule );
1391 if (HIWORD(name) != 0)
1393 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1394 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1395 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1399 ordinal = LOWORD(name);
1400 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1403 if (!ordinal) return (FARPROC)0;
1405 ret = MODULE_GetEntryPoint( hModule, ordinal );
1407 dprintf_module( stddeb, "GetProcAddress: returning %08lx\n", (DWORD)ret );
1408 return (FARPROC)ret;
1412 /**********************************************************************
1413 * GetExpWinVer (KERNEL.167)
1415 WORD GetExpWinVer( HMODULE hModule )
1417 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1418 return pModule ? pModule->expected_version : 0;
1422 /**********************************************************************
1423 * ModuleFirst (TOOLHELP.59)
1425 BOOL ModuleFirst( MODULEENTRY *lpme )
1427 lpme->wNext = hFirstModule;
1428 return ModuleNext( lpme );
1432 /**********************************************************************
1433 * ModuleNext (TOOLHELP.60)
1435 BOOL ModuleNext( MODULEENTRY *lpme )
1439 if (!lpme->wNext) return FALSE;
1440 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1441 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1443 lpme->szModule[MAX_MODULE_NAME] = '\0';
1444 lpme->hModule = lpme->wNext;
1445 lpme->wcUsage = pModule->count;
1446 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1447 lpme->szExePath[MAX_PATH] = '\0';
1448 lpme->wNext = pModule->next;
1453 /**********************************************************************
1454 * ModuleFindName (TOOLHELP.61)
1456 BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1458 lpme->wNext = GetModuleHandle( name );
1459 return ModuleNext( lpme );
1463 /**********************************************************************
1464 * ModuleFindHandle (TOOLHELP.62)
1466 BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
1468 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1469 lpme->wNext = hModule;
1470 return ModuleNext( lpme );