4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
21 #include "stackframe.h"
30 static HMODULE hFirstModule = 0;
31 static HMODULE hCachedModule = 0; /* Module cached by MODULE_OpenFile */
34 static HANDLE hInitialStack32 = 0;
36 /***********************************************************************
39 * Load a built-in module. If the 'force' parameter is FALSE, we only
40 * load the module if it has not been disabled via the -dll option.
43 static HMODULE MODULE_LoadBuiltin( LPCSTR name, BOOL force )
47 SEGTABLEENTRY *pSegTable;
48 struct dll_table_s *table;
52 /* Fix the name in case we have a full path and extension */
54 if ((p = strrchr( name, '\\' ))) name = p + 1;
55 strncpy( dllname, name, 15 );
57 if ((p = strrchr( dllname, '.' ))) *p = '\0';
59 for (i = 0, table = dll_builtin_table; i < N_BUILTINS; i++, table++)
60 if (!lstrcmpi( table->name, dllname )) break;
61 if (i >= N_BUILTINS) return 0;
62 if (!table->used && !force) return 0;
64 hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, table->module_start,
65 table->module_end - table->module_start,
66 0, FALSE, FALSE, FALSE, NULL );
67 if (!hModule) return 0;
68 FarSetOwner( hModule, hModule );
70 table->hModule = hModule;
72 dprintf_module( stddeb, "Built-in %s: hmodule=%04x\n",
73 table->name, hModule );
75 /* Allocate the code segment */
77 pModule = (NE_MODULE *)GlobalLock( hModule );
78 pSegTable = NE_SEG_TABLE( pModule );
80 pSegTable->selector = GLOBAL_CreateBlock( GMEM_FIXED, table->code_start,
81 pSegTable->minsize, hModule,
82 TRUE, TRUE, FALSE, NULL );
83 if (!pSegTable->selector) return 0;
86 /* Allocate the data segment */
88 pSegTable->selector = GLOBAL_Alloc( GMEM_FIXED, pSegTable->minsize,
89 hModule, FALSE, FALSE, FALSE );
90 if (!pSegTable->selector) return 0;
91 memcpy( GlobalLock( pSegTable->selector ),
92 table->data_start, pSegTable->minsize );
94 pModule->next = hFirstModule;
95 hFirstModule = hModule;
100 /***********************************************************************
103 * Create the built-in modules.
105 BOOL MODULE_Init(void)
107 /* For these, built-in modules are always used */
110 if (!MODULE_LoadBuiltin( "KERNEL", TRUE ) ||
111 !MODULE_LoadBuiltin( "GDI", TRUE ) ||
112 !MODULE_LoadBuiltin( "USER", TRUE ) ||
113 !MODULE_LoadBuiltin( "WINPROCS", TRUE )) return FALSE;
115 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
117 MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
122 /***********************************************************************
125 void MODULE_PrintModule( HMODULE hmodule )
131 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hmodule );
133 /* Dump the module info */
135 printf( "Module "NPFMT":\n", hmodule );
136 printf( "count=%d flags=%04x heap=%d stack=%d\n",
137 pModule->count, pModule->flags,
138 pModule->heap_size, pModule->stack_size );
139 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
140 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
141 pModule->seg_count, pModule->modref_count );
142 printf( "os_flags=%d swap_area=%d version=%04x\n",
143 pModule->os_flags, pModule->min_swap_area,
144 pModule->expected_version );
146 /* Dump the file info */
148 printf( "Filename: '%s'\n",
149 ((LOADEDFILEINFO *)((BYTE *)pModule + pModule->fileinfo))->filename );
151 /* Dump the segment table */
153 printf( "\nSegment table:\n" );
154 pSeg = NE_SEG_TABLE( pModule );
155 for (i = 0; i < pModule->seg_count; i++, pSeg++)
156 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel="NPFMT"\n",
157 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
158 pSeg->minsize, pSeg->selector );
160 /* Dump the resource table */
162 printf( "\nResource table:\n" );
163 if (pModule->res_table)
165 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
166 printf( "Alignment: %d\n", *pword++ );
169 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
170 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
171 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
172 for (i = 0; i < ptr->count; i++, pname++)
173 printf( "offset=%d len=%d id=%04x\n",
174 pname->offset, pname->length, pname->id );
175 pword = (WORD *)pname;
178 else printf( "None\n" );
180 /* Dump the resident name table */
182 printf( "\nResident-name table:\n" );
183 pstr = (char *)pModule + pModule->name_table;
186 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
187 *(WORD *)(pstr + *pstr + 1) );
188 pstr += *pstr + 1 + sizeof(WORD);
191 /* Dump the module reference table */
193 printf( "\nModule ref table:\n" );
194 if (pModule->modref_table)
196 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
197 for (i = 0; i < pModule->modref_count; i++, pword++)
199 char *name = (char *)pModule + pModule->import_table + *pword;
200 printf( "%d: %04x -> '%*.*s'\n",
201 i, *pword, *name, *name, name + 1 );
204 else printf( "None\n" );
206 /* Dump the entry table */
208 printf( "\nEntry table:\n" );
209 pstr = (char *)pModule + pModule->entry_table;
213 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
219 else if ((BYTE)pstr[1] == 0xff) /* moveable */
221 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
222 for (i = 0; i < *pstr; i++, pe++)
223 printf( "%d: %02x:%04x (moveable)\n",
224 ordinal++, pe->seg_number, pe->offset );
229 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
230 for (i = 0; i < *pstr; i++, pe++)
231 printf( "%d: %04x (fixed)\n",
232 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
237 /* Dump the non-resident names table */
239 printf( "\nNon-resident names table:\n" );
240 if (pModule->nrname_handle)
242 pstr = (char *)GlobalLock( pModule->nrname_handle );
245 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
246 *(WORD *)(pstr + *pstr + 1) );
247 pstr += *pstr + 1 + sizeof(WORD);
254 /***********************************************************************
257 int MODULE_OpenFile( HMODULE hModule )
261 const char *unixName;
263 static int cachedfd = -1;
265 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
266 dprintf_module( stddeb, "MODULE_OpenFile("NPFMT") cache: mod="NPFMT" fd=%d\n",
267 hModule, hCachedModule, cachedfd );
268 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return -1;
269 if (hCachedModule == hModule) return cachedfd;
271 hCachedModule = hModule;
272 name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
273 if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
274 (cachedfd = open( unixName, O_RDONLY )) == -1)
275 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module "NPFMT"\n",
277 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
283 /***********************************************************************
286 * This function translates NE segment flags to GlobalAlloc flags
288 static WORD MODULE_Ne2MemFlags(WORD flags)
292 if (flags & NE_SEGFLAGS_DISCARDABLE)
293 memflags |= GMEM_DISCARDABLE;
294 if (flags & NE_SEGFLAGS_MOVEABLE ||
295 ( ! (flags & NE_SEGFLAGS_DATA) &&
296 ! (flags & NE_SEGFLAGS_LOADED) &&
297 ! (flags & NE_SEGFLAGS_ALLOCATED)
300 memflags |= GMEM_MOVEABLE;
301 memflags |= GMEM_ZEROINIT;
303 memflags = GMEM_ZEROINIT | GMEM_FIXED;
308 /***********************************************************************
309 * MODULE_AllocateSegment (WINPROCS.26)
312 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
314 WORD size = wSize << wElem;
315 HANDLE hMem = GlobalAlloc( MODULE_Ne2MemFlags(wFlags), size);
317 return (DWORD)GlobalLock(hMem);
319 WORD selector = HIWORD(GlobalLock(hMem));
320 return MAKELONG(hMem, selector);
324 /***********************************************************************
325 * MODULE_CreateSegments
328 static BOOL MODULE_CreateSegments( HMODULE hModule )
330 SEGTABLEENTRY *pSegment;
334 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
335 pSegment = NE_SEG_TABLE( pModule );
336 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
338 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
339 if (i == pModule->ss) minsize += pModule->stack_size;
340 /* The DGROUP is allocated by MODULE_CreateInstance */
341 if (i == pModule->dgroup) continue;
342 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
344 !(pSegment->flags & NE_SEGFLAGS_DATA),
346 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
347 if (!pSegment->selector) return FALSE;
350 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
351 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
357 /***********************************************************************
361 static HINSTANCE MODULE_GetInstance( HMODULE hModule )
363 SEGTABLEENTRY *pSegment;
366 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
367 if (pModule->dgroup == 0) return hModule;
369 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
371 return pSegment->selector;
376 /***********************************************************************
377 * MODULE_CreateInstance
379 HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
381 SEGTABLEENTRY *pSegment;
384 HINSTANCE hNewInstance, hPrevInstance;
386 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
387 if (pModule->dgroup == 0) return hModule;
389 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
390 hPrevInstance = pSegment->selector;
392 /* if it's a library, create a new instance only the first time */
395 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
396 if (params == (LOADPARAMS*)-1) return hPrevInstance;
399 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
400 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
401 minsize += pModule->heap_size;
402 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
403 minsize, hModule, FALSE, FALSE, FALSE );
404 if (!hNewInstance) return 0;
405 pSegment->selector = hNewInstance;
410 /***********************************************************************
411 * MODULE_LoadExeHeader
413 HMODULE MODULE_LoadExeHeader( int fd, OFSTRUCT *ofs )
415 struct mz_header_s mz_header;
416 struct ne_header_s ne_header;
421 char *buffer, *fastload = NULL;
422 int fastload_offset = 0, fastload_length = 0;
424 /* Read a block from either the file or the fast-load area. */
425 #define READ(offset,size,buffer) \
426 ((fastload && ((offset) >= fastload_offset) && \
427 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
428 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
429 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
430 read( fd, (buffer), (size) ) == (size)))
432 lseek( fd, 0, SEEK_SET );
433 if ((read( fd, &mz_header, sizeof(mz_header) ) != sizeof(mz_header)) ||
434 (mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11; /* invalid exe */
436 lseek( fd, mz_header.ne_offset, SEEK_SET );
437 if (read( fd, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
438 return (HMODULE)11; /* invalid exe */
440 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21; /* win32 exe */
441 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE)11; /* invalid exe */
443 /* We now have a valid NE header */
445 size = sizeof(NE_MODULE) +
446 /* loaded file info */
447 sizeof(LOADEDFILEINFO) + strlen(ofs->szPathName) +
449 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
451 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
452 /* resident names table */
453 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
454 /* module ref table */
455 ne_header.n_mod_ref_tab * sizeof(WORD) +
456 /* imported names table */
457 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
458 /* entry table length */
459 ne_header.entry_tab_length;
461 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
462 if (!hModule) return (HMODULE)11; /* invalid exe */
463 FarSetOwner( hModule, (WORD)(DWORD)hModule );
464 pModule = (NE_MODULE *)GlobalLock( hModule );
465 memcpy( pModule, &ne_header, sizeof(NE_MODULE) );
467 pData = (BYTE *)(pModule + 1);
469 /* Read the fast-load area */
471 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
473 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
474 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
475 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
476 fastload_offset, fastload_length );
477 if ((fastload = (char *)malloc( fastload_length )) != NULL)
479 lseek( fd, mz_header.ne_offset + fastload_offset, SEEK_SET );
480 if (read( fd, fastload, fastload_length ) != fastload_length)
488 /* Store the filename information */
490 pModule->fileinfo = (int)pData - (int)pModule;
491 ((LOADEDFILEINFO*)pData)->length = sizeof(LOADEDFILEINFO)+strlen(ofs->szPathName);
492 ((LOADEDFILEINFO*)pData)->fixed_media = TRUE;
493 ((LOADEDFILEINFO*)pData)->error = 0;
494 ((LOADEDFILEINFO*)pData)->date = 0;
495 ((LOADEDFILEINFO*)pData)->time = 0;
496 strcpy( ((LOADEDFILEINFO*)pData)->filename, ofs->szPathName );
497 pData += ((LOADEDFILEINFO*)pData)->length--;
499 /* Get the segment table */
501 pModule->seg_table = (int)pData - (int)pModule;
502 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
506 struct ne_segment_table_entry_s *pSeg;
508 if (!READ( ne_header.segment_tab_offset,
509 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
510 buffer )) return (HMODULE)11; /* invalid exe */
511 pSeg = (struct ne_segment_table_entry_s *)buffer;
512 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
514 memcpy( pData, pSeg, sizeof(*pSeg) );
515 pData += sizeof(SEGTABLEENTRY);
519 else return (HMODULE)11; /* invalid exe */
521 /* Get the resource table */
523 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
525 pModule->res_table = (int)pData - (int)pModule;
526 if (!READ(ne_header.resource_tab_offset,
527 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
528 pData )) return (HMODULE)11; /* invalid exe */
529 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
531 else pModule->res_table = 0; /* No resource table */
533 /* Get the resident names table */
535 pModule->name_table = (int)pData - (int)pModule;
536 if (!READ( ne_header.rname_tab_offset,
537 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
538 pData )) return (HMODULE)11; /* invalid exe */
539 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
541 /* Get the module references table */
543 if (ne_header.n_mod_ref_tab > 0)
545 pModule->modref_table = (int)pData - (int)pModule;
546 if (!READ( ne_header.moduleref_tab_offset,
547 ne_header.n_mod_ref_tab * sizeof(WORD),
548 pData )) return (HMODULE)11; /* invalid exe */
549 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
551 else pModule->modref_table = 0; /* No module references */
553 /* Get the imported names table */
555 pModule->import_table = (int)pData - (int)pModule;
556 if (!READ( ne_header.iname_tab_offset,
557 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
558 pData )) return (HMODULE)11; /* invalid exe */
559 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
561 /* Get the entry table */
563 pModule->entry_table = (int)pData - (int)pModule;
564 if (!READ( ne_header.entry_tab_offset,
565 ne_header.entry_tab_length,
566 pData )) return (HMODULE)11; /* invalid exe */
567 pData += ne_header.entry_tab_length;
569 /* Get the non-resident names table */
571 if (ne_header.nrname_tab_length)
573 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
574 hModule, FALSE, FALSE, FALSE );
575 if (!pModule->nrname_handle) return (HMODULE)11; /* invalid exe */
576 buffer = GlobalLock( pModule->nrname_handle );
577 lseek( fd, ne_header.nrname_tab_offset, SEEK_SET );
578 if (read( fd, buffer, ne_header.nrname_tab_length )
579 != ne_header.nrname_tab_length) return (HMODULE)11; /* invalid exe */
581 else pModule->nrname_handle = 0;
583 /* Allocate a segment for the implicitly-loaded DLLs */
585 if (pModule->modref_count)
587 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
588 (pModule->modref_count+1)*sizeof(HMODULE),
589 hModule, FALSE, FALSE, FALSE );
590 if (!pModule->dlls_to_init) return (HMODULE)11; /* invalid exe */
592 else pModule->dlls_to_init = 0;
594 if (debugging_module) MODULE_PrintModule( hModule );
595 pModule->next = hFirstModule;
596 hFirstModule = hModule;
601 /***********************************************************************
604 * Lookup the ordinal for a given name.
606 WORD MODULE_GetOrdinal( HMODULE hModule, char *name )
608 char buffer[256], *cpnt;
612 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
614 dprintf_module( stddeb, "MODULE_GetOrdinal("NPFMT",'%s')\n",
617 /* First handle names of the form '#xxxx' */
619 if (name[0] == '#') return atoi( name + 1 );
621 /* Now copy and uppercase the string */
623 strcpy( buffer, name );
625 len = strlen( buffer );
627 /* First search the resident names */
629 cpnt = (char *)pModule + pModule->name_table;
631 /* Skip the first entry (module name) */
632 cpnt += *cpnt + 1 + sizeof(WORD);
635 dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
636 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
638 dprintf_module( stddeb, " Found: ordinal=%d\n",
639 *(WORD *)(cpnt + *cpnt + 1) );
640 return *(WORD *)(cpnt + *cpnt + 1);
642 cpnt += *cpnt + 1 + sizeof(WORD);
645 /* Now search the non-resident names table */
647 if (!pModule->nrname_handle) return 0; /* No non-resident table */
648 cpnt = (char *)GlobalLock( pModule->nrname_handle );
650 /* Skip the first entry (module description string) */
651 cpnt += *cpnt + 1 + sizeof(WORD);
654 dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
655 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
657 dprintf_module( stddeb, " Found: ordinal=%d\n",
658 *(WORD *)(cpnt + *cpnt + 1) );
659 return *(WORD *)(cpnt + *cpnt + 1);
661 cpnt += *cpnt + 1 + sizeof(WORD);
667 /***********************************************************************
668 * MODULE_GetEntryPoint
670 * Return the entry point for a given ordinal.
672 SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
679 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
681 p = (BYTE *)pModule + pModule->entry_table;
682 while (*p && (curOrdinal + *p <= ordinal))
684 /* Skipping this bundle */
688 case 0: p += 2; break; /* unused */
689 case 0xff: p += 2 + *p * 6; break; /* moveable */
690 default: p += 2 + *p * 3; break; /* fixed */
699 case 0xff: /* moveable */
700 p += 2 + 6 * (ordinal - curOrdinal);
702 offset = *(WORD *)(p + 4);
706 p += 2 + 3 * (ordinal - curOrdinal);
707 offset = *(WORD *)(p + 1);
711 if (sel == 0xfe) sel = 0xffff; /* constant entry */
712 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
713 return (SEGPTR)MAKELONG( offset, sel );
717 /***********************************************************************
718 * MODULE_SetEntryPoint
720 * Change the value of an entry point. Use with caution!
721 * It can only change the offset value, not the selector.
723 BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset )
729 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
731 p = (BYTE *)pModule + pModule->entry_table;
732 while (*p && (curOrdinal + *p <= ordinal))
734 /* Skipping this bundle */
738 case 0: p += 2; break; /* unused */
739 case 0xff: p += 2 + *p * 6; break; /* moveable */
740 default: p += 2 + *p * 3; break; /* fixed */
743 if (!*p) return FALSE;
749 case 0xff: /* moveable */
750 p += 2 + 6 * (ordinal - curOrdinal);
751 *(WORD *)(p + 4) = offset;
754 p += 2 + 3 * (ordinal - curOrdinal);
755 *(WORD *)(p + 1) = offset;
762 /***********************************************************************
763 * MODULE_GetEntryPointName
765 * Return the entry point name for a given ordinal.
766 * Used only by relay debugging.
767 * Warning: returned pointer is to a Pascal-type string.
769 LPSTR MODULE_GetEntryPointName( HMODULE hModule, WORD ordinal )
774 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
776 /* First search the resident names */
778 cpnt = (char *)pModule + pModule->name_table;
781 cpnt += *cpnt + 1 + sizeof(WORD);
782 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
785 /* Now search the non-resident names table */
787 if (!pModule->nrname_handle) return 0; /* No non-resident table */
788 cpnt = (char *)GlobalLock( pModule->nrname_handle );
791 cpnt += *cpnt + 1 + sizeof(WORD);
792 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
798 /***********************************************************************
799 * MODULE_GetModuleName
801 LPSTR MODULE_GetModuleName( HMODULE hModule )
805 static char buffer[10];
807 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return NULL;
808 p = (BYTE *)pModule + pModule->name_table;
810 memcpy( buffer, p + 1, len );
816 /**********************************************************************
817 * MODULE_RegisterModule
819 void MODULE_RegisterModule( HMODULE hModule )
822 pModule = (NE_MODULE *)GlobalLock( hModule );
823 pModule->next = hFirstModule;
824 hFirstModule = hModule;
827 /**********************************************************************
830 * Find a module from a path name.
832 HMODULE MODULE_FindModule( LPCSTR path )
834 HMODULE hModule = hFirstModule;
835 LPCSTR filename, dotptr, modulepath, modulename;
836 BYTE len, *name_table;
838 if (!(filename = strrchr( path, '\\' ))) filename = path;
840 if ((dotptr = strrchr( filename, '.' )) != NULL)
841 len = (BYTE)(dotptr - filename);
842 else len = strlen( filename );
846 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
848 modulepath = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
849 if (!(modulename = strrchr( modulepath, '\\' )))
850 modulename = modulepath;
852 if (!lstrcmpi( modulename, filename )) return hModule;
854 name_table = (BYTE *)pModule + pModule->name_table;
855 if ((*name_table == len) && !lstrncmpi(filename, name_table+1, len))
857 hModule = pModule->next;
863 /**********************************************************************
866 * Remove a module from memory.
868 static void MODULE_FreeModule( HMODULE hModule )
870 HMODULE *hPrevModule;
872 SEGTABLEENTRY *pSegment;
876 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return;
877 if (pModule->flags & NE_FFLAGS_BUILTIN)
878 return; /* Can't free built-in module */
880 /* FIXME: should call the exit code for the library here */
882 /* Remove it from the linked list */
884 hPrevModule = &hFirstModule;
885 while (*hPrevModule && (*hPrevModule != hModule))
887 hPrevModule = &((NE_MODULE *)GlobalLock( *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 GlobalFree( 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) GlobalFree( pModule->nrname_handle );
910 if (pModule->dlls_to_init) GlobalFree( pModule->dlls_to_init );
911 GlobalFree( hModule );
913 /* Remove module from cache */
915 if (hCachedModule == hModule) hCachedModule = 0;
919 HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params);
921 /**********************************************************************
922 * LoadModule (KERNEL.45)
924 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
927 HANDLE hInstance, hPrevInstance;
929 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
931 WORD *pModRef, *pDLLs;
934 hModule = MODULE_FindModule( name );
936 if (!hModule) /* We have to load the module */
940 /* Try to load the built-in first if not disabled */
941 if ((hModule = MODULE_LoadBuiltin( name, FALSE ))) return hModule;
943 if ((fd = FILE_OpenFile( name, &ofs, OF_READ )) == -1)
945 /* Now try the built-in even if disabled */
946 if ((hModule = MODULE_LoadBuiltin( name, TRUE )))
948 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
951 return 2; /* File not found */
954 /* Create the module structure */
956 hModule = MODULE_LoadExeHeader( fd, &ofs );
959 if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
962 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
967 pModule = (NE_MODULE *)GlobalLock( hModule );
969 /* Allocate the segments for this module */
971 MODULE_CreateSegments( hModule );
974 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
976 /* Load the referenced DLLs */
978 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
979 pDLLs = (WORD *)GlobalLock( pModule->dlls_to_init );
980 for (i = 0; i < pModule->modref_count; i++, pModRef++)
983 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
984 memcpy( buffer, pstr + 1, *pstr );
985 strcpy( buffer + *pstr, ".dll" );
986 dprintf_module( stddeb, "Loading '%s'\n", buffer );
987 if (!(*pModRef = MODULE_FindModule( buffer )))
989 /* If the DLL is not loaded yet, load it and store */
990 /* its handle in the list of DLLs to initialize. */
993 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
997 /* Try with prepending the path of the current module */
998 GetModuleFileName( hModule, buffer, 256 );
999 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1000 memcpy( p + 1, pstr + 1, *pstr );
1001 strcpy( p + 1 + *pstr, ".dll" );
1002 hDLL = LoadModule( buffer, (LPVOID)-1 );
1006 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1007 buffer, name, hDLL );
1008 return 2; /* file not found */
1010 *pModRef = GetExePtr( hDLL );
1011 *pDLLs++ = *pModRef;
1013 else /* Increment the reference count of the DLL */
1015 NE_MODULE *pOldDLL = (NE_MODULE *)GlobalLock( *pModRef );
1016 if (pOldDLL) pOldDLL->count++;
1020 /* Load the segments */
1022 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1024 /* Handle self loading modules */
1025 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1026 SELFLOADHEADER *selfloadheader;
1027 HMODULE hselfload = GetModuleHandle("WINPROCS");
1028 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1029 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1030 "Support for self-loading modules is very experimental\n",
1031 *((BYTE*)pModule + pModule->name_table),
1032 *((BYTE*)pModule + pModule->name_table),
1033 (char *)pModule + pModule->name_table + 1);
1034 NE_LoadSegment( hModule, 1 );
1035 selfloadheader = (SELFLOADHEADER *)
1036 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1037 selfloadheader->EntryAddrProc =
1038 MODULE_GetEntryPoint(hselfload,27);
1039 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1040 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1041 pModule->self_loading_sel = GlobalHandleToSel(
1042 GLOBAL_Alloc (GMEM_ZEROINIT,
1043 0xFF00, hModule, FALSE, FALSE, FALSE)
1045 oldss = IF1632_Saved16_ss;
1046 oldsp = IF1632_Saved16_sp;
1047 IF1632_Saved16_ss = pModule->self_loading_sel;
1048 IF1632_Saved16_sp = 0xFF00;
1049 if (!IF1632_Stack32_base) {
1050 STACK32FRAME* frame32;
1052 /* Setup an initial 32 bit stack frame */
1053 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1054 hModule, FALSE, FALSE,
1057 /* Create the 32-bit stack frame */
1059 *(DWORD *)GlobalLock(hInitialStack32) = 0xDEADBEEF;
1060 stack32Top = (char*)GlobalLock(hInitialStack32) +
1062 frame32 = (STACK32FRAME *)stack32Top - 1;
1063 frame32->saved_esp = (DWORD)stack32Top;
1070 frame32->retaddr = 0;
1071 frame32->codeselector = WINE_CODE_SELECTOR;
1072 /* pTask->esp = (DWORD)frame32; */
1073 IF1632_Stack32_base = WIN16_GlobalLock(hInitialStack32);
1076 CallTo16_word_ww (selfloadheader->BootApp,
1077 pModule->self_loading_sel, hModule, fd);
1078 /* some BootApp procs overwrite the selector of dgroup */
1079 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1080 IF1632_Saved16_ss = oldss;
1081 IF1632_Saved16_sp = oldsp;
1082 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1083 if (hInitialStack32){
1084 GlobalUnlock (hInitialStack32);
1085 GlobalFree (hInitialStack32);
1086 IF1632_Stack32_base = hInitialStack32 = 0;
1091 for (i = 1; i <= pModule->seg_count; i++)
1092 NE_LoadSegment( hModule, i );
1095 /* Fixup the functions prologs */
1097 NE_FixupPrologs( hModule );
1099 /* Make sure the usage count is 1 on the first loading of */
1100 /* the module, even if it contains circular DLL references */
1104 /* Clear built-in flag in case it was set in the EXE file */
1106 pModule->flags &= ~NE_FFLAGS_BUILTIN;
1110 pModule = (NE_MODULE *)GlobalLock( 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 = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE) );
1119 pModule = (NE_MODULE *)GlobalLock( hModule );
1121 pModule->magic = 0x454e;
1123 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1124 #endif /* WINELIB */
1126 /* Create a task for this instance */
1128 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1130 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1131 params->hEnvironment,
1132 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1133 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1140 /**********************************************************************
1141 * FreeModule (KERNEL.46)
1143 BOOL FreeModule( HANDLE hModule )
1147 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1148 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
1150 dprintf_module( stddeb, "FreeModule: %s count %d\n",
1151 MODULE_GetModuleName(hModule), pModule->count );
1152 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1157 /**********************************************************************
1158 * GetModuleHandle (KERNEL.47)
1160 HMODULE WIN16_GetModuleHandle( SEGPTR name )
1163 if (HIWORD(name) == 0) return GetExePtr( name );
1165 if (HIWORD(name) == 0) return GetExePtr( LOWORD(name) );
1167 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1170 HMODULE GetModuleHandle( LPCSTR name )
1172 return MODULE_FindModule( name );
1176 /**********************************************************************
1177 * GetModuleUsage (KERNEL.48)
1179 int GetModuleUsage( HANDLE hModule )
1183 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1184 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
1185 dprintf_module( stddeb, "GetModuleUsage("NPFMT"): returning %d\n",
1186 hModule, pModule->count );
1187 return pModule->count;
1191 /**********************************************************************
1192 * GetModuleFileName (KERNEL.49)
1194 int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1199 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1200 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
1201 name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
1202 lstrcpyn( lpFileName, name, nSize );
1203 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1204 return strlen(lpFileName);
1208 /***********************************************************************
1209 * LoadLibrary (KERNEL.95)
1211 HANDLE LoadLibrary( LPCSTR libname )
1214 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1215 WINELIB_UNIMP("LoadLibrary()");
1220 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1222 /* This does not increment the module reference count, and will
1223 * therefore cause crashes on FreeLibrary calls.
1224 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1226 handle = LoadModule( libname, (LPVOID)-1 );
1227 if (handle == (HANDLE)2) /* file not found */
1230 lstrcpyn( buffer, libname, 252 );
1231 strcat( buffer, ".dll" );
1232 handle = LoadModule( buffer, (LPVOID)-1 );
1234 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
1240 /***********************************************************************
1241 * FreeLibrary (KERNEL.96)
1243 void FreeLibrary( HANDLE handle )
1245 dprintf_module( stddeb,"FreeLibrary: "NPFMT"\n", handle );
1246 FreeModule( handle );
1250 /***********************************************************************
1251 * WinExec (KERNEL.166)
1253 HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1256 HLOCAL cmdShowHandle, cmdLineHandle;
1259 char *p, *cmdline, filename[256];
1261 if (!(cmdShowHandle = GlobalAlloc( 0, 2 * sizeof(WORD) ))) return 0;
1262 if (!(cmdLineHandle = GlobalAlloc( 0, 256 ))) return 0;
1264 /* Store nCmdShow */
1266 cmdShowPtr = (WORD *)GlobalLock( cmdShowHandle );
1268 cmdShowPtr[1] = nCmdShow;
1270 /* Build the filename and command-line */
1272 cmdline = (char *)GlobalLock( cmdLineHandle );
1273 strncpy( filename, lpCmdLine, 256 );
1274 filename[255] = '\0';
1275 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1278 strncpy( cmdline, p + 1, 128 );
1279 cmdline[127] = '\0';
1281 else cmdline[0] = '\0';
1284 /* Now load the executable file */
1287 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1289 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1291 params.cmdLine = (SEGPTR)WIN16_GlobalLock( cmdLineHandle );
1292 params.showCmd = (SEGPTR)WIN16_GlobalLock( cmdShowHandle );
1293 params.reserved = 0;
1294 handle = LoadModule( filename, ¶ms );
1295 if (handle == (HANDLE)2) /* file not found */
1297 /* Check that the original file name did not have a suffix */
1298 p = strrchr(filename, '.');
1299 if (p && !(strchr(p, '/') || strchr(p, '\\')))
1300 return handle; /* filename already includes a suffix! */
1301 strcat( filename, ".exe" );
1302 handle = LoadModule( filename, ¶ms );
1305 GlobalFree( cmdShowHandle );
1306 GlobalFree( cmdLineHandle );
1309 if (handle < (HANDLE)32) /* Error? */
1312 /* FIXME: Yield never returns!
1313 We may want to run more applications or start the debugger
1314 before calling Yield. If we don't Yield will be called immdiately
1315 after returning. Why is it needed for Word anyway? */
1316 Yield(); /* program is executed immediately ....needed for word */
1323 /***********************************************************************
1324 * GetProcAddress (KERNEL.50)
1326 FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
1331 if (!hModule) hModule = GetCurrentTask();
1332 hModule = GetExePtr( hModule );
1334 if (HIWORD(name) != 0)
1336 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1337 dprintf_module( stddeb, "GetProcAddress: "NPFMT" '%s'\n",
1338 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1342 ordinal = LOWORD(name);
1343 dprintf_module( stddeb, "GetProcAddress: "NPFMT" %04x\n",
1346 if (!ordinal) return (FARPROC)0;
1348 ret = MODULE_GetEntryPoint( hModule, ordinal );
1350 dprintf_module( stddeb, "GetProcAddress: returning "SPFMT"\n", ret );
1351 return (FARPROC)ret;
1355 /**********************************************************************
1356 * GetExpWinVer (KERNEL.167)
1358 WORD GetExpWinVer( HMODULE hModule )
1360 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
1362 return pModule->expected_version;
1366 /***********************************************************************
1367 * GetWndProcEntry16 (not a Windows API function)
1369 * Return an entry point from the WINPROCS dll.
1372 WNDPROC GetWndProcEntry16( char *name )
1375 static HMODULE hModule = 0;
1377 if (!hModule) hModule = GetModuleHandle( "WINPROCS" );
1378 ordinal = MODULE_GetOrdinal( hModule, name );
1379 return MODULE_GetEntryPoint( hModule, ordinal );
1384 /**********************************************************************
1385 * ModuleFirst (TOOLHELP.59)
1387 BOOL ModuleFirst( MODULEENTRY *lpme )
1389 lpme->wNext = hFirstModule;
1390 return ModuleNext( lpme );
1394 /**********************************************************************
1395 * ModuleNext (TOOLHELP.60)
1397 BOOL ModuleNext( MODULEENTRY *lpme )
1401 if (!lpme->wNext) return FALSE;
1402 if (!(pModule = (NE_MODULE *)GlobalLock( lpme->wNext ))) return FALSE;
1403 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1405 lpme->szModule[MAX_MODULE_NAME] = '\0';
1406 lpme->hModule = lpme->wNext;
1407 lpme->wcUsage = pModule->count;
1408 strncpy( lpme->szExePath,
1409 ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename,
1411 lpme->szExePath[MAX_PATH] = '\0';
1412 lpme->wNext = pModule->next;
1417 /**********************************************************************
1418 * ModuleFindName (TOOLHELP.61)
1420 BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1422 lpme->wNext = GetModuleHandle( name );
1423 return ModuleNext( lpme );
1427 /**********************************************************************
1428 * ModuleFindHandle (TOOLHELP.62)
1430 BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
1432 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1433 lpme->wNext = hModule;
1434 return ModuleNext( lpme );