4 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
21 #include "selectors.h"
22 #include "stackframe.h"
29 extern HINSTANCE16 PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
31 static HMODULE16 hFirstModule = 0;
32 static HMODULE16 hCachedModule = 0; /* Module cached by MODULE_OpenFile */
35 /***********************************************************************
38 NE_MODULE *MODULE_GetPtr( HMODULE16 hModule )
40 NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule );
41 if (!pModule || (pModule->magic != IMAGE_OS2_SIGNATURE) ||
42 (pModule->self != hModule)) return NULL;
47 /***********************************************************************
50 void MODULE_DumpModule( HMODULE16 hModule )
58 if (!(pModule = MODULE_GetPtr( hModule )))
60 fprintf( stderr, "**** %04x is not a module handle\n", hModule );
64 /* Dump the module info */
66 printf( "Module %04x:\n", hModule );
67 printf( "count=%d flags=%04x heap=%d stack=%d\n",
68 pModule->count, pModule->flags,
69 pModule->heap_size, pModule->stack_size );
70 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
71 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
72 pModule->seg_count, pModule->modref_count );
73 printf( "os_flags=%d swap_area=%d version=%04x\n",
74 pModule->os_flags, pModule->min_swap_area,
75 pModule->expected_version );
76 if (pModule->flags & NE_FFLAGS_WIN32)
77 printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
79 /* Dump the file info */
81 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
83 /* Dump the segment table */
85 printf( "\nSegment table:\n" );
86 pSeg = NE_SEG_TABLE( pModule );
87 for (i = 0; i < pModule->seg_count; i++, pSeg++)
88 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
89 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
90 pSeg->minsize, pSeg->selector );
92 /* Dump the resource table */
94 printf( "\nResource table:\n" );
95 if (pModule->res_table)
97 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
98 printf( "Alignment: %d\n", *pword++ );
101 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
102 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
103 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
104 for (i = 0; i < ptr->count; i++, pname++)
105 printf( "offset=%d len=%d id=%04x\n",
106 pname->offset, pname->length, pname->id );
107 pword = (WORD *)pname;
110 else printf( "None\n" );
112 /* Dump the resident name table */
114 printf( "\nResident-name table:\n" );
115 pstr = (char *)pModule + pModule->name_table;
118 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
119 *(WORD *)(pstr + *pstr + 1) );
120 pstr += *pstr + 1 + sizeof(WORD);
123 /* Dump the module reference table */
125 printf( "\nModule ref table:\n" );
126 if (pModule->modref_table)
128 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
129 for (i = 0; i < pModule->modref_count; i++, pword++)
131 printf( "%d: %04x -> '%s'\n", i, *pword,
132 MODULE_GetModuleName(*pword));
135 else printf( "None\n" );
137 /* Dump the entry table */
139 printf( "\nEntry table:\n" );
140 pstr = (char *)pModule + pModule->entry_table;
144 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
150 else if ((BYTE)pstr[1] == 0xff) /* moveable */
152 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
153 for (i = 0; i < *pstr; i++, pe++)
154 printf( "%d: %02x:%04x (moveable)\n",
155 ordinal++, pe->seg_number, pe->offset );
160 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
161 for (i = 0; i < *pstr; i++, pe++)
162 printf( "%d: %04x (fixed)\n",
163 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
168 /* Dump the non-resident names table */
170 printf( "\nNon-resident names table:\n" );
171 if (pModule->nrname_handle)
173 pstr = (char *)GlobalLock16( pModule->nrname_handle );
176 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
177 *(WORD *)(pstr + *pstr + 1) );
178 pstr += *pstr + 1 + sizeof(WORD);
185 /***********************************************************************
188 * Walk the module list and print the modules.
190 void MODULE_WalkModules(void)
192 HMODULE16 hModule = hFirstModule;
193 fprintf( stderr, "Module Flags Name\n" );
196 NE_MODULE *pModule = MODULE_GetPtr( hModule );
199 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
202 fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
203 *((char *)pModule + pModule->name_table),
204 (char *)pModule + pModule->name_table + 1 );
205 hModule = pModule->next;
210 /***********************************************************************
213 int MODULE_OpenFile( HMODULE16 hModule )
216 DOS_FULL_NAME full_name;
219 static int cachedfd = -1;
221 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
222 dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
223 hModule, hCachedModule, cachedfd );
224 if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
225 if (hCachedModule == hModule) return cachedfd;
227 hCachedModule = hModule;
228 name = NE_MODULE_NAME( pModule );
229 if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
230 (cachedfd = open( full_name.long_name, O_RDONLY )) == -1)
231 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
233 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
239 /***********************************************************************
242 * This function translates NE segment flags to GlobalAlloc flags
244 static WORD MODULE_Ne2MemFlags(WORD flags)
248 if (flags & NE_SEGFLAGS_DISCARDABLE)
249 memflags |= GMEM_DISCARDABLE;
250 if (flags & NE_SEGFLAGS_MOVEABLE ||
251 ( ! (flags & NE_SEGFLAGS_DATA) &&
252 ! (flags & NE_SEGFLAGS_LOADED) &&
253 ! (flags & NE_SEGFLAGS_ALLOCATED)
256 memflags |= GMEM_MOVEABLE;
257 memflags |= GMEM_ZEROINIT;
259 memflags = GMEM_ZEROINIT | GMEM_FIXED;
264 /***********************************************************************
265 * MODULE_AllocateSegment (WPROCS.26)
268 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
270 WORD size = wSize << wElem;
271 HANDLE16 hMem = GlobalAlloc16( MODULE_Ne2MemFlags(wFlags), size);
272 return MAKELONG( hMem, GlobalHandleToSel(hMem) );
275 /***********************************************************************
276 * MODULE_CreateSegments
278 static BOOL32 MODULE_CreateSegments( HMODULE16 hModule )
280 SEGTABLEENTRY *pSegment;
284 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
285 pSegment = NE_SEG_TABLE( pModule );
286 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
288 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
289 if (i == pModule->ss) minsize += pModule->stack_size;
290 /* The DGROUP is allocated by MODULE_CreateInstance */
291 if (i == pModule->dgroup) continue;
292 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
294 !(pSegment->flags & NE_SEGFLAGS_DATA),
296 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
297 if (!pSegment->selector) return FALSE;
300 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
301 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
306 /***********************************************************************
309 HINSTANCE16 MODULE_GetInstance( HMODULE16 hModule )
311 SEGTABLEENTRY *pSegment;
314 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
315 if (pModule->dgroup == 0) return hModule;
317 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
319 return pSegment->selector;
323 /***********************************************************************
324 * MODULE_CreateInstance
326 HINSTANCE16 MODULE_CreateInstance( HMODULE16 hModule, LOADPARAMS *params )
328 SEGTABLEENTRY *pSegment;
331 HINSTANCE16 hNewInstance, hPrevInstance;
333 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
334 if (pModule->dgroup == 0) return hModule;
336 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
337 hPrevInstance = pSegment->selector;
339 /* if it's a library, create a new instance only the first time */
342 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
343 if (params == (LOADPARAMS*)-1) return hPrevInstance;
346 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
347 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
348 minsize += pModule->heap_size;
349 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
350 minsize, hModule, FALSE, FALSE, FALSE );
351 if (!hNewInstance) return 0;
352 pSegment->selector = hNewInstance;
357 /***********************************************************************
358 * MODULE_CreateDummyModule
360 * Create a dummy NE module for Win32 or Winelib.
362 HMODULE16 MODULE_CreateDummyModule( const OFSTRUCT *ofs )
366 SEGTABLEENTRY *pSegment;
367 char *pStr,*basename,*s;
369 INT32 of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
370 + strlen(ofs->szPathName) + 1;
371 INT32 size = sizeof(NE_MODULE) +
372 /* loaded file info */
374 /* segment table: DS,CS */
375 2 * sizeof(SEGTABLEENTRY) +
378 /* several empty tables */
381 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
382 if (!hModule) return (HMODULE16)11; /* invalid exe */
384 FarSetOwner( hModule, hModule );
385 pModule = (NE_MODULE *)GlobalLock16( hModule );
387 /* Set all used entries */
388 pModule->magic = IMAGE_OS2_SIGNATURE;
395 pModule->heap_size = 0xe000;
396 pModule->stack_size = 0x1000;
397 pModule->seg_count = 2;
398 pModule->modref_count = 0;
399 pModule->nrname_size = 0;
400 pModule->fileinfo = sizeof(NE_MODULE);
401 pModule->os_flags = NE_OSFLAGS_WINDOWS;
402 pModule->expected_version = 0x030a;
403 pModule->self = hModule;
405 /* Set loaded file information */
406 memcpy( pModule + 1, ofs, of_size );
407 ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
409 pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
410 pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
413 pSegment->flags = NE_SEGFLAGS_DATA;
414 pSegment->minsize = 0x1000;
421 pStr = (char *)pSegment;
422 pModule->name_table = (int)pStr - (int)pModule;
423 /* strcpy( pStr, "\x08W32SXXXX" ); */
424 basename = strrchr(ofs->szPathName,'\\');
426 basename=ofs->szPathName;
429 basename=strdup(basename);
430 if ((s=strchr(basename,'.')))
432 *pStr = strlen(basename);
433 if (*pStr>8) *pStr=8;
434 strncpy( pStr+1, basename, 8 );
438 /* All tables zero terminated */
439 pModule->res_table = pModule->import_table = pModule->entry_table =
440 (int)pStr - (int)pModule;
442 MODULE_RegisterModule( pModule );
447 /***********************************************************************
448 * MODULE_LoadExeHeader
450 static HMODULE16 MODULE_LoadExeHeader( HFILE32 hFile, OFSTRUCT *ofs )
452 IMAGE_DOS_HEADER mz_header;
453 IMAGE_OS2_HEADER ne_header;
458 char *buffer, *fastload = NULL;
459 int fastload_offset = 0, fastload_length = 0;
461 /* Read a block from either the file or the fast-load area. */
462 #define READ(offset,size,buffer) \
463 ((fastload && ((offset) >= fastload_offset) && \
464 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
465 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
466 (_llseek32( hFile, (offset), SEEK_SET), \
467 _lread32( hFile, (buffer), (size) ) == (size)))
469 _llseek32( hFile, 0, SEEK_SET );
470 if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
471 (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
472 return (HMODULE16)11; /* invalid exe */
474 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
475 if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
476 return (HMODULE16)11; /* invalid exe */
478 if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE16)21; /* win32 exe */
479 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE16)11; /* invalid exe */
481 /* We now have a valid NE header */
483 size = sizeof(NE_MODULE) +
484 /* loaded file info */
485 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
487 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
489 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
490 /* resident names table */
491 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
492 /* module ref table */
493 ne_header.n_mod_ref_tab * sizeof(WORD) +
494 /* imported names table */
495 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
496 /* entry table length */
497 ne_header.entry_tab_length;
499 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
500 if (!hModule) return (HMODULE16)11; /* invalid exe */
501 FarSetOwner( hModule, hModule );
502 pModule = (NE_MODULE *)GlobalLock16( hModule );
503 memcpy( pModule, &ne_header, sizeof(ne_header) );
505 pModule->pe_module = NULL;
506 pModule->self = hModule;
507 pModule->self_loading_sel = 0;
508 pData = (BYTE *)(pModule + 1);
510 /* Clear internal Wine flags in case they are set in the EXE file */
512 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
514 /* Read the fast-load area */
516 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
518 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
519 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
520 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
521 fastload_offset, fastload_length );
522 if ((fastload = HeapAlloc( SystemHeap, 0, fastload_length )) != NULL)
524 _llseek32( hFile, fastload_offset, SEEK_SET);
525 if (_lread32(hFile, fastload, fastload_length) != fastload_length)
527 HeapFree( SystemHeap, 0, fastload );
528 fprintf(stderr, "Error reading fast-load area !\n");
534 /* Store the filename information */
536 pModule->fileinfo = (int)pData - (int)pModule;
537 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
538 memcpy( pData, ofs, size );
539 ((OFSTRUCT *)pData)->cBytes = size - 1;
542 /* Get the segment table */
544 pModule->seg_table = (int)pData - (int)pModule;
545 buffer = HeapAlloc( SystemHeap, 0, ne_header.n_segment_tab *
546 sizeof(struct ne_segment_table_entry_s));
550 struct ne_segment_table_entry_s *pSeg;
552 if (!READ( mz_header.e_lfanew + ne_header.segment_tab_offset,
553 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
556 HeapFree( SystemHeap, 0, buffer );
557 if (fastload) HeapFree( SystemHeap, 0, fastload );
558 GlobalFree16( hModule );
559 return (HMODULE16)11; /* invalid exe */
561 pSeg = (struct ne_segment_table_entry_s *)buffer;
562 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
564 memcpy( pData, pSeg, sizeof(*pSeg) );
565 pData += sizeof(SEGTABLEENTRY);
567 HeapFree( SystemHeap, 0, buffer );
571 if (fastload) HeapFree( SystemHeap, 0, fastload );
572 GlobalFree16( hModule );
573 return (HMODULE16)11; /* invalid exe */
576 /* Get the resource table */
578 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
580 pModule->res_table = (int)pData - (int)pModule;
581 if (!READ(mz_header.e_lfanew + ne_header.resource_tab_offset,
582 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
583 pData )) return (HMODULE16)11; /* invalid exe */
584 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
586 else pModule->res_table = 0; /* No resource table */
588 /* Get the resident names table */
590 pModule->name_table = (int)pData - (int)pModule;
591 if (!READ( mz_header.e_lfanew + ne_header.rname_tab_offset,
592 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
595 if (fastload) HeapFree( SystemHeap, 0, fastload );
596 GlobalFree16( hModule );
597 return (HMODULE16)11; /* invalid exe */
599 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
601 /* Get the module references table */
603 if (ne_header.n_mod_ref_tab > 0)
605 pModule->modref_table = (int)pData - (int)pModule;
606 if (!READ( mz_header.e_lfanew + ne_header.moduleref_tab_offset,
607 ne_header.n_mod_ref_tab * sizeof(WORD),
610 if (fastload) HeapFree( SystemHeap, 0, fastload );
611 GlobalFree16( hModule );
612 return (HMODULE16)11; /* invalid exe */
614 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
616 else pModule->modref_table = 0; /* No module references */
618 /* Get the imported names table */
620 pModule->import_table = (int)pData - (int)pModule;
621 if (!READ( mz_header.e_lfanew + ne_header.iname_tab_offset,
622 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
625 if (fastload) HeapFree( SystemHeap, 0, fastload );
626 GlobalFree16( hModule );
627 return (HMODULE16)11; /* invalid exe */
629 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
631 /* Get the entry table */
633 pModule->entry_table = (int)pData - (int)pModule;
634 if (!READ( mz_header.e_lfanew + ne_header.entry_tab_offset,
635 ne_header.entry_tab_length,
638 if (fastload) HeapFree( SystemHeap, 0, fastload );
639 GlobalFree16( hModule );
640 return (HMODULE16)11; /* invalid exe */
642 pData += ne_header.entry_tab_length;
644 /* Free the fast-load area */
647 if (fastload) HeapFree( SystemHeap, 0, fastload );
649 /* Get the non-resident names table */
651 if (ne_header.nrname_tab_length)
653 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
654 hModule, FALSE, FALSE, FALSE );
655 if (!pModule->nrname_handle)
657 GlobalFree16( hModule );
658 return (HMODULE16)11; /* invalid exe */
660 buffer = GlobalLock16( pModule->nrname_handle );
661 _llseek32( hFile, ne_header.nrname_tab_offset, SEEK_SET );
662 if (_lread32( hFile, buffer, ne_header.nrname_tab_length )
663 != ne_header.nrname_tab_length)
665 GlobalFree16( pModule->nrname_handle );
666 GlobalFree16( hModule );
667 return (HMODULE16)11; /* invalid exe */
670 else pModule->nrname_handle = 0;
672 /* Allocate a segment for the implicitly-loaded DLLs */
674 if (pModule->modref_count)
676 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
677 (pModule->modref_count+1)*sizeof(HMODULE16),
678 hModule, FALSE, FALSE, FALSE );
679 if (!pModule->dlls_to_init)
681 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
682 GlobalFree16( hModule );
683 return (HMODULE16)11; /* invalid exe */
686 else pModule->dlls_to_init = 0;
688 MODULE_RegisterModule( pModule );
693 /***********************************************************************
696 * Lookup the ordinal for a given name.
698 WORD MODULE_GetOrdinal( HMODULE16 hModule, const char *name )
700 unsigned char buffer[256], *cpnt;
704 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
706 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
709 /* First handle names of the form '#xxxx' */
711 if (name[0] == '#') return atoi( name + 1 );
713 /* Now copy and uppercase the string */
715 strcpy( buffer, name );
716 CharUpper32A( buffer );
717 len = strlen( buffer );
719 /* First search the resident names */
721 cpnt = (char *)pModule + pModule->name_table;
723 /* Skip the first entry (module name) */
724 cpnt += *cpnt + 1 + sizeof(WORD);
727 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
729 dprintf_module( stddeb, " Found: ordinal=%d\n",
730 *(WORD *)(cpnt + *cpnt + 1) );
731 return *(WORD *)(cpnt + *cpnt + 1);
733 cpnt += *cpnt + 1 + sizeof(WORD);
736 /* Now search the non-resident names table */
738 if (!pModule->nrname_handle) return 0; /* No non-resident table */
739 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
741 /* Skip the first entry (module description string) */
742 cpnt += *cpnt + 1 + sizeof(WORD);
745 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
747 dprintf_module( stddeb, " Found: ordinal=%d\n",
748 *(WORD *)(cpnt + *cpnt + 1) );
749 return *(WORD *)(cpnt + *cpnt + 1);
751 cpnt += *cpnt + 1 + sizeof(WORD);
757 /***********************************************************************
758 * MODULE_GetEntryPoint
760 * Return the entry point for a given ordinal.
762 FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
769 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
771 p = (BYTE *)pModule + pModule->entry_table;
772 while (*p && (curOrdinal + *p <= ordinal))
774 /* Skipping this bundle */
778 case 0: p += 2; break; /* unused */
779 case 0xff: p += 2 + *p * 6; break; /* moveable */
780 default: p += 2 + *p * 3; break; /* fixed */
789 case 0xff: /* moveable */
790 p += 2 + 6 * (ordinal - curOrdinal);
792 offset = *(WORD *)(p + 4);
796 p += 2 + 3 * (ordinal - curOrdinal);
797 offset = *(WORD *)(p + 1);
801 if (sel == 0xfe) sel = 0xffff; /* constant entry */
802 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
803 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
807 /***********************************************************************
808 * MODULE_SetEntryPoint
810 * Change the value of an entry point. Use with caution!
811 * It can only change the offset value, not the selector.
813 BOOL16 MODULE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
819 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
821 p = (BYTE *)pModule + pModule->entry_table;
822 while (*p && (curOrdinal + *p <= ordinal))
824 /* Skipping this bundle */
828 case 0: p += 2; break; /* unused */
829 case 0xff: p += 2 + *p * 6; break; /* moveable */
830 default: p += 2 + *p * 3; break; /* fixed */
833 if (!*p) return FALSE;
839 case 0xff: /* moveable */
840 p += 2 + 6 * (ordinal - curOrdinal);
841 *(WORD *)(p + 4) = offset;
844 p += 2 + 3 * (ordinal - curOrdinal);
845 *(WORD *)(p + 1) = offset;
852 /***********************************************************************
853 * MODULE_GetWndProcEntry16 (not a Windows API function)
855 * Return an entry point from the WPROCS dll.
858 FARPROC16 MODULE_GetWndProcEntry16( const char *name )
862 static HMODULE16 hModule = 0;
864 if (!hModule) hModule = GetModuleHandle16( "WPROCS" );
865 ordinal = MODULE_GetOrdinal( hModule, name );
866 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
867 fprintf( stderr, "GetWndProc16: %s not found, please report\n", name );
873 /***********************************************************************
874 * MODULE_GetModuleName
876 LPSTR MODULE_GetModuleName( HMODULE16 hModule )
880 static char buffer[10];
882 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
883 p = (BYTE *)pModule + pModule->name_table;
885 memcpy( buffer, p + 1, len );
891 /**********************************************************************
892 * MODULE_RegisterModule
894 void MODULE_RegisterModule( NE_MODULE *pModule )
896 pModule->next = hFirstModule;
897 hFirstModule = pModule->self;
901 /**********************************************************************
904 * Find a module from a path name.
906 HMODULE16 MODULE_FindModule( LPCSTR path )
908 HMODULE16 hModule = hFirstModule;
909 LPCSTR filename, dotptr, modulepath, modulename;
910 BYTE len, *name_table;
912 if (!(filename = strrchr( path, '\\' ))) filename = path;
914 if ((dotptr = strrchr( filename, '.' )) != NULL)
915 len = (BYTE)(dotptr - filename);
916 else len = strlen( filename );
920 NE_MODULE *pModule = MODULE_GetPtr( hModule );
922 modulepath = NE_MODULE_NAME(pModule);
923 if (!(modulename = strrchr( modulepath, '\\' )))
924 modulename = modulepath;
926 if (!lstrcmpi32A( modulename, filename )) return hModule;
928 name_table = (BYTE *)pModule + pModule->name_table;
929 if ((*name_table == len) && !lstrncmpi32A(filename, name_table+1, len))
931 hModule = pModule->next;
937 /**********************************************************************
940 * Call a DLL's WEP, allowing it to shut down.
941 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
943 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
945 FARPROC16 WEP = (FARPROC16)0;
946 WORD ordinal = MODULE_GetOrdinal( hModule, "WEP" );
948 if (ordinal) WEP = MODULE_GetEntryPoint( hModule, ordinal );
951 dprintf_module( stddeb, "module %04x doesn't have a WEP\n", hModule );
954 return CallWindowsExitProc( WEP, WEP_FREE_DLL );
958 /**********************************************************************
961 * Remove a module from memory.
963 static void MODULE_FreeModule( HMODULE16 hModule )
965 HMODULE16 *hPrevModule;
967 SEGTABLEENTRY *pSegment;
971 if (!(pModule = MODULE_GetPtr( hModule ))) return;
972 if (pModule->flags & NE_FFLAGS_BUILTIN)
973 return; /* Can't free built-in module */
975 if (pModule->flags & NE_FFLAGS_LIBMODULE) MODULE_CallWEP( hModule );
977 /* Free the objects owned by the module */
979 HOOK_FreeModuleHooks( hModule );
980 CLASS_FreeModuleClasses( hModule );
982 /* Clear magic number just in case */
984 pModule->magic = pModule->self = 0;
986 /* Remove it from the linked list */
988 hPrevModule = &hFirstModule;
989 while (*hPrevModule && (*hPrevModule != hModule))
991 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
993 if (*hPrevModule) *hPrevModule = pModule->next;
995 /* Free all the segments */
997 pSegment = NE_SEG_TABLE( pModule );
998 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
1000 GlobalFree16( pSegment->selector );
1003 /* Free the referenced modules */
1005 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
1006 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1008 FreeModule16( *pModRef );
1011 /* Free the module storage */
1013 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
1014 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
1015 GlobalFree16( hModule );
1017 /* Remove module from cache */
1019 if (hCachedModule == hModule) hCachedModule = 0;
1023 /**********************************************************************
1026 * Implementation of LoadModule()
1028 HINSTANCE16 MODULE_Load( LPCSTR name, LPVOID paramBlock, BOOL32 first )
1031 HINSTANCE16 hInstance, hPrevInstance;
1033 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
1036 WORD *pModRef, *pDLLs;
1039 extern const char * DEBUG_curr_module;
1041 hModule = MODULE_FindModule( name );
1043 if (!hModule) /* We have to load the module */
1045 /* Try to load the built-in first if not disabled */
1046 if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
1048 if ((hFile = OpenFile32( name, &ofs, OF_READ )) == HFILE_ERROR32)
1050 /* Now try the built-in even if disabled */
1051 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
1053 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
1056 return 2; /* File not found */
1060 * Record this so that the internal debugger gets some
1061 * record of what it is that we are working with.
1063 DEBUG_curr_module = name;
1065 /* Create the module structure */
1067 hModule = MODULE_LoadExeHeader( hFile, &ofs );
1070 /* Note: PE_LoadModule closes the file */
1072 hModule = PE_LoadModule( hFile, &ofs, paramBlock );
1073 else _lclose32( hFile );
1076 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
1081 pModule = MODULE_GetPtr( hModule );
1083 /* Allocate the segments for this module */
1085 MODULE_CreateSegments( hModule );
1088 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1090 /* Load the referenced DLLs */
1092 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
1093 pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
1094 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1097 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
1098 memcpy( buffer, pstr + 1, *pstr );
1099 strcpy( buffer + *pstr, ".dll" );
1100 dprintf_module( stddeb, "Loading '%s'\n", buffer );
1101 if (!(*pModRef = MODULE_FindModule( buffer )))
1103 /* If the DLL is not loaded yet, load it and store */
1104 /* its handle in the list of DLLs to initialize. */
1107 if ((hDLL = MODULE_Load( buffer, (LPVOID)-1, FALSE )) == 2)
1109 /* file not found */
1112 /* Try with prepending the path of the current module */
1113 GetModuleFileName16( hModule, buffer, sizeof(buffer) );
1114 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1115 memcpy( p + 1, pstr + 1, *pstr );
1116 strcpy( p + 1 + *pstr, ".dll" );
1117 hDLL = MODULE_Load( buffer, (LPVOID)-1, FALSE );
1121 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1122 buffer, name, hDLL );
1123 return 2; /* file not found */
1125 *pModRef = GetExePtr( hDLL );
1126 *pDLLs++ = *pModRef;
1128 else /* Increment the reference count of the DLL */
1130 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
1131 if (pOldDLL) pOldDLL->count++;
1135 /* Load the segments */
1137 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1140 HGLOBAL16 hInitialStack32 = 0;
1141 /* Handle self loading modules */
1142 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1143 SELFLOADHEADER *selfloadheader;
1144 STACK16FRAME *stack16Top;
1145 HMODULE16 hselfload = GetModuleHandle16("WPROCS");
1147 WORD saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1148 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1149 "Support for self-loading modules is very experimental\n",
1150 *((BYTE*)pModule + pModule->name_table),
1151 *((BYTE*)pModule + pModule->name_table),
1152 (char *)pModule + pModule->name_table + 1);
1153 NE_LoadSegment( hModule, 1 );
1154 selfloadheader = (SELFLOADHEADER *)
1155 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1156 selfloadheader->EntryAddrProc =
1157 MODULE_GetEntryPoint(hselfload,27);
1158 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1159 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
1160 pModule->self_loading_sel = GlobalHandleToSel(
1161 GLOBAL_Alloc (GMEM_ZEROINIT,
1162 0xFF00, hModule, FALSE, FALSE, FALSE)
1164 oldstack = IF1632_Saved16_ss_sp;
1165 IF1632_Saved16_ss_sp = MAKELONG( 0xFF00 - sizeof(*stack16Top),
1166 pModule->self_loading_sel );
1167 stack16Top = CURRENT_STACK16;
1168 stack16Top->saved_ss_sp = 0;
1169 stack16Top->ebp = 0;
1170 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
1171 stack16Top->entry_point = 0;
1172 stack16Top->entry_ip = 0;
1173 stack16Top->entry_cs = 0;
1178 if (!IF1632_Saved32_esp)
1180 STACK32FRAME* frame32;
1182 /* Setup an initial 32 bit stack frame */
1183 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1184 hModule, FALSE, FALSE,
1187 /* Create the 32-bit stack frame */
1189 stack32Top = (char*)GlobalLock16(hInitialStack32) +
1191 frame32 = (STACK32FRAME *)stack32Top - 1;
1192 frame32->saved_esp = (DWORD)stack32Top;
1199 frame32->retaddr = 0;
1200 frame32->codeselector = WINE_CODE_SELECTOR;
1201 /* pTask->esp = (DWORD)frame32; */
1203 hf = FILE_DupUnixHandle( MODULE_OpenFile( hModule ) );
1204 CallTo16_word_ww( selfloadheader->BootApp, hModule, hf );
1206 /* some BootApp procs overwrite the selector of dgroup */
1207 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1208 IF1632_Saved16_ss_sp = oldstack;
1209 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1210 if (hInitialStack32)
1212 GlobalFree16(hInitialStack32);
1213 hInitialStack32 = 0;
1218 for (i = 1; i <= pModule->seg_count; i++)
1219 NE_LoadSegment( hModule, i );
1222 /* Fixup the functions prologs */
1224 NE_FixupPrologs( pModule );
1226 /* Make sure the usage count is 1 on the first loading of */
1227 /* the module, even if it contains circular DLL references */
1231 if (first && (pModule->flags & NE_FFLAGS_LIBMODULE))
1232 NE_InitializeDLLs( hModule );
1236 pModule = MODULE_GetPtr( hModule );
1237 hPrevInstance = MODULE_GetInstance( hModule );
1238 hInstance = MODULE_CreateInstance( hModule, params );
1239 if (hInstance != hPrevInstance) /* not a library */
1240 NE_LoadSegment( hModule, pModule->dgroup );
1244 lstrcpyn32A( ofs.szPathName, name, sizeof(ofs.szPathName) );
1245 if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return hModule;
1246 pModule = (NE_MODULE *)GlobalLock16( hModule );
1248 hInstance = MODULE_CreateInstance( hModule, params );
1249 #endif /* WINELIB */
1251 /* Create a task for this instance */
1253 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1258 /* PowerPoint passes NULL as showCmd */
1259 if (params->showCmd)
1260 showcmd = *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1);
1262 showcmd = 0; /* FIXME: correct */
1264 hTask = TASK_CreateTask( hModule, hInstance, hPrevInstance,
1265 params->hEnvironment,
1266 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1269 if( hTask && TASK_GetNextTask(hTask)) Yield();
1276 /**********************************************************************
1277 * LoadModule16 (KERNEL.45)
1279 HINSTANCE16 LoadModule16( LPCSTR name, LPVOID paramBlock )
1281 return MODULE_Load( name, paramBlock, TRUE );
1285 /**********************************************************************
1286 * FreeModule16 (KERNEL.46)
1288 BOOL16 FreeModule16( HMODULE16 hModule )
1292 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1293 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1295 dprintf_module( stddeb, "FreeModule16: %s count %d\n",
1296 MODULE_GetModuleName(hModule), pModule->count );
1297 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1302 /**********************************************************************
1303 * GetModuleHandle16 (KERNEL.47)
1305 HMODULE16 WIN16_GetModuleHandle( SEGPTR name )
1307 if (HIWORD(name) == 0) return GetExePtr( (HINSTANCE16)name );
1308 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1311 HMODULE16 GetModuleHandle16( LPCSTR name )
1313 return MODULE_FindModule( name );
1317 /**********************************************************************
1318 * GetModuleUsage (KERNEL.48)
1320 INT16 GetModuleUsage( HINSTANCE16 hModule )
1324 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1325 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1326 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1327 hModule, pModule->count );
1328 return pModule->count;
1332 /**********************************************************************
1333 * GetModuleFileName16 (KERNEL.49)
1335 INT16 GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName, INT16 nSize )
1339 if (!hModule) hModule = GetCurrentTask();
1340 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1341 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1342 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
1343 dprintf_module( stddeb, "GetModuleFileName16: %s\n", lpFileName );
1344 return strlen(lpFileName);
1348 /***********************************************************************
1349 * GetModuleFileName32A (KERNEL32.235)
1351 DWORD GetModuleFileName32A( HMODULE32 hModule, LPSTR lpFileName, DWORD size )
1357 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1358 hModule = pTask->hInstance;
1360 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1361 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1362 lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), size );
1363 dprintf_module( stddeb, "GetModuleFileName32A: %s\n", lpFileName );
1364 return strlen(lpFileName);
1368 /***********************************************************************
1369 * GetModuleFileName32W (KERNEL32.236)
1371 DWORD GetModuleFileName32W( HMODULE32 hModule, LPWSTR lpFileName, DWORD size )
1373 LPSTR fnA = (char*)HeapAlloc( GetProcessHeap(), 0, size );
1374 DWORD res = GetModuleFileName32A( hModule, fnA, size );
1375 lstrcpynAtoW( lpFileName, fnA, size );
1376 HeapFree( GetProcessHeap(), 0, fnA );
1381 /**********************************************************************
1382 * GetModuleName (KERNEL.27)
1384 BOOL16 GetModuleName( HINSTANCE16 hinst, LPSTR buf, INT16 nSize )
1386 LPSTR name = MODULE_GetModuleName(hinst);
1388 if (!name) return FALSE;
1389 lstrcpyn32A( buf, name, nSize );
1394 /***********************************************************************
1395 * LoadLibraryEx32W (KERNEL.513)
1397 HINSTANCE16 LoadLibraryEx32W16( LPCSTR libname, HANDLE16 hf, DWORD flags )
1399 fprintf(stderr,"LoadLibraryEx32W(%s,%d,%08lx)\n",libname,hf,flags);
1401 return LoadLibrary32A(libname);
1405 /***********************************************************************
1406 * LoadLibrary (KERNEL.95)
1408 HINSTANCE16 LoadLibrary16( LPCSTR libname )
1414 fprintf( stderr, "LoadLibrary not supported in Winelib\n" );
1417 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1419 /* This does not increment the module reference count, and will
1420 * therefore cause crashes on FreeLibrary calls.
1421 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1423 handle = MODULE_Load( libname, (LPVOID)-1, TRUE );
1424 if (handle == (HINSTANCE16)2) /* file not found */
1427 lstrcpyn32A( buffer, libname, 252 );
1428 strcat( buffer, ".dll" );
1429 handle = MODULE_Load( buffer, (LPVOID)-1, TRUE );
1435 /***********************************************************************
1436 * FreeLibrary16 (KERNEL.96)
1438 void FreeLibrary16( HINSTANCE16 handle )
1440 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1441 FreeModule16( handle );
1445 /***********************************************************************
1446 * WinExec16 (KERNEL.166)
1448 HINSTANCE16 WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
1450 return WinExec32( lpCmdLine, nCmdShow );
1454 /***********************************************************************
1455 * WinExec32 (KERNEL32.566)
1457 HINSTANCE32 WinExec32( LPCSTR lpCmdLine, UINT32 nCmdShow )
1460 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1463 char *p, *cmdline, filename[256];
1464 static int use_load_module = 1;
1467 return 2; /* File not found */
1468 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) )))
1469 return 8; /* Out of memory */
1470 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 )))
1472 GlobalFree16( cmdShowHandle );
1473 return 8; /* Out of memory */
1476 /* Store nCmdShow */
1478 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1480 cmdShowPtr[1] = nCmdShow;
1482 /* Build the filename and command-line */
1484 cmdline = (char *)GlobalLock16( cmdLineHandle );
1485 lstrcpyn32A(filename, lpCmdLine, sizeof(filename) - 4 /* for extension */);
1486 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1487 if (*p) lstrcpyn32A( cmdline + 1, p + 1, 127 );
1488 else cmdline[1] = '\0';
1489 cmdline[0] = strlen( cmdline + 1 ) + 1;
1492 /* Now load the executable file */
1494 if (use_load_module)
1497 /* WINELIB: Use LoadModule() only for the program itself */
1498 use_load_module = 0;
1499 params.hEnvironment = (HGLOBAL16)GetDOSEnvironment();
1501 params.hEnvironment = (HGLOBAL16)SELECTOROF( GetDOSEnvironment() );
1502 #endif /* WINELIB */
1503 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1504 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1505 params.reserved = 0;
1506 handle = LoadModule16( filename, ¶ms );
1507 if (handle == 2) /* file not found */
1509 /* Check that the original file name did not have a suffix */
1510 p = strrchr(filename, '.');
1511 /* if there is a '.', check if either \ OR / follow */
1512 if (!p || strchr(p, '/') || strchr(p, '\\'))
1514 p = filename + strlen(filename);
1515 strcpy( p, ".exe" );
1516 handle = LoadModule16( filename, ¶ms );
1517 *p = '\0'; /* Remove extension */
1525 /* Try to start it as a unix program */
1529 DOS_FULL_NAME full_name;
1530 const char *unixfilename = NULL;
1531 const char *argv[256], **argptr;
1532 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1533 nCmdShow == SW_SHOWMINNOACTIVE);
1535 /* get unixfilename */
1536 if (strchr(filename, '/') ||
1537 strchr(filename, ':') ||
1538 strchr(filename, '\\'))
1540 if (DOSFS_GetFullName( filename, TRUE, &full_name ))
1541 unixfilename = full_name.long_name;
1543 else unixfilename = filename;
1549 if (iconic) *argptr++ = "-iconic";
1550 *argptr++ = unixfilename;
1554 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1557 while (*p && *p != ' ' && *p != '\t') p++;
1562 execvp(argv[0], (char**)argv);
1572 if (iconic) *argptr++ = "-iconic";
1573 *argptr++ = lpCmdLine;
1577 execvp(argv[0] , (char**)argv);
1580 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1586 GlobalFree16( cmdShowHandle );
1587 GlobalFree16( cmdLineHandle );
1592 /***********************************************************************
1593 * GetProcAddress16 (KERNEL.50)
1595 FARPROC16 GetProcAddress16( HMODULE16 hModule, SEGPTR name )
1600 if (!hModule) hModule = GetCurrentTask();
1601 hModule = GetExePtr( hModule );
1603 if (HIWORD(name) != 0)
1605 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1606 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1607 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1611 ordinal = LOWORD(name);
1612 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1615 if (!ordinal) return (FARPROC16)0;
1617 ret = MODULE_GetEntryPoint( hModule, ordinal );
1619 dprintf_module( stddeb, "GetProcAddress: returning %08x\n", (UINT32)ret );
1624 /***********************************************************************
1625 * GetProcAddress32 (KERNEL32.257)
1627 FARPROC32 GetProcAddress32( HMODULE32 hModule, LPCSTR function )
1632 if (HIWORD(function))
1633 dprintf_win32(stddeb,"GetProcAddress32(%08lx,%s)\n",(DWORD)hModule,function);
1635 dprintf_win32(stddeb,"GetProcAddress32(%08lx,%p)\n",(DWORD)hModule,function);
1636 hModule = GetExePtr( hModule );
1637 if (!(pModule = MODULE_GetPtr( hModule )))
1638 return (FARPROC32)0;
1639 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1640 return (FARPROC32)0;
1641 if (pModule->flags & NE_FFLAGS_BUILTIN)
1642 return BUILTIN_GetProcAddress32( pModule, function );
1643 return PE_FindExportedFunction( pModule->pe_module, function );
1649 /***********************************************************************
1650 * RtlImageNtHeaders (NTDLL)
1653 RtlImageNtHeader(HMODULE32 hModule)
1658 hModule = GetExePtr( hModule );
1659 if (!(pModule = MODULE_GetPtr( hModule )))
1660 return (LPIMAGE_NT_HEADERS)0;
1661 if (!(pModule->flags & NE_FFLAGS_WIN32) || !pModule->pe_module)
1662 return (LPIMAGE_NT_HEADERS)0;
1663 return pModule->pe_module->pe_header;
1670 /**********************************************************************
1671 * GetExpWinVer (KERNEL.167)
1673 WORD GetExpWinVer( HMODULE16 hModule )
1675 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1676 return pModule ? pModule->expected_version : 0;
1680 /**********************************************************************
1681 * IsSharedSelector (KERNEL.345)
1683 BOOL16 IsSharedSelector( HANDLE16 selector )
1685 /* Check whether the selector belongs to a DLL */
1686 NE_MODULE *pModule = MODULE_GetPtr( GetExePtr( selector ));
1687 if (!pModule) return FALSE;
1688 return (pModule->flags & NE_FFLAGS_LIBMODULE) != 0;
1692 /**********************************************************************
1693 * ModuleFirst (TOOLHELP.59)
1695 BOOL16 ModuleFirst( MODULEENTRY *lpme )
1697 lpme->wNext = hFirstModule;
1698 return ModuleNext( lpme );
1702 /**********************************************************************
1703 * ModuleNext (TOOLHELP.60)
1705 BOOL16 ModuleNext( MODULEENTRY *lpme )
1709 if (!lpme->wNext) return FALSE;
1710 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1711 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1713 lpme->szModule[MAX_MODULE_NAME] = '\0';
1714 lpme->hModule = lpme->wNext;
1715 lpme->wcUsage = pModule->count;
1716 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1717 lpme->szExePath[MAX_PATH] = '\0';
1718 lpme->wNext = pModule->next;
1723 /**********************************************************************
1724 * ModuleFindName (TOOLHELP.61)
1726 BOOL16 ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1728 lpme->wNext = GetModuleHandle16( name );
1729 return ModuleNext( lpme );
1733 /**********************************************************************
1734 * ModuleFindHandle (TOOLHELP.62)
1736 BOOL16 ModuleFindHandle( MODULEENTRY *lpme, HMODULE16 hModule )
1738 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1739 lpme->wNext = hModule;
1740 return ModuleNext( lpme );