Release 951212
[wine/multimedia.git] / loader / module.c
blob1137f3dcd362d448596355bcf993640ad5579ec3
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 "dlls.h"
15 #include "dos_fs.h"
16 #include "global.h"
17 #include "ldt.h"
18 #include "module.h"
19 #include "neexe.h"
20 #include "stackframe.h"
21 #include "task.h"
22 #include "toolhelp.h"
23 #include "stddebug.h"
24 #include "debug.h"
26 #include "callback.h"
27 #include "wine.h"
29 static HMODULE hFirstModule = 0;
30 static HMODULE hCachedModule = 0; /* Module cached by MODULE_OpenFile */
32 #ifndef WINELIB
33 static HANDLE hInitialStack32 = 0;
34 #endif
35 /***********************************************************************
36 * MODULE_LoadBuiltin
38 * Load a built-in module. If the 'force' parameter is FALSE, we only
39 * load the module if it has not been disabled via the -dll option.
41 #ifndef WINELIB
42 static HMODULE MODULE_LoadBuiltin( LPCSTR name, BOOL force )
44 HMODULE hModule;
45 NE_MODULE *pModule;
46 SEGTABLEENTRY *pSegTable;
47 struct dll_table_s *table;
48 int i;
49 char dllname[16], *p;
51 /* Fix the name in case we have a full path and extension */
53 if ((p = strrchr( name, '\\' ))) name = p + 1;
54 strncpy( dllname, name, 15 );
55 dllname[15] = '\0';
56 if ((p = strrchr( dllname, '.' ))) *p = '\0';
58 for (i = 0, table = dll_builtin_table; i < N_BUILTINS; i++, table++)
59 if (!strcasecmp( table->name, dllname )) break;
60 if (i >= N_BUILTINS) return 0;
61 if (!table->used && !force) return 0;
63 hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, table->module_start,
64 table->module_end - table->module_start,
65 0, FALSE, FALSE, FALSE, NULL );
66 if (!hModule) return 0;
67 FarSetOwner( hModule, hModule );
69 table->hModule = hModule;
71 dprintf_module( stddeb, "Built-in %s: hmodule=%04x\n",
72 table->name, hModule );
74 /* Allocate the code segment */
76 pModule = (NE_MODULE *)GlobalLock( hModule );
77 pSegTable = NE_SEG_TABLE( pModule );
79 pSegTable->selector = GLOBAL_CreateBlock( GMEM_FIXED, table->code_start,
80 pSegTable->minsize, hModule,
81 TRUE, TRUE, FALSE, NULL );
82 if (!pSegTable->selector) return 0;
83 pSegTable++;
85 /* Allocate the data segment */
87 pSegTable->selector = GLOBAL_Alloc( GMEM_FIXED, pSegTable->minsize,
88 hModule, FALSE, FALSE, FALSE );
89 if (!pSegTable->selector) return 0;
90 memcpy( GlobalLock( pSegTable->selector ),
91 table->data_start, pSegTable->minsize );
93 pModule->next = hFirstModule;
94 hFirstModule = hModule;
95 return hModule;
97 #endif
99 /***********************************************************************
100 * MODULE_Init
102 * Create the built-in modules.
104 BOOL MODULE_Init(void)
106 /* For these, built-in modules are always used */
108 #ifndef WINELIB32
109 if (!MODULE_LoadBuiltin( "KERNEL", TRUE ) ||
110 !MODULE_LoadBuiltin( "GDI", TRUE ) ||
111 !MODULE_LoadBuiltin( "USER", TRUE ) ||
112 !MODULE_LoadBuiltin( "WINPROCS", TRUE )) return FALSE;
114 #else
115 fprintf(stderr, "JBP: MODULE_Init() ignored.\n");
116 #endif
117 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
119 MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
120 return TRUE;
124 /***********************************************************************
125 * MODULE_PrintModule
127 void MODULE_PrintModule( HMODULE hmodule )
129 int i, ordinal;
130 SEGTABLEENTRY *pSeg;
131 BYTE *pstr;
132 WORD *pword;
133 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hmodule );
135 /* Dump the module info */
137 printf( "Module "NPFMT":\n", hmodule );
138 printf( "count=%d flags=%04x heap=%d stack=%d\n",
139 pModule->count, pModule->flags,
140 pModule->heap_size, pModule->stack_size );
141 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
142 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
143 pModule->seg_count, pModule->modref_count );
144 printf( "os_flags=%d swap_area=%d version=%04x\n",
145 pModule->os_flags, pModule->min_swap_area,
146 pModule->expected_version );
148 /* Dump the file info */
150 printf( "Filename: '%s'\n",
151 ((LOADEDFILEINFO *)((BYTE *)pModule + pModule->fileinfo))->filename );
153 /* Dump the segment table */
155 printf( "\nSegment table:\n" );
156 pSeg = NE_SEG_TABLE( pModule );
157 for (i = 0; i < pModule->seg_count; i++, pSeg++)
158 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel="NPFMT"\n",
159 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
160 pSeg->minsize, pSeg->selector );
162 /* Dump the resource table */
164 printf( "\nResource table:\n" );
165 if (pModule->res_table)
167 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
168 printf( "Alignment: %d\n", *pword++ );
169 while (*pword)
171 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
172 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
173 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
174 for (i = 0; i < ptr->count; i++, pname++)
175 printf( "offset=%d len=%d id=%04x\n",
176 pname->offset, pname->length, pname->id );
177 pword = (WORD *)pname;
180 else printf( "None\n" );
182 /* Dump the resident name table */
184 printf( "\nResident-name table:\n" );
185 pstr = (char *)pModule + pModule->name_table;
186 while (*pstr)
188 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
189 *(WORD *)(pstr + *pstr + 1) );
190 pstr += *pstr + 1 + sizeof(WORD);
193 /* Dump the module reference table */
195 printf( "\nModule ref table:\n" );
196 if (pModule->modref_table)
198 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
199 for (i = 0; i < pModule->modref_count; i++, pword++)
201 char *name = (char *)pModule + pModule->import_table + *pword;
202 printf( "%d: %04x -> '%*.*s'\n",
203 i, *pword, *name, *name, name + 1 );
206 else printf( "None\n" );
208 /* Dump the entry table */
210 printf( "\nEntry table:\n" );
211 pstr = (char *)pModule + pModule->entry_table;
212 ordinal = 1;
213 while (*pstr)
215 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
216 if (!pstr[1])
218 ordinal += *pstr;
219 pstr += 2;
221 else if ((BYTE)pstr[1] == 0xff) /* moveable */
223 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
224 for (i = 0; i < *pstr; i++, pe++)
225 printf( "%d: %02x:%04x (moveable)\n",
226 ordinal++, pe->seg_number, pe->offset );
227 pstr = (char *)pe;
229 else /* fixed */
231 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
232 for (i = 0; i < *pstr; i++, pe++)
233 printf( "%d: %04x (fixed)\n",
234 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
235 pstr = (char *)pe;
239 /* Dump the non-resident names table */
241 printf( "\nNon-resident names table:\n" );
242 if (pModule->nrname_handle)
244 pstr = (char *)GlobalLock( pModule->nrname_handle );
245 while (*pstr)
247 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
248 *(WORD *)(pstr + *pstr + 1) );
249 pstr += *pstr + 1 + sizeof(WORD);
252 printf( "\n" );
256 /***********************************************************************
257 * MODULE_OpenFile
259 int MODULE_OpenFile( HMODULE hModule )
261 NE_MODULE *pModule;
262 char *name;
264 static int cachedfd = -1;
266 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
267 dprintf_module( stddeb, "MODULE_OpenFile("NPFMT") cache: mod="NPFMT" fd=%d\n",
268 hModule, hCachedModule, cachedfd );
269 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return -1;
270 if (hCachedModule == hModule) return cachedfd;
271 close( cachedfd );
272 hCachedModule = hModule;
273 name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
274 cachedfd = open( DOS_GetUnixFileName( name ), O_RDONLY );
275 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
276 name, cachedfd );
277 return cachedfd;
279 /***********************************************************************
280 * MODULE_Ne2MemFlags
283 /* This function translates NE segment flags to GlobalAlloc flags */
285 static WORD MODULE_Ne2MemFlags(WORD flags)
287 WORD memflags = 0;
288 #if 0
289 if (flags & NE_SEGFLAGS_DISCARDABLE)
290 memflags |= GMEM_DISCARDABLE;
291 if (flags & NE_SEGFLAGS_MOVEABLE ||
292 ( ! (flags & NE_SEGFLAGS_DATA) &&
293 ! (flags & NE_SEGFLAGS_LOADED) &&
294 ! (flags & NE_SEGFLAGS_ALLOCATED)
297 memflags |= GMEM_MOVEABLE;
298 memflags |= GMEM_ZEROINIT;
299 #else
300 memflags = GMEM_ZEROINIT | GMEM_FIXED;
301 return memflags;
302 #endif
305 /***********************************************************************
306 * MODULE_AllocateSegment (WINPROCS.26)
309 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
311 WORD size = wSize << wElem;
312 HANDLE hMem = GlobalAlloc( MODULE_Ne2MemFlags(wFlags), size);
313 #ifdef WINELIB32
314 return (DWORD)GlobalLock(hMem);
315 #else
316 WORD selector = HIWORD(GlobalLock(hMem));
317 return MAKELONG(hMem, selector);
318 #endif
321 /***********************************************************************
322 * MODULE_CreateSegments
324 #ifndef WINELIB32
325 static BOOL MODULE_CreateSegments( HMODULE hModule )
327 SEGTABLEENTRY *pSegment;
328 NE_MODULE *pModule;
329 int i, minsize;
331 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
332 pSegment = NE_SEG_TABLE( pModule );
333 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
335 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
336 if (i == pModule->ss) minsize += pModule->stack_size;
337 /* The DGROUP is allocated by MODULE_CreateInstance */
338 if (i == pModule->dgroup) continue;
339 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
340 minsize, hModule,
341 !(pSegment->flags & NE_SEGFLAGS_DATA),
342 FALSE,
343 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
344 if (!pSegment->selector) return FALSE;
347 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
348 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
349 return TRUE;
351 #endif
354 /***********************************************************************
355 * MODULE_GetInstance
357 #ifndef WINELIB32
358 static HINSTANCE MODULE_GetInstance( HMODULE hModule )
360 SEGTABLEENTRY *pSegment;
361 NE_MODULE *pModule;
363 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
364 if (pModule->dgroup == 0) return hModule;
366 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
368 return pSegment->selector;
370 #endif
373 /***********************************************************************
374 * MODULE_CreateInstance
376 HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
378 SEGTABLEENTRY *pSegment;
379 NE_MODULE *pModule;
380 int minsize;
381 HINSTANCE hNewInstance, hPrevInstance;
383 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
384 if (pModule->dgroup == 0) return hModule;
386 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
387 hPrevInstance = pSegment->selector;
389 /* if it's a library, create a new instance only the first time */
390 if (hPrevInstance)
392 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
393 if (params == (LOADPARAMS*)-1) return hPrevInstance;
396 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
397 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
398 minsize += pModule->heap_size;
399 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
400 minsize, hModule, FALSE, FALSE, FALSE );
401 if (!hNewInstance) return 0;
402 pSegment->selector = hNewInstance;
403 return hNewInstance;
407 /***********************************************************************
408 * MODULE_LoadExeHeader
410 HMODULE MODULE_LoadExeHeader( int fd, OFSTRUCT *ofs )
412 struct mz_header_s mz_header;
413 struct ne_header_s ne_header;
414 int size;
415 HMODULE hModule;
416 NE_MODULE *pModule;
417 BYTE *pData;
418 char *buffer, *fastload = NULL;
419 int fastload_offset = 0, fastload_length = 0;
421 /* Read a block from either the file or the fast-load area. */
422 #define READ(offset,size,buffer) \
423 ((fastload && ((offset) >= fastload_offset) && \
424 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
425 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
426 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
427 read( fd, (buffer), (size) ) == (size)))
429 lseek( fd, 0, SEEK_SET );
430 if ((read( fd, &mz_header, sizeof(mz_header) ) != sizeof(mz_header)) ||
431 (mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11; /* invalid exe */
433 lseek( fd, mz_header.ne_offset, SEEK_SET );
434 if (read( fd, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
435 return (HMODULE)11; /* invalid exe */
437 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21; /* win32 exe */
438 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE)11; /* invalid exe */
440 /* We now have a valid NE header */
442 size = sizeof(NE_MODULE) +
443 /* loaded file info */
444 sizeof(LOADEDFILEINFO) + strlen(ofs->szPathName) +
445 /* segment table */
446 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
447 /* resource table */
448 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
449 /* resident names table */
450 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
451 /* module ref table */
452 ne_header.n_mod_ref_tab * sizeof(WORD) +
453 /* imported names table */
454 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
455 /* entry table length */
456 ne_header.entry_tab_length;
458 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
459 if (!hModule) return (HMODULE)11; /* invalid exe */
460 FarSetOwner( hModule, hModule );
461 pModule = (NE_MODULE *)GlobalLock( hModule );
462 memcpy( pModule, &ne_header, sizeof(NE_MODULE) );
463 pModule->count = 0;
464 pData = (BYTE *)(pModule + 1);
466 /* Read the fast-load area */
468 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
470 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
471 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
472 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
473 fastload_offset, fastload_length );
474 if ((fastload = (char *)malloc( fastload_length )) != NULL)
476 lseek( fd, mz_header.ne_offset + fastload_offset, SEEK_SET );
477 if (read( fd, fastload, fastload_length ) != fastload_length)
479 free( fastload );
480 fastload = NULL;
485 /* Store the filename information */
487 pModule->fileinfo = (int)pData - (int)pModule;
488 ((LOADEDFILEINFO*)pData)->length = sizeof(LOADEDFILEINFO)+strlen(ofs->szPathName);
489 ((LOADEDFILEINFO*)pData)->fixed_media = TRUE;
490 ((LOADEDFILEINFO*)pData)->error = 0;
491 ((LOADEDFILEINFO*)pData)->date = 0;
492 ((LOADEDFILEINFO*)pData)->time = 0;
493 strcpy( ((LOADEDFILEINFO*)pData)->filename, ofs->szPathName );
494 pData += ((LOADEDFILEINFO*)pData)->length--;
496 /* Get the segment table */
498 pModule->seg_table = (int)pData - (int)pModule;
499 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
500 if (buffer)
502 int i;
503 struct ne_segment_table_entry_s *pSeg;
505 if (!READ( ne_header.segment_tab_offset,
506 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
507 buffer )) return (HMODULE)11; /* invalid exe */
508 pSeg = (struct ne_segment_table_entry_s *)buffer;
509 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
511 memcpy( pData, pSeg, sizeof(*pSeg) );
512 pData += sizeof(SEGTABLEENTRY);
514 free( buffer );
516 else return (HMODULE)11; /* invalid exe */
518 /* Get the resource table */
520 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
522 pModule->res_table = (int)pData - (int)pModule;
523 if (!READ(ne_header.resource_tab_offset,
524 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
525 pData )) return (HMODULE)11; /* invalid exe */
526 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
528 else pModule->res_table = 0; /* No resource table */
530 /* Get the resident names table */
532 pModule->name_table = (int)pData - (int)pModule;
533 if (!READ( ne_header.rname_tab_offset,
534 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
535 pData )) return (HMODULE)11; /* invalid exe */
536 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
538 /* Get the module references table */
540 if (ne_header.n_mod_ref_tab > 0)
542 pModule->modref_table = (int)pData - (int)pModule;
543 if (!READ( ne_header.moduleref_tab_offset,
544 ne_header.n_mod_ref_tab * sizeof(WORD),
545 pData )) return (HMODULE)11; /* invalid exe */
546 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
548 else pModule->modref_table = 0; /* No module references */
550 /* Get the imported names table */
552 pModule->import_table = (int)pData - (int)pModule;
553 if (!READ( ne_header.iname_tab_offset,
554 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
555 pData )) return (HMODULE)11; /* invalid exe */
556 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
558 /* Get the entry table */
560 pModule->entry_table = (int)pData - (int)pModule;
561 if (!READ( ne_header.entry_tab_offset,
562 ne_header.entry_tab_length,
563 pData )) return (HMODULE)11; /* invalid exe */
564 pData += ne_header.entry_tab_length;
566 /* Get the non-resident names table */
568 if (ne_header.nrname_tab_length)
570 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
571 hModule, FALSE, FALSE, FALSE );
572 if (!pModule->nrname_handle) return (HMODULE)11; /* invalid exe */
573 buffer = GlobalLock( pModule->nrname_handle );
574 lseek( fd, ne_header.nrname_tab_offset, SEEK_SET );
575 if (read( fd, buffer, ne_header.nrname_tab_length )
576 != ne_header.nrname_tab_length) return (HMODULE)11; /* invalid exe */
578 else pModule->nrname_handle = 0;
580 /* Allocate a segment for the implicitly-loaded DLLs */
582 if (pModule->modref_count)
584 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
585 (pModule->modref_count+1)*sizeof(HMODULE),
586 hModule, FALSE, FALSE, FALSE );
587 if (!pModule->dlls_to_init) return (HMODULE)11; /* invalid exe */
589 else pModule->dlls_to_init = 0;
591 if (debugging_module) MODULE_PrintModule( hModule );
592 pModule->next = hFirstModule;
593 hFirstModule = hModule;
594 return hModule;
598 /***********************************************************************
599 * MODULE_GetOrdinal
601 * Lookup the ordinal for a given name.
603 WORD MODULE_GetOrdinal( HMODULE hModule, char *name )
605 char buffer[256], *cpnt;
606 BYTE len;
607 NE_MODULE *pModule;
609 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
611 dprintf_module( stddeb, "MODULE_GetOrdinal("NPFMT",'%s')\n",
612 hModule, name );
614 /* First handle names of the form '#xxxx' */
616 if (name[0] == '#') return atoi( name + 1 );
618 /* Now copy and uppercase the string */
620 strcpy( buffer, name );
621 AnsiUpper( buffer );
622 len = strlen( buffer );
624 /* First search the resident names */
626 cpnt = (char *)pModule + pModule->name_table;
628 /* Skip the first entry (module name) */
629 cpnt += *cpnt + 1 + sizeof(WORD);
630 while (*cpnt)
632 dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
633 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
635 dprintf_module( stddeb, " Found: ordinal=%d\n",
636 *(WORD *)(cpnt + *cpnt + 1) );
637 return *(WORD *)(cpnt + *cpnt + 1);
639 cpnt += *cpnt + 1 + sizeof(WORD);
642 /* Now search the non-resident names table */
644 if (!pModule->nrname_handle) return 0; /* No non-resident table */
645 cpnt = (char *)GlobalLock( pModule->nrname_handle );
647 /* Skip the first entry (module description string) */
648 cpnt += *cpnt + 1 + sizeof(WORD);
649 while (*cpnt)
651 dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
652 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
654 dprintf_module( stddeb, " Found: ordinal=%d\n",
655 *(WORD *)(cpnt + *cpnt + 1) );
656 return *(WORD *)(cpnt + *cpnt + 1);
658 cpnt += *cpnt + 1 + sizeof(WORD);
660 return 0;
664 /***********************************************************************
665 * MODULE_GetEntryPoint
667 * Return the entry point for a given ordinal.
669 DWORD MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
671 NE_MODULE *pModule;
672 WORD curOrdinal = 1;
673 BYTE *p;
674 WORD sel, offset;
676 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
678 p = (BYTE *)pModule + pModule->entry_table;
679 while (*p && (curOrdinal + *p <= ordinal))
681 /* Skipping this bundle */
682 curOrdinal += *p;
683 switch(p[1])
685 case 0: p += 2; break; /* unused */
686 case 0xff: p += 2 + *p * 6; break; /* moveable */
687 default: p += 2 + *p * 3; break; /* fixed */
690 if (!*p) return 0;
692 switch(p[1])
694 case 0: /* unused */
695 return 0;
696 case 0xff: /* moveable */
697 p += 2 + 6 * (ordinal - curOrdinal);
698 sel = p[3];
699 offset = *(WORD *)(p + 4);
700 break;
701 default: /* fixed */
702 sel = p[1];
703 p += 2 + 3 * (ordinal - curOrdinal);
704 offset = *(WORD *)(p + 1);
705 break;
708 if (sel == 0xfe) sel = 0xffff; /* constant entry */
709 else sel = (WORD)NE_SEG_TABLE(pModule)[sel-1].selector;
710 return MAKELONG( offset, sel );
714 /***********************************************************************
715 * MODULE_SetEntryPoint
717 * Change the value of an entry point. Use with caution!
718 * It can only change the offset value, not the selector.
720 BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset )
722 NE_MODULE *pModule;
723 WORD curOrdinal = 1;
724 BYTE *p;
726 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
728 p = (BYTE *)pModule + pModule->entry_table;
729 while (*p && (curOrdinal + *p <= ordinal))
731 /* Skipping this bundle */
732 curOrdinal += *p;
733 switch(p[1])
735 case 0: p += 2; break; /* unused */
736 case 0xff: p += 2 + *p * 6; break; /* moveable */
737 default: p += 2 + *p * 3; break; /* fixed */
740 if (!*p) return FALSE;
742 switch(p[1])
744 case 0: /* unused */
745 return FALSE;
746 case 0xff: /* moveable */
747 p += 2 + 6 * (ordinal - curOrdinal);
748 *(WORD *)(p + 4) = offset;
749 break;
750 default: /* fixed */
751 p += 2 + 3 * (ordinal - curOrdinal);
752 *(WORD *)(p + 1) = offset;
753 break;
755 return TRUE;
759 /***********************************************************************
760 * MODULE_GetEntryPointName
762 * Return the entry point name for a given ordinal.
763 * Used only by relay debugging.
764 * Warning: returned pointer is to a Pascal-type string.
766 LPSTR MODULE_GetEntryPointName( HMODULE hModule, WORD ordinal )
768 register char *cpnt;
769 NE_MODULE *pModule;
771 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
773 /* First search the resident names */
775 cpnt = (char *)pModule + pModule->name_table;
776 while (*cpnt)
778 cpnt += *cpnt + 1 + sizeof(WORD);
779 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
782 /* Now search the non-resident names table */
784 if (!pModule->nrname_handle) return 0; /* No non-resident table */
785 cpnt = (char *)GlobalLock( pModule->nrname_handle );
786 while (*cpnt)
788 cpnt += *cpnt + 1 + sizeof(WORD);
789 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
791 return NULL;
795 /***********************************************************************
796 * MODULE_GetModuleName
798 LPSTR MODULE_GetModuleName( HMODULE hModule )
800 NE_MODULE *pModule;
801 BYTE *p, len;
802 static char buffer[10];
804 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return NULL;
805 p = (BYTE *)pModule + pModule->name_table;
806 len = MIN( *p, 8 );
807 memcpy( buffer, p + 1, len );
808 buffer[len] = '\0';
809 return buffer;
813 /**********************************************************************
814 * MODULE_FindModule
816 * Find a module from a path name.
818 HMODULE MODULE_FindModule( LPCSTR path )
820 HMODULE hModule = hFirstModule;
821 LPCSTR filename, dotptr, modulepath, modulename;
822 BYTE len, *name_table;
824 if (!(filename = strrchr( path, '\\' ))) filename = path;
825 else filename++;
826 if ((dotptr = strrchr( filename, '.' )) != NULL)
827 len = (BYTE)(dotptr - filename);
828 else len = strlen( filename );
830 while(hModule)
832 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
833 if (!pModule) break;
834 modulepath = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
835 if (!(modulename = strrchr( modulepath, '\\' )))
836 modulename = modulepath;
837 else modulename++;
838 if (!strcasecmp( modulename, filename )) return hModule;
840 name_table = (BYTE *)pModule + pModule->name_table;
841 if ((*name_table == len) && !strncasecmp(filename, name_table+1, len))
842 return hModule;
843 hModule = pModule->next;
845 return 0;
849 /**********************************************************************
850 * MODULE_FreeModule
852 * Remove a module from memory.
854 static void MODULE_FreeModule( HMODULE hModule )
856 HMODULE *hPrevModule;
857 NE_MODULE *pModule;
858 SEGTABLEENTRY *pSegment;
859 HMODULE *pModRef;
860 int i;
862 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return;
863 if (pModule->flags & NE_FFLAGS_BUILTIN)
864 return; /* Can't free built-in module */
866 /* FIXME: should call the exit code for the library here */
868 /* Remove it from the linked list */
870 hPrevModule = &hFirstModule;
871 while (*hPrevModule && (*hPrevModule != hModule))
873 hPrevModule = &((NE_MODULE *)GlobalLock( *hPrevModule ))->next;
875 if (*hPrevModule) *hPrevModule = pModule->next;
877 /* Free all the segments */
879 pSegment = NE_SEG_TABLE( pModule );
880 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
882 GlobalFree( pSegment->selector );
885 /* Free the referenced modules */
887 pModRef = NE_MODULE_TABLE( pModule );
888 for (i = 0; i < pModule->modref_count; i++, pModRef++)
890 FreeModule( *pModRef );
893 /* Free the module storage */
895 if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
896 if (pModule->dlls_to_init) GlobalFree( pModule->dlls_to_init );
897 GlobalFree( hModule );
899 /* Remove module from cache */
901 if (hCachedModule == hModule) hCachedModule = 0;
905 HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params);
907 /**********************************************************************
908 * LoadModule (KERNEL.45)
910 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
912 HMODULE hModule;
913 HANDLE hInstance, hPrevInstance;
914 NE_MODULE *pModule;
915 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
916 #ifndef WINELIB
917 WORD *pModRef, *pDLLs;
918 int i, fd;
920 hModule = MODULE_FindModule( name );
922 if (!hModule) /* We have to load the module */
924 OFSTRUCT ofs;
926 /* Try to load the built-in first if not disabled */
927 if ((hModule = MODULE_LoadBuiltin( name, FALSE ))) return hModule;
929 if (strchr( name, '/' )) name = DOS_GetDosFileName( name );
930 if ((fd = OpenFile( name, &ofs, OF_READ )) == -1)
932 /* Now try the built-in even if disabled */
933 if ((hModule = MODULE_LoadBuiltin( name, TRUE )))
935 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
936 return hModule;
938 return 2; /* File not found */
941 /* Create the module structure */
943 if ((hModule = MODULE_LoadExeHeader( fd, &ofs )) < 32)
945 if(hModule == 21)
946 return PE_LoadModule(fd,&ofs,paramBlock);
947 close( fd );
948 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
949 name, hModule );
950 return hModule;
952 pModule = (NE_MODULE *)GlobalLock( hModule );
954 /* Allocate the segments for this module */
956 MODULE_CreateSegments( hModule );
958 hPrevInstance = 0;
959 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
961 /* Load the referenced DLLs */
963 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
964 pDLLs = (WORD *)GlobalLock( pModule->dlls_to_init );
965 for (i = 0; i < pModule->modref_count; i++, pModRef++)
967 char buffer[256];
968 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
969 memcpy( buffer, pstr + 1, *pstr );
970 strcpy( buffer + *pstr, ".dll" );
971 dprintf_module( stddeb, "Loading '%s'\n", buffer );
972 if (!(*pModRef = MODULE_FindModule( buffer )))
974 /* If the DLL is not loaded yet, load it and store */
975 /* its handle in the list of DLLs to initialize. */
976 HMODULE hDLL;
978 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
980 char *p;
982 /* Try with prepending the path of the current module */
983 GetModuleFileName( hModule, buffer, 256 );
984 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
985 memcpy( p + 1, pstr + 1, *pstr );
986 strcpy( p + 1 + *pstr, ".dll" );
987 hDLL = LoadModule( buffer, (LPVOID)-1 );
989 if (hDLL < 32)
991 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
992 buffer, name, hDLL );
993 return 2; /* file not found */
995 *pModRef = GetExePtr( hDLL );
996 *pDLLs++ = *pModRef;
998 else /* Increment the reference count of the DLL */
1000 NE_MODULE *pOldDLL = (NE_MODULE *)GlobalLock( *pModRef );
1001 if (pOldDLL) pOldDLL->count++;
1005 /* Load the segments */
1007 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1009 /* Handle self loading modules */
1010 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1011 SELFLOADHEADER *selfloadheader;
1012 HMODULE hselfload = GetModuleHandle("WINPROCS");
1013 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1014 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1015 "Support for self-loading modules is very experimental\n",
1016 *((BYTE*)pModule + pModule->name_table),
1017 *((BYTE*)pModule + pModule->name_table),
1018 (char *)pModule + pModule->name_table + 1);
1019 NE_LoadSegment( hModule, 1 );
1020 selfloadheader = (SELFLOADHEADER *)
1021 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1022 selfloadheader->EntryAddrProc =
1023 MODULE_GetEntryPoint(hselfload,27);
1024 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1025 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1026 pModule->self_loading_sel = GlobalHandleToSel(
1027 GLOBAL_Alloc (GMEM_ZEROINIT,
1028 0xFF00, hModule, FALSE, FALSE, FALSE)
1030 oldss = IF1632_Saved16_ss;
1031 oldsp = IF1632_Saved16_sp;
1032 IF1632_Saved16_ss = pModule->self_loading_sel;
1033 IF1632_Saved16_sp = 0xFF00;
1034 if (!IF1632_Stack32_base) {
1035 STACK32FRAME* frame32;
1036 char *stack32Top;
1037 /* Setup an initial 32 bit stack frame */
1038 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1039 hModule, FALSE, FALSE,
1040 FALSE );
1042 /* Create the 32-bit stack frame */
1044 *(DWORD *)GlobalLock(hInitialStack32) = 0xDEADBEEF;
1045 stack32Top = (char*)GlobalLock(hInitialStack32) +
1046 0x10000;
1047 frame32 = (STACK32FRAME *)stack32Top - 1;
1048 frame32->saved_esp = (DWORD)stack32Top;
1049 frame32->edi = 0;
1050 frame32->esi = 0;
1051 frame32->edx = 0;
1052 frame32->ecx = 0;
1053 frame32->ebx = 0;
1054 frame32->ebp = 0;
1055 frame32->retaddr = 0;
1056 frame32->codeselector = WINE_CODE_SELECTOR;
1057 /* pTask->esp = (DWORD)frame32; */
1058 IF1632_Stack32_base = WIN16_GlobalLock(hInitialStack32);
1061 CallTo16_word_ww (selfloadheader->BootApp,
1062 pModule->self_loading_sel, hModule, fd);
1063 /* some BootApp procs overwrite the selector of dgroup */
1064 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1065 IF1632_Saved16_ss = oldss;
1066 IF1632_Saved16_sp = oldsp;
1067 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1068 if (hInitialStack32){
1069 GlobalUnlock (hInitialStack32);
1070 GlobalFree (hInitialStack32);
1071 IF1632_Stack32_base = hInitialStack32 = 0;
1074 else
1076 for (i = 1; i <= pModule->seg_count; i++)
1077 NE_LoadSegment( hModule, i );
1080 /* Fixup the functions prologs */
1082 NE_FixupPrologs( hModule );
1084 /* Make sure the usage count is 1 on the first loading of */
1085 /* the module, even if it contains circular DLL references */
1087 pModule->count = 1;
1089 /* Clear built-in flag in case it was set in the EXE file */
1091 pModule->flags &= ~NE_FFLAGS_BUILTIN;
1093 else
1095 pModule = (NE_MODULE *)GlobalLock( hModule );
1096 hPrevInstance = MODULE_GetInstance( hModule );
1097 hInstance = MODULE_CreateInstance( hModule, params );
1098 if (hInstance != hPrevInstance) /* not a library */
1099 NE_LoadSegment( hModule, pModule->dgroup );
1100 pModule->count++;
1102 #else
1103 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE) );
1104 pModule = (NE_MODULE *)GlobalLock( hModule );
1105 pModule->count = 1;
1106 pModule->magic = 0x454e;
1107 hPrevInstance = 0;
1108 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1109 #endif /* WINELIB */
1111 /* Create a task for this instance */
1113 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1115 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1116 params->hEnvironment,
1117 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1118 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1121 return hInstance;
1125 /**********************************************************************
1126 * FreeModule (KERNEL.46)
1128 BOOL FreeModule( HANDLE hModule )
1130 NE_MODULE *pModule;
1132 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1133 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
1135 dprintf_module( stddeb, "FreeModule: %s count %d\n",
1136 MODULE_GetModuleName(hModule), pModule->count );
1137 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1138 return TRUE;
1142 /**********************************************************************
1143 * GetModuleHandle (KERNEL.47)
1145 HMODULE WIN16_GetModuleHandle( SEGPTR name )
1147 #ifdef WINELIB32
1148 if (HIWORD(name) == 0) return GetExePtr( name );
1149 #else
1150 if (HIWORD(name) == 0) return GetExePtr( LOWORD(name) );
1151 #endif
1152 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1155 HMODULE GetModuleHandle( LPCSTR name )
1157 return MODULE_FindModule( name );
1161 /**********************************************************************
1162 * GetModuleUsage (KERNEL.48)
1164 int GetModuleUsage( HANDLE hModule )
1166 NE_MODULE *pModule;
1168 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1169 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
1170 dprintf_module( stddeb, "GetModuleUsage("NPFMT"): returning %d\n",
1171 hModule, pModule->count );
1172 return pModule->count;
1176 /**********************************************************************
1177 * GetModuleFileName (KERNEL.49)
1179 int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1181 NE_MODULE *pModule;
1182 char *name;
1184 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1185 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
1186 name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
1187 lstrcpyn( lpFileName, name, nSize );
1188 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1189 return strlen(lpFileName);
1193 /***********************************************************************
1194 * LoadLibrary (KERNEL.95)
1196 HANDLE LoadLibrary( LPCSTR libname )
1198 #ifdef WINELIB
1199 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1200 WINELIB_UNIMP("LoadLibrary()");
1201 return (HANDLE)0;
1202 #else
1203 HANDLE handle;
1205 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1207 /* This does not increment the module reference count, and will
1208 * therefore cause crashes on FreeLibrary calls.
1209 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1211 handle = LoadModule( libname, (LPVOID)-1 );
1212 if (handle == (HANDLE)2) /* file not found */
1214 char buffer[256];
1215 strcpy( buffer, libname );
1216 strcat( buffer, ".dll" );
1217 handle = LoadModule( buffer, (LPVOID)-1 );
1219 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
1220 return handle;
1221 #endif
1225 /***********************************************************************
1226 * FreeLibrary (KERNEL.96)
1228 void FreeLibrary( HANDLE handle )
1230 dprintf_module( stddeb,"FreeLibrary: "NPFMT"\n", handle );
1231 FreeModule( handle );
1235 /***********************************************************************
1236 * WinExec (KERNEL.166)
1238 HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1240 LOADPARAMS params;
1241 HLOCAL cmdShowHandle, cmdLineHandle;
1242 HANDLE handle;
1243 WORD *cmdShowPtr;
1244 char *p, *cmdline, filename[256];
1246 if (!(cmdShowHandle = GlobalAlloc( 0, 2 * sizeof(WORD) ))) return 0;
1247 if (!(cmdLineHandle = GlobalAlloc( 0, 256 ))) return 0;
1249 /* Store nCmdShow */
1251 cmdShowPtr = (WORD *)GlobalLock( cmdShowHandle );
1252 cmdShowPtr[0] = 2;
1253 cmdShowPtr[1] = nCmdShow;
1255 /* Build the filename and command-line */
1257 cmdline = (char *)GlobalLock( cmdLineHandle );
1258 strncpy( filename, lpCmdLine, 256 );
1259 filename[255] = '\0';
1260 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1261 if (*p)
1263 strncpy( cmdline, p + 1, 128 );
1264 cmdline[127] = '\0';
1266 else cmdline[0] = '\0';
1267 *p = '\0';
1269 /* Now load the executable file */
1271 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1272 params.cmdLine = (SEGPTR)WIN16_GlobalLock( cmdLineHandle );
1273 params.showCmd = (SEGPTR)WIN16_GlobalLock( cmdShowHandle );
1274 params.reserved = 0;
1275 handle = LoadModule( filename, &params );
1276 if (handle == (HANDLE)2) /* file not found */
1278 /* Check that the original file name did not have a suffix */
1279 p = strrchr(filename, '.');
1280 if (p && !(strchr(p, '/') || strchr(p, '\\')))
1281 return handle; /* filename already includes a suffix! */
1282 strcat( filename, ".exe" );
1283 handle = LoadModule( filename, &params );
1286 GlobalFree( cmdShowHandle );
1287 GlobalFree( cmdLineHandle );
1289 #if 0
1290 if (handle < (HANDLE)32) /* Error? */
1291 return handle;
1293 /* FIXME: Yield never returns!
1294 We may want to run more applications or start the debugger
1295 before calling Yield. If we don't Yield will be called immdiately
1296 after returning. Why is it needed for Word anyway? */
1297 Yield(); /* program is executed immediately ....needed for word */
1299 #endif
1300 return handle;
1304 /***********************************************************************
1305 * GetProcAddress (KERNEL.50)
1307 FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
1309 WORD ordinal;
1310 SEGPTR ret;
1312 if (!hModule) hModule = GetCurrentTask();
1313 hModule = GetExePtr( hModule );
1315 if (HIWORD(name) != 0)
1317 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1318 dprintf_module( stddeb, "GetProcAddress: "NPFMT" '%s'\n",
1319 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1321 else
1323 ordinal = LOWORD(name);
1324 dprintf_module( stddeb, "GetProcAddress: "NPFMT" %04x\n",
1325 hModule, ordinal );
1327 if (!ordinal) return (FARPROC)0;
1329 ret = MODULE_GetEntryPoint( hModule, ordinal );
1331 dprintf_module( stddeb, "GetProcAddress: returning %08lx\n", ret );
1332 return (FARPROC)ret;
1336 /**********************************************************************
1337 * GetExpWinVer (KERNEL.167)
1339 WORD GetExpWinVer( HMODULE hModule )
1341 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
1343 return pModule->expected_version;
1347 /***********************************************************************
1348 * GetWndProcEntry16 (not a Windows API function)
1350 * Return an entry point from the WINPROCS dll.
1352 #ifndef WINELIB
1353 WNDPROC GetWndProcEntry16( char *name )
1355 WORD ordinal;
1356 static HMODULE hModule = 0;
1358 if (!hModule) hModule = GetModuleHandle( "WINPROCS" );
1359 ordinal = MODULE_GetOrdinal( hModule, name );
1360 return MODULE_GetEntryPoint( hModule, ordinal );
1362 #endif
1365 /**********************************************************************
1366 * ModuleFirst (TOOLHELP.59)
1368 BOOL ModuleFirst( MODULEENTRY *lpme )
1370 lpme->wNext = hFirstModule;
1371 return ModuleNext( lpme );
1375 /**********************************************************************
1376 * ModuleNext (TOOLHELP.60)
1378 BOOL ModuleNext( MODULEENTRY *lpme )
1380 NE_MODULE *pModule;
1382 if (!lpme->wNext) return FALSE;
1383 if (!(pModule = (NE_MODULE *)GlobalLock( lpme->wNext ))) return FALSE;
1384 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1385 MAX_MODULE_NAME );
1386 lpme->szModule[MAX_MODULE_NAME] = '\0';
1387 lpme->hModule = lpme->wNext;
1388 lpme->wcUsage = pModule->count;
1389 strncpy( lpme->szExePath,
1390 ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename,
1391 MAX_PATH );
1392 lpme->szExePath[MAX_PATH] = '\0';
1393 lpme->wNext = pModule->next;
1394 return TRUE;
1398 /**********************************************************************
1399 * ModuleFindName (TOOLHELP.61)
1401 BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1403 lpme->wNext = GetModuleHandle( name );
1404 return ModuleNext( lpme );
1408 /**********************************************************************
1409 * ModuleFindHandle (TOOLHELP.62)
1411 BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
1413 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1414 lpme->wNext = hModule;
1415 return ModuleNext( lpme );