Release 960521
[wine.git] / loader / module.c
blobf6638fda70a8c82633220b3e89cfd7a42ac1d58a
1 /*
2 * Modules
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <unistd.h>
13 #include "windows.h"
14 #include "class.h"
15 #include "dos_fs.h"
16 #include "file.h"
17 #include "global.h"
18 #include "hook.h"
19 #include "ldt.h"
20 #include "module.h"
21 #include "neexe.h"
22 #include "stackframe.h"
23 #include "task.h"
24 #include "toolhelp.h"
25 #include "stddebug.h"
26 #include "debug.h"
28 #include "callback.h"
29 #include "wine.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 */
36 #ifndef WINELIB
37 static HANDLE hInitialStack32 = 0;
38 #endif
41 /***********************************************************************
42 * MODULE_GetPtr
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;
49 return pModule;
53 /***********************************************************************
54 * MODULE_DumpModule
56 void MODULE_DumpModule( HMODULE hmodule )
58 int i, ordinal;
59 SEGTABLEENTRY *pSeg;
60 BYTE *pstr;
61 WORD *pword;
62 NE_MODULE *pModule;
64 if (!(pModule = MODULE_GetPtr( hmodule )))
66 fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
67 return;
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++ );
105 while (*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;
122 while (*pstr)
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;
148 ordinal = 1;
149 while (*pstr)
151 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
152 if (!pstr[1])
154 ordinal += *pstr;
155 pstr += 2;
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 );
163 pstr = (char *)pe;
165 else /* fixed */
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) );
171 pstr = (char *)pe;
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 );
181 while (*pstr)
183 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
184 *(WORD *)(pstr + *pstr + 1) );
185 pstr += *pstr + 1 + sizeof(WORD);
188 printf( "\n" );
192 /***********************************************************************
193 * MODULE_WalkModules
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" );
201 while (hModule)
203 NE_MODULE *pModule = MODULE_GetPtr( hModule );
204 if (!pModule)
206 fprintf( stderr, "**** Bad module %04x in list\n", hModule );
207 return;
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 /***********************************************************************
218 * MODULE_OpenFile
220 int MODULE_OpenFile( HMODULE hModule )
222 NE_MODULE *pModule;
223 char *name;
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;
233 close( 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",
239 name, hModule );
240 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
241 name, cachedfd );
242 return cachedfd;
246 /***********************************************************************
247 * MODULE_Ne2MemFlags
249 * This function translates NE segment flags to GlobalAlloc flags
251 static WORD MODULE_Ne2MemFlags(WORD flags)
253 WORD memflags = 0;
254 #if 0
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;
265 #else
266 memflags = GMEM_ZEROINIT | GMEM_FIXED;
267 return memflags;
268 #endif
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);
279 #ifdef WINELIB
280 return (DWORD)GlobalLock16(hMem);
281 #else
282 WORD selector = HIWORD(WIN16_GlobalLock16(hMem));
283 return MAKELONG(hMem, selector);
284 #endif
287 /***********************************************************************
288 * MODULE_CreateSegments
290 #ifndef WINELIB32
291 static BOOL MODULE_CreateSegments( HMODULE hModule )
293 SEGTABLEENTRY *pSegment;
294 NE_MODULE *pModule;
295 int i, minsize;
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),
306 minsize, hModule,
307 !(pSegment->flags & NE_SEGFLAGS_DATA),
308 FALSE,
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;
315 return TRUE;
317 #endif
320 /***********************************************************************
321 * MODULE_GetInstance
323 #ifndef WINELIB32
324 HINSTANCE MODULE_GetInstance( HMODULE hModule )
326 SEGTABLEENTRY *pSegment;
327 NE_MODULE *pModule;
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;
336 #endif
339 /***********************************************************************
340 * MODULE_CreateInstance
342 HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
344 SEGTABLEENTRY *pSegment;
345 NE_MODULE *pModule;
346 int minsize;
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 */
356 if (hPrevInstance)
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;
369 return 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;
380 int size;
381 HMODULE hModule;
382 NE_MODULE *pModule;
383 BYTE *pData;
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+
411 /* segment table */
412 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
413 /* resource table */
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) );
429 pModule->count = 0;
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)
452 free( fastload );
453 fastload = NULL;
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;
464 pData += size;
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) );
470 if (buffer)
472 int i;
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);
484 free( buffer );
486 else
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,
509 pData ))
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,
533 pData ))
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,
545 pData ))
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 );
592 return hModule;
593 #undef READ
597 /***********************************************************************
598 * MODULE_GetOrdinal
600 * Lookup the ordinal for a given name.
602 WORD MODULE_GetOrdinal( HMODULE hModule, const char *name )
604 char buffer[256], *cpnt;
605 BYTE len;
606 NE_MODULE *pModule;
608 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
610 dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
611 hModule, name );
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 );
620 AnsiUpper( buffer );
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);
629 while (*cpnt)
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);
647 while (*cpnt)
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);
657 return 0;
661 /***********************************************************************
662 * MODULE_GetEntryPoint
664 * Return the entry point for a given ordinal.
666 SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
668 NE_MODULE *pModule;
669 WORD curOrdinal = 1;
670 BYTE *p;
671 WORD sel, offset;
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 */
679 curOrdinal += *p;
680 switch(p[1])
682 case 0: p += 2; break; /* unused */
683 case 0xff: p += 2 + *p * 6; break; /* moveable */
684 default: p += 2 + *p * 3; break; /* fixed */
687 if (!*p) return 0;
689 switch(p[1])
691 case 0: /* unused */
692 return 0;
693 case 0xff: /* moveable */
694 p += 2 + 6 * (ordinal - curOrdinal);
695 sel = p[3];
696 offset = *(WORD *)(p + 4);
697 break;
698 default: /* fixed */
699 sel = p[1];
700 p += 2 + 3 * (ordinal - curOrdinal);
701 offset = *(WORD *)(p + 1);
702 break;
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 )
719 NE_MODULE *pModule;
720 WORD curOrdinal = 1;
721 BYTE *p;
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 */
729 curOrdinal += *p;
730 switch(p[1])
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;
739 switch(p[1])
741 case 0: /* unused */
742 return FALSE;
743 case 0xff: /* moveable */
744 p += 2 + 6 * (ordinal - curOrdinal);
745 *(WORD *)(p + 4) = offset;
746 break;
747 default: /* fixed */
748 p += 2 + 3 * (ordinal - curOrdinal);
749 *(WORD *)(p + 1) = offset;
750 break;
752 return TRUE;
756 /***********************************************************************
757 * MODULE_GetWndProcEntry16 (not a Windows API function)
759 * Return an entry point from the WPROCS dll.
761 #ifndef WINELIB
762 FARPROC16 MODULE_GetWndProcEntry16( const char *name )
764 WORD ordinal;
765 FARPROC16 ret;
766 static HMODULE hModule = 0;
768 if (!hModule) hModule = GetModuleHandle( "WPROCS" );
769 ordinal = MODULE_GetOrdinal( hModule, name );
770 if (!(ret = MODULE_GetEntryPoint( hModule, ordinal )))
771 fprintf( stderr, "GetWndProc16: %s not found, please report\n", name );
772 return ret;
774 #endif
777 /***********************************************************************
778 * MODULE_GetWndProcEntry32 (not a Windows API function)
780 * Return an entry point from the WPROCS32 dll.
782 #ifndef WINELIB
783 FARPROC32 MODULE_GetWndProcEntry32( const char *name )
785 FARPROC32 ret;
786 static HMODULE hModule = 0;
788 if (!hModule) hModule = GetModuleHandle( "WPROCS32" );
789 if (!(ret = PE_GetProcAddress( hModule, name )))
790 fprintf( stderr, "GetWndProc32: %s not found, please report\n", name );
791 return ret;
793 #endif
796 /***********************************************************************
797 * MODULE_GetModuleName
799 LPSTR MODULE_GetModuleName( HMODULE hModule )
801 NE_MODULE *pModule;
802 BYTE *p, len;
803 static char buffer[10];
805 if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
806 p = (BYTE *)pModule + pModule->name_table;
807 len = MIN( *p, 8 );
808 memcpy( buffer, p + 1, len );
809 buffer[len] = '\0';
810 return buffer;
814 /**********************************************************************
815 * MODULE_RegisterModule
817 void MODULE_RegisterModule( NE_MODULE *pModule )
819 pModule->next = hFirstModule;
820 hFirstModule = pModule->self;
824 /**********************************************************************
825 * MODULE_FindModule
827 * Find a module from a path name.
829 HMODULE MODULE_FindModule( LPCSTR path )
831 HMODULE hModule = hFirstModule;
832 LPCSTR filename, dotptr, modulepath, modulename;
833 BYTE len, *name_table;
835 if (!(filename = strrchr( path, '\\' ))) filename = path;
836 else filename++;
837 if ((dotptr = strrchr( filename, '.' )) != NULL)
838 len = (BYTE)(dotptr - filename);
839 else len = strlen( filename );
841 while(hModule)
843 NE_MODULE *pModule = MODULE_GetPtr( hModule );
844 if (!pModule) break;
845 modulepath = NE_MODULE_NAME(pModule);
846 if (!(modulename = strrchr( modulepath, '\\' )))
847 modulename = modulepath;
848 else modulename++;
849 if (!lstrcmpi( modulename, filename )) return hModule;
851 name_table = (BYTE *)pModule + pModule->name_table;
852 if ((*name_table == len) && !lstrncmpi(filename, name_table+1, len))
853 return hModule;
854 hModule = pModule->next;
856 return 0;
860 /**********************************************************************
861 * MODULE_FreeModule
863 * Remove a module from memory.
865 static void MODULE_FreeModule( HMODULE hModule )
867 HMODULE *hPrevModule;
868 NE_MODULE *pModule;
869 SEGTABLEENTRY *pSegment;
870 HMODULE *pModRef;
871 int i;
873 if (!(pModule = MODULE_GetPtr( hModule ))) return;
874 if (pModule->flags & NE_FFLAGS_BUILTIN)
875 return; /* Can't free built-in module */
877 /* FIXME: should call the exit code for the library here */
879 /* Free the objects owned by the module */
881 HOOK_FreeModuleHooks( hModule );
882 CLASS_FreeModuleClasses( hModule );
884 /* Clear magic number just in case */
886 pModule->magic = pModule->self = 0;
888 /* Remove it from the linked list */
890 hPrevModule = &hFirstModule;
891 while (*hPrevModule && (*hPrevModule != hModule))
893 hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
895 if (*hPrevModule) *hPrevModule = pModule->next;
897 /* Free all the segments */
899 pSegment = NE_SEG_TABLE( pModule );
900 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
902 GlobalFree16( pSegment->selector );
905 /* Free the referenced modules */
907 pModRef = (HMODULE*)NE_MODULE_TABLE( pModule );
908 for (i = 0; i < pModule->modref_count; i++, pModRef++)
910 FreeModule( *pModRef );
913 /* Free the module storage */
915 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
916 if (pModule->dlls_to_init) GlobalFree16( pModule->dlls_to_init );
917 GlobalFree16( hModule );
919 /* Remove module from cache */
921 if (hCachedModule == hModule) hCachedModule = 0;
925 /**********************************************************************
926 * LoadModule (KERNEL.45)
928 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
930 HMODULE hModule;
931 HANDLE hInstance, hPrevInstance;
932 NE_MODULE *pModule;
933 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
934 #ifndef WINELIB
935 WORD *pModRef, *pDLLs;
936 HFILE hFile;
937 int i;
939 hModule = MODULE_FindModule( name );
941 if (!hModule) /* We have to load the module */
943 OFSTRUCT ofs;
945 /* Try to load the built-in first if not disabled */
946 if ((hModule = BUILTIN_LoadModule( name, FALSE ))) return hModule;
948 if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR)
950 /* Now try the built-in even if disabled */
951 if ((hModule = BUILTIN_LoadModule( name, TRUE )))
953 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
954 return hModule;
956 return 2; /* File not found */
959 /* Create the module structure */
961 hModule = MODULE_LoadExeHeader( hFile, &ofs );
962 if (hModule < 32)
964 /* FIXME: Hack because PE_LoadModule is recursive */
965 int fd = dup( FILE_GetUnixHandle(hFile) );
966 _lclose( hFile );
967 if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
968 close( fd );
969 if (hModule < 32)
970 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
971 name, hModule );
972 return hModule;
974 _lclose( hFile );
975 pModule = MODULE_GetPtr( hModule );
977 /* Allocate the segments for this module */
979 MODULE_CreateSegments( hModule );
981 hPrevInstance = 0;
982 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
984 /* Load the referenced DLLs */
986 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
987 pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
988 for (i = 0; i < pModule->modref_count; i++, pModRef++)
990 char buffer[256];
991 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
992 memcpy( buffer, pstr + 1, *pstr );
993 strcpy( buffer + *pstr, ".dll" );
994 dprintf_module( stddeb, "Loading '%s'\n", buffer );
995 if (!(*pModRef = MODULE_FindModule( buffer )))
997 /* If the DLL is not loaded yet, load it and store */
998 /* its handle in the list of DLLs to initialize. */
999 HMODULE hDLL;
1001 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
1003 char *p;
1005 /* Try with prepending the path of the current module */
1006 GetModuleFileName( hModule, buffer, 256 );
1007 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
1008 memcpy( p + 1, pstr + 1, *pstr );
1009 strcpy( p + 1 + *pstr, ".dll" );
1010 hDLL = LoadModule( buffer, (LPVOID)-1 );
1012 if (hDLL < 32)
1014 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
1015 buffer, name, hDLL );
1016 return 2; /* file not found */
1018 *pModRef = GetExePtr( hDLL );
1019 *pDLLs++ = *pModRef;
1021 else /* Increment the reference count of the DLL */
1023 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
1024 if (pOldDLL) pOldDLL->count++;
1028 /* Load the segments */
1030 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1032 int fd;
1033 /* Handle self loading modules */
1034 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1035 SELFLOADHEADER *selfloadheader;
1036 HMODULE hselfload = GetModuleHandle("WPROCS");
1037 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1038 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1039 "Support for self-loading modules is very experimental\n",
1040 *((BYTE*)pModule + pModule->name_table),
1041 *((BYTE*)pModule + pModule->name_table),
1042 (char *)pModule + pModule->name_table + 1);
1043 NE_LoadSegment( hModule, 1 );
1044 selfloadheader = (SELFLOADHEADER *)
1045 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1046 selfloadheader->EntryAddrProc =
1047 MODULE_GetEntryPoint(hselfload,27);
1048 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1049 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1050 pModule->self_loading_sel = GlobalHandleToSel(
1051 GLOBAL_Alloc (GMEM_ZEROINIT,
1052 0xFF00, hModule, FALSE, FALSE, FALSE)
1054 oldss = IF1632_Saved16_ss;
1055 oldsp = IF1632_Saved16_sp;
1056 IF1632_Saved16_ss = pModule->self_loading_sel;
1057 IF1632_Saved16_sp = 0xFF00;
1058 if (!IF1632_Stack32_base) {
1059 STACK32FRAME* frame32;
1060 char *stack32Top;
1061 /* Setup an initial 32 bit stack frame */
1062 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1063 hModule, FALSE, FALSE,
1064 FALSE );
1066 /* Create the 32-bit stack frame */
1068 *(DWORD *)GlobalLock16(hInitialStack32) = 0xDEADBEEF;
1069 stack32Top = (char*)GlobalLock16(hInitialStack32) +
1070 0x10000;
1071 frame32 = (STACK32FRAME *)stack32Top - 1;
1072 frame32->saved_esp = (DWORD)stack32Top;
1073 frame32->edi = 0;
1074 frame32->esi = 0;
1075 frame32->edx = 0;
1076 frame32->ecx = 0;
1077 frame32->ebx = 0;
1078 frame32->ebp = 0;
1079 frame32->retaddr = 0;
1080 frame32->codeselector = WINE_CODE_SELECTOR;
1081 /* pTask->esp = (DWORD)frame32; */
1082 IF1632_Stack32_base = WIN16_GlobalLock16(hInitialStack32);
1085 /* FIXME: we probably need a DOS handle here */
1086 fd = MODULE_OpenFile( hModule );
1087 CallTo16_word_ww (selfloadheader->BootApp,
1088 pModule->self_loading_sel, hModule, fd);
1089 /* some BootApp procs overwrite the selector of dgroup */
1090 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1091 IF1632_Saved16_ss = oldss;
1092 IF1632_Saved16_sp = oldsp;
1093 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1094 if (hInitialStack32){
1095 GlobalFree16(hInitialStack32);
1096 IF1632_Stack32_base = hInitialStack32 = 0;
1099 else
1101 for (i = 1; i <= pModule->seg_count; i++)
1102 NE_LoadSegment( hModule, i );
1105 /* Fixup the functions prologs */
1107 NE_FixupPrologs( pModule );
1109 /* Make sure the usage count is 1 on the first loading of */
1110 /* the module, even if it contains circular DLL references */
1112 pModule->count = 1;
1114 else
1116 pModule = MODULE_GetPtr( hModule );
1117 hPrevInstance = MODULE_GetInstance( hModule );
1118 hInstance = MODULE_CreateInstance( hModule, params );
1119 if (hInstance != hPrevInstance) /* not a library */
1120 NE_LoadSegment( hModule, pModule->dgroup );
1121 pModule->count++;
1123 #else
1124 hModule = GlobalAlloc16( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE));
1125 pModule = (NE_MODULE *)GlobalLock16( hModule );
1126 pModule->count = 1;
1127 pModule->magic = NE_SIGNATURE;
1128 pModule->self = hModule;
1129 hPrevInstance = 0;
1130 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1131 #endif /* WINELIB */
1133 /* Create a task for this instance */
1135 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1137 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1138 params->hEnvironment,
1139 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1140 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1143 return hInstance;
1147 /**********************************************************************
1148 * FreeModule (KERNEL.46)
1150 BOOL FreeModule( HANDLE hModule )
1152 NE_MODULE *pModule;
1154 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1155 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
1157 dprintf_module( stddeb, "FreeModule: %s count %d\n",
1158 MODULE_GetModuleName(hModule), pModule->count );
1159 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1160 return TRUE;
1164 /**********************************************************************
1165 * GetModuleHandle (KERNEL.47)
1167 HMODULE WIN16_GetModuleHandle( SEGPTR name )
1169 if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
1170 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1173 HMODULE GetModuleHandle( LPCSTR name )
1175 return MODULE_FindModule( name );
1179 /**********************************************************************
1180 * GetModuleUsage (KERNEL.48)
1182 int GetModuleUsage( HANDLE hModule )
1184 NE_MODULE *pModule;
1186 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1187 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1188 dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
1189 hModule, pModule->count );
1190 return pModule->count;
1194 /**********************************************************************
1195 * GetModuleFileName (KERNEL.49)
1197 int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1199 NE_MODULE *pModule;
1201 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1202 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
1203 lstrcpyn( lpFileName, NE_MODULE_NAME(pModule), nSize );
1204 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1205 return strlen(lpFileName);
1209 /***********************************************************************
1210 * LoadLibrary (KERNEL.95)
1212 HANDLE LoadLibrary( LPCSTR libname )
1214 #ifdef WINELIB
1215 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1216 WINELIB_UNIMP("LoadLibrary()");
1217 return (HANDLE)0;
1218 #else
1219 HANDLE handle;
1221 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1223 /* This does not increment the module reference count, and will
1224 * therefore cause crashes on FreeLibrary calls.
1225 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1227 handle = LoadModule( libname, (LPVOID)-1 );
1228 if (handle == (HANDLE)2) /* file not found */
1230 char buffer[256];
1231 lstrcpyn( buffer, libname, 252 );
1232 strcat( buffer, ".dll" );
1233 handle = LoadModule( buffer, (LPVOID)-1 );
1235 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
1236 return handle;
1237 #endif
1241 /***********************************************************************
1242 * FreeLibrary (KERNEL.96)
1244 void FreeLibrary( HANDLE handle )
1246 dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
1247 FreeModule( handle );
1251 /***********************************************************************
1252 * WinExec (KERNEL.166)
1254 HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1256 LOADPARAMS params;
1257 HGLOBAL16 cmdShowHandle, cmdLineHandle;
1258 HANDLE handle;
1259 WORD *cmdShowPtr;
1260 char *p, *cmdline, filename[256];
1261 static int use_load_module = 1;
1263 if (!(cmdShowHandle = GlobalAlloc16( 0, 2 * sizeof(WORD) ))) return 0;
1264 if (!(cmdLineHandle = GlobalAlloc16( 0, 256 ))) return 0;
1266 /* Store nCmdShow */
1268 cmdShowPtr = (WORD *)GlobalLock16( cmdShowHandle );
1269 cmdShowPtr[0] = 2;
1270 cmdShowPtr[1] = nCmdShow;
1272 /* Build the filename and command-line */
1274 cmdline = (char *)GlobalLock16( cmdLineHandle );
1275 lstrcpyn( filename, lpCmdLine, sizeof(filename) - 4 /* for extension */ );
1276 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1277 if (*p) lstrcpyn( cmdline, p + 1, 128 );
1278 else cmdline[0] = '\0';
1279 *p = '\0';
1281 /* Now load the executable file */
1283 if (use_load_module)
1285 #ifdef WINELIB
1286 /* WINELIB: Use LoadModule() only for the program itself */
1287 use_load_module = 0;
1288 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1289 #else
1290 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1291 #endif /* WINELIB */
1292 params.cmdLine = (SEGPTR)WIN16_GlobalLock16( cmdLineHandle );
1293 params.showCmd = (SEGPTR)WIN16_GlobalLock16( cmdShowHandle );
1294 params.reserved = 0;
1295 handle = LoadModule( filename, &params );
1296 if (handle == 2) /* file not found */
1298 /* Check that the original file name did not have a suffix */
1299 p = strrchr(filename, '.');
1300 if (!p || (strchr(p, '/') && strchr(p, '\\')))
1302 p = filename + strlen(filename);
1303 strcpy( p, ".exe" );
1304 handle = LoadModule( filename, &params );
1305 *p = '\0'; /* Remove extension */
1309 else handle = 2;
1311 if (handle < 32)
1313 /* Try to start it as a unix program */
1314 if (!fork())
1316 /* Child process */
1317 const char *unixfilename;
1318 const char *argv[256], **argptr;
1319 int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
1320 nCmdShow == SW_SHOWMINNOACTIVE);
1322 /* get unixfilename */
1323 if (strchr(filename, '/') ||
1324 strchr(filename, ':') ||
1325 strchr(filename, '\\'))
1326 unixfilename = DOSFS_GetUnixFileName(filename, 1);
1327 else unixfilename = filename;
1329 if (unixfilename)
1331 /* build argv */
1332 argptr = argv;
1333 if (iconic) *argptr++ = "-iconic";
1334 *argptr++ = unixfilename;
1335 p = cmdline;
1336 while (1)
1338 while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
1339 if (!*p) break;
1340 *argptr++ = p;
1341 while (*p && *p != ' ' && *p != '\t') p++;
1343 *argptr++ = 0;
1345 /* Execute */
1346 execvp(argv[0], (char**)argv);
1349 /* Failed ! */
1350 #ifdef WINELIB
1351 /* build argv */
1352 argptr = argv;
1353 *argptr++ = "wine";
1354 if (iconic) *argptr++ = "-iconic";
1355 *argptr++ = lpCmdLine;
1356 *argptr++ = 0;
1358 /* Execute */
1359 execvp(argv[0] , (char**)argv);
1361 /* Failed ! */
1362 fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
1363 #endif
1364 exit(1);
1368 GlobalFree16( cmdShowHandle );
1369 GlobalFree16( cmdLineHandle );
1371 #if 0
1372 if (handle < (HANDLE)32) /* Error? */
1373 return handle;
1375 /* FIXME: Yield never returns!
1376 We may want to run more applications or start the debugger
1377 before calling Yield. If we don't Yield will be called immdiately
1378 after returning. Why is it needed for Word anyway? */
1379 Yield(); /* program is executed immediately ....needed for word */
1381 #endif
1382 return handle;
1386 /***********************************************************************
1387 * GetProcAddress (KERNEL.50)
1389 FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
1391 WORD ordinal;
1392 SEGPTR ret;
1394 if (!hModule) hModule = GetCurrentTask();
1395 hModule = GetExePtr( hModule );
1397 if (HIWORD(name) != 0)
1399 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1400 dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
1401 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1403 else
1405 ordinal = LOWORD(name);
1406 dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
1407 hModule, ordinal );
1409 if (!ordinal) return (FARPROC)0;
1411 ret = MODULE_GetEntryPoint( hModule, ordinal );
1413 dprintf_module( stddeb, "GetProcAddress: returning %08lx\n", (DWORD)ret );
1414 return (FARPROC)ret;
1418 /**********************************************************************
1419 * GetExpWinVer (KERNEL.167)
1421 WORD GetExpWinVer( HMODULE hModule )
1423 NE_MODULE *pModule = MODULE_GetPtr( hModule );
1424 return pModule ? pModule->expected_version : 0;
1428 /**********************************************************************
1429 * ModuleFirst (TOOLHELP.59)
1431 BOOL ModuleFirst( MODULEENTRY *lpme )
1433 lpme->wNext = hFirstModule;
1434 return ModuleNext( lpme );
1438 /**********************************************************************
1439 * ModuleNext (TOOLHELP.60)
1441 BOOL ModuleNext( MODULEENTRY *lpme )
1443 NE_MODULE *pModule;
1445 if (!lpme->wNext) return FALSE;
1446 if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
1447 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1448 MAX_MODULE_NAME );
1449 lpme->szModule[MAX_MODULE_NAME] = '\0';
1450 lpme->hModule = lpme->wNext;
1451 lpme->wcUsage = pModule->count;
1452 strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
1453 lpme->szExePath[MAX_PATH] = '\0';
1454 lpme->wNext = pModule->next;
1455 return TRUE;
1459 /**********************************************************************
1460 * ModuleFindName (TOOLHELP.61)
1462 BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1464 lpme->wNext = GetModuleHandle( name );
1465 return ModuleNext( lpme );
1469 /**********************************************************************
1470 * ModuleFindHandle (TOOLHELP.62)
1472 BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
1474 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1475 lpme->wNext = hModule;
1476 return ModuleNext( lpme );