Release 951105
[wine/multimedia.git] / loader / module.c
blob7186c931ca5442b923bcbda34dc2d3dab4ac6fe4
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 */
33 static HANDLE hInitialStack32 = 0;
34 /***********************************************************************
35 * MODULE_LoadBuiltin
37 * Load a built-in module. If the 'force' parameter is FALSE, we only
38 * load the module if it has not been disabled via the -dll option.
40 #ifndef WINELIB /* JBP: Not really allowed in libwine.a (FIXME:?) */
41 static HMODULE MODULE_LoadBuiltin( LPCSTR name, BOOL force )
43 HMODULE hModule;
44 NE_MODULE *pModule;
45 SEGTABLEENTRY *pSegTable;
46 struct dll_table_s *table;
47 int i;
48 char dllname[16], *p;
50 /* Fix the name in case we have a full path and extension */
52 if ((p = strrchr( name, '\\' ))) name = p + 1;
53 strncpy( dllname, name, 15 );
54 dllname[15] = '\0';
55 if ((p = strrchr( dllname, '.' ))) *p = '\0';
57 for (i = 0, table = dll_builtin_table; i < N_BUILTINS; i++, table++)
58 if (!strcasecmp( table->name, dllname )) break;
59 if (i >= N_BUILTINS) return 0;
60 if (!table->used && !force) return 0;
62 hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, table->module_start,
63 table->module_end - table->module_start,
64 0, FALSE, FALSE, FALSE, NULL );
65 if (!hModule) return 0;
66 FarSetOwner( hModule, hModule );
68 table->hModule = hModule;
70 dprintf_module( stddeb, "Built-in %s: hmodule=%04x\n",
71 table->name, hModule );
73 /* Allocate the code segment */
75 pModule = (NE_MODULE *)GlobalLock( hModule );
76 pSegTable = NE_SEG_TABLE( pModule );
78 pSegTable->selector = GLOBAL_CreateBlock( GMEM_FIXED, table->code_start,
79 pSegTable->minsize, hModule,
80 TRUE, TRUE, FALSE, NULL );
81 if (!pSegTable->selector) return 0;
82 pSegTable++;
84 /* Allocate the data segment */
86 pSegTable->selector = GLOBAL_Alloc( GMEM_FIXED, pSegTable->minsize,
87 hModule, FALSE, FALSE, FALSE );
88 if (!pSegTable->selector) return 0;
89 memcpy( GlobalLock( pSegTable->selector ),
90 table->data_start, pSegTable->minsize );
92 pModule->next = hFirstModule;
93 hFirstModule = hModule;
94 return hModule;
96 #endif
98 /***********************************************************************
99 * MODULE_Init
101 * Create the built-in modules.
103 BOOL MODULE_Init(void)
105 /* For these, built-in modules are always used */
107 #ifndef WINELIB32
108 if (!MODULE_LoadBuiltin( "KERNEL", TRUE ) ||
109 !MODULE_LoadBuiltin( "GDI", TRUE ) ||
110 !MODULE_LoadBuiltin( "USER", TRUE ) ||
111 !MODULE_LoadBuiltin( "WINPROCS", TRUE )) return FALSE;
113 #else
114 fprintf(stderr, "JBP: MODULE_Init() ignored.\n");
115 #endif
116 /* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
118 MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
119 return TRUE;
123 /***********************************************************************
124 * MODULE_PrintModule
126 void MODULE_PrintModule( HMODULE hmodule )
128 int i, ordinal;
129 SEGTABLEENTRY *pSeg;
130 BYTE *pstr;
131 WORD *pword;
132 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hmodule );
134 /* Dump the module info */
136 printf( "Module "NPFMT":\n", hmodule );
137 printf( "count=%d flags=%04x heap=%d stack=%d\n",
138 pModule->count, pModule->flags,
139 pModule->heap_size, pModule->stack_size );
140 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
141 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
142 pModule->seg_count, pModule->modref_count );
143 printf( "os_flags=%d swap_area=%d version=%04x\n",
144 pModule->os_flags, pModule->min_swap_area,
145 pModule->expected_version );
147 /* Dump the file info */
149 printf( "Filename: '%s'\n",
150 ((LOADEDFILEINFO *)((BYTE *)pModule + pModule->fileinfo))->filename );
152 /* Dump the segment table */
154 printf( "\nSegment table:\n" );
155 pSeg = NE_SEG_TABLE( pModule );
156 for (i = 0; i < pModule->seg_count; i++, pSeg++)
157 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel="NPFMT"\n",
158 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
159 pSeg->minsize, pSeg->selector );
161 /* Dump the resource table */
163 printf( "\nResource table:\n" );
164 if (pModule->res_table)
166 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
167 printf( "Alignment: %d\n", *pword++ );
168 while (*pword)
170 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
171 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
172 printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
173 for (i = 0; i < ptr->count; i++, pname++)
174 printf( "offset=%d len=%d id=%04x\n",
175 pname->offset, pname->length, pname->id );
176 pword = (WORD *)pname;
179 else printf( "None\n" );
181 /* Dump the resident name table */
183 printf( "\nResident-name table:\n" );
184 pstr = (char *)pModule + pModule->name_table;
185 while (*pstr)
187 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
188 *(WORD *)(pstr + *pstr + 1) );
189 pstr += *pstr + 1 + sizeof(WORD);
192 /* Dump the module reference table */
194 printf( "\nModule ref table:\n" );
195 if (pModule->modref_table)
197 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
198 for (i = 0; i < pModule->modref_count; i++, pword++)
200 char *name = (char *)pModule + pModule->import_table + *pword;
201 printf( "%d: %04x -> '%*.*s'\n",
202 i, *pword, *name, *name, name + 1 );
205 else printf( "None\n" );
207 /* Dump the entry table */
209 printf( "\nEntry table:\n" );
210 pstr = (char *)pModule + pModule->entry_table;
211 ordinal = 1;
212 while (*pstr)
214 printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
215 if (!pstr[1])
217 ordinal += *pstr;
218 pstr += 2;
220 else if ((BYTE)pstr[1] == 0xff) /* moveable */
222 struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
223 for (i = 0; i < *pstr; i++, pe++)
224 printf( "%d: %02x:%04x (moveable)\n",
225 ordinal++, pe->seg_number, pe->offset );
226 pstr = (char *)pe;
228 else /* fixed */
230 struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
231 for (i = 0; i < *pstr; i++, pe++)
232 printf( "%d: %04x (fixed)\n",
233 ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
234 pstr = (char *)pe;
238 /* Dump the non-resident names table */
240 printf( "\nNon-resident names table:\n" );
241 if (pModule->nrname_handle)
243 pstr = (char *)GlobalLock( pModule->nrname_handle );
244 while (*pstr)
246 printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
247 *(WORD *)(pstr + *pstr + 1) );
248 pstr += *pstr + 1 + sizeof(WORD);
251 printf( "\n" );
255 /***********************************************************************
256 * MODULE_OpenFile
258 int MODULE_OpenFile( HMODULE hModule )
260 NE_MODULE *pModule;
261 char *name;
263 static int cachedfd = -1;
265 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
266 dprintf_module( stddeb, "MODULE_OpenFile("NPFMT") cache: mod="NPFMT" fd=%d\n",
267 hModule, hCachedModule, cachedfd );
268 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return -1;
269 if (hCachedModule == hModule) return cachedfd;
270 close( cachedfd );
271 hCachedModule = hModule;
272 name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
273 cachedfd = open( DOS_GetUnixFileName( name ), O_RDONLY );
274 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
275 name, cachedfd );
276 return cachedfd;
278 /***********************************************************************
279 * MODULE_Ne2MemFlags
282 /* This function translates NE segment flags to GlobalAlloc flags */
284 static WORD MODULE_Ne2MemFlags(WORD flags)
286 WORD memflags = 0;
287 #if 0
288 if (flags & NE_SEGFLAGS_DISCARDABLE)
289 memflags |= GMEM_DISCARDABLE;
290 if (flags & NE_SEGFLAGS_MOVEABLE ||
291 ( ! (flags & NE_SEGFLAGS_DATA) &&
292 ! (flags & NE_SEGFLAGS_LOADED) &&
293 ! (flags & NE_SEGFLAGS_ALLOCATED)
296 memflags |= GMEM_MOVEABLE;
297 memflags |= GMEM_ZEROINIT;
298 #else
299 memflags = GMEM_ZEROINIT | GMEM_FIXED;
300 return memflags;
301 #endif
304 /***********************************************************************
305 * MODULE_AllocateSegment (WINPROCS.26)
308 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
310 WORD size = wSize << wElem;
311 HANDLE hMem = GlobalAlloc( MODULE_Ne2MemFlags(wFlags), size);
312 #ifdef WINELIB32
313 return (DWORD)GlobalLock(hMem);
314 #else
315 WORD selector = HIWORD(GlobalLock(hMem));
316 return MAKELONG(hMem, selector);
317 #endif
320 /***********************************************************************
321 * MODULE_CreateSegments
323 #ifndef WINELIB32
324 static BOOL MODULE_CreateSegments( HMODULE hModule )
326 SEGTABLEENTRY *pSegment;
327 NE_MODULE *pModule;
328 int i, minsize;
330 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
331 pSegment = NE_SEG_TABLE( pModule );
332 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
334 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
335 if (i == pModule->ss) minsize += pModule->stack_size;
336 /* The DGROUP is allocated by MODULE_CreateInstance */
337 if (i == pModule->dgroup) continue;
338 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
339 minsize, hModule,
340 !(pSegment->flags & NE_SEGFLAGS_DATA),
341 FALSE,
342 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
343 if (!pSegment->selector) return FALSE;
346 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
347 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
348 return TRUE;
350 #endif
353 /***********************************************************************
354 * MODULE_GetInstance
356 #ifndef WINELIB32
357 static HINSTANCE MODULE_GetInstance( HMODULE hModule )
359 SEGTABLEENTRY *pSegment;
360 NE_MODULE *pModule;
362 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
363 if (pModule->dgroup == 0) return hModule;
365 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
367 return pSegment->selector;
369 #endif
372 /***********************************************************************
373 * MODULE_CreateInstance
375 HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
377 SEGTABLEENTRY *pSegment;
378 NE_MODULE *pModule;
379 int minsize;
380 HINSTANCE hNewInstance, hPrevInstance;
382 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
383 if (pModule->dgroup == 0) return hModule;
385 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
386 hPrevInstance = pSegment->selector;
388 /* if it's a library, create a new instance only the first time */
389 if (hPrevInstance)
391 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
392 if (params == (LOADPARAMS*)-1) return hPrevInstance;
395 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
396 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
397 minsize += pModule->heap_size;
398 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
399 minsize, hModule, FALSE, FALSE, FALSE );
400 if (!hNewInstance) return 0;
401 pSegment->selector = hNewInstance;
402 return hNewInstance;
406 /***********************************************************************
407 * MODULE_LoadExeHeader
409 HMODULE MODULE_LoadExeHeader( int fd, OFSTRUCT *ofs )
411 struct mz_header_s mz_header;
412 struct ne_header_s ne_header;
413 int size;
414 HMODULE hModule;
415 NE_MODULE *pModule;
416 BYTE *pData;
417 char *buffer, *fastload = NULL;
418 int fastload_offset = 0, fastload_length = 0;
420 /* Read a block from either the file or the fast-load area. */
421 #define READ(offset,size,buffer) \
422 ((fastload && ((offset) >= fastload_offset) && \
423 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
424 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
425 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
426 read( fd, (buffer), (size) ) == (size)))
428 lseek( fd, 0, SEEK_SET );
429 if ((read( fd, &mz_header, sizeof(mz_header) ) != sizeof(mz_header)) ||
430 (mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11; /* invalid exe */
432 lseek( fd, mz_header.ne_offset, SEEK_SET );
433 if (read( fd, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
434 return (HMODULE)11; /* invalid exe */
436 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21; /* win32 exe */
437 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE)11; /* invalid exe */
439 /* We now have a valid NE header */
441 size = sizeof(NE_MODULE) +
442 /* loaded file info */
443 sizeof(LOADEDFILEINFO) + strlen(ofs->szPathName) +
444 /* segment table */
445 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
446 /* resource table */
447 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
448 /* resident names table */
449 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
450 /* module ref table */
451 ne_header.n_mod_ref_tab * sizeof(WORD) +
452 /* imported names table */
453 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
454 /* entry table length */
455 ne_header.entry_tab_length;
457 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
458 if (!hModule) return (HMODULE)11; /* invalid exe */
459 FarSetOwner( hModule, hModule );
460 pModule = (NE_MODULE *)GlobalLock( hModule );
461 memcpy( pModule, &ne_header, sizeof(NE_MODULE) );
462 pModule->count = 0;
463 pData = (BYTE *)(pModule + 1);
465 /* Read the fast-load area */
467 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
469 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
470 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
471 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
472 fastload_offset, fastload_length );
473 if ((fastload = (char *)malloc( fastload_length )) != NULL)
475 lseek( fd, mz_header.ne_offset + fastload_offset, SEEK_SET );
476 if (read( fd, fastload, fastload_length ) != fastload_length)
478 free( fastload );
479 fastload = NULL;
484 /* Store the filename information */
486 pModule->fileinfo = (int)pData - (int)pModule;
487 ((LOADEDFILEINFO*)pData)->length = sizeof(LOADEDFILEINFO)+strlen(ofs->szPathName);
488 ((LOADEDFILEINFO*)pData)->fixed_media = TRUE;
489 ((LOADEDFILEINFO*)pData)->error = 0;
490 ((LOADEDFILEINFO*)pData)->date = 0;
491 ((LOADEDFILEINFO*)pData)->time = 0;
492 strcpy( ((LOADEDFILEINFO*)pData)->filename, ofs->szPathName );
493 pData += ((LOADEDFILEINFO*)pData)->length--;
495 /* Get the segment table */
497 pModule->seg_table = (int)pData - (int)pModule;
498 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
499 if (buffer)
501 int i;
502 struct ne_segment_table_entry_s *pSeg;
504 if (!READ( ne_header.segment_tab_offset,
505 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
506 buffer )) return (HMODULE)11; /* invalid exe */
507 pSeg = (struct ne_segment_table_entry_s *)buffer;
508 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
510 memcpy( pData, pSeg, sizeof(*pSeg) );
511 pData += sizeof(SEGTABLEENTRY);
513 free( buffer );
515 else return (HMODULE)11; /* invalid exe */
517 /* Get the resource table */
519 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
521 pModule->res_table = (int)pData - (int)pModule;
522 if (!READ(ne_header.resource_tab_offset,
523 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
524 pData )) return (HMODULE)11; /* invalid exe */
525 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
527 else pModule->res_table = 0; /* No resource table */
529 /* Get the resident names table */
531 pModule->name_table = (int)pData - (int)pModule;
532 if (!READ( ne_header.rname_tab_offset,
533 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
534 pData )) return (HMODULE)11; /* invalid exe */
535 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
537 /* Get the module references table */
539 if (ne_header.n_mod_ref_tab > 0)
541 pModule->modref_table = (int)pData - (int)pModule;
542 if (!READ( ne_header.moduleref_tab_offset,
543 ne_header.n_mod_ref_tab * sizeof(WORD),
544 pData )) return (HMODULE)11; /* invalid exe */
545 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
547 else pModule->modref_table = 0; /* No module references */
549 /* Get the imported names table */
551 pModule->import_table = (int)pData - (int)pModule;
552 if (!READ( ne_header.iname_tab_offset,
553 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
554 pData )) return (HMODULE)11; /* invalid exe */
555 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
557 /* Get the entry table */
559 pModule->entry_table = (int)pData - (int)pModule;
560 if (!READ( ne_header.entry_tab_offset,
561 ne_header.entry_tab_length,
562 pData )) return (HMODULE)11; /* invalid exe */
563 pData += ne_header.entry_tab_length;
565 /* Get the non-resident names table */
567 if (ne_header.nrname_tab_length)
569 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
570 hModule, FALSE, FALSE, FALSE );
571 if (!pModule->nrname_handle) return (HMODULE)11; /* invalid exe */
572 buffer = GlobalLock( pModule->nrname_handle );
573 lseek( fd, ne_header.nrname_tab_offset, SEEK_SET );
574 if (read( fd, buffer, ne_header.nrname_tab_length )
575 != ne_header.nrname_tab_length) return (HMODULE)11; /* invalid exe */
577 else pModule->nrname_handle = 0;
579 /* Allocate a segment for the implicitly-loaded DLLs */
581 if (pModule->modref_count)
583 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
584 (pModule->modref_count+1)*sizeof(HMODULE),
585 hModule, FALSE, FALSE, FALSE );
586 if (!pModule->dlls_to_init) return (HMODULE)11; /* invalid exe */
588 else pModule->dlls_to_init = 0;
590 if (debugging_module) MODULE_PrintModule( hModule );
591 pModule->next = hFirstModule;
592 hFirstModule = hModule;
593 return hModule;
597 /***********************************************************************
598 * MODULE_GetOrdinal
600 * Lookup the ordinal for a given name.
602 WORD MODULE_GetOrdinal( HMODULE hModule, char *name )
604 char buffer[256], *cpnt;
605 BYTE len;
606 NE_MODULE *pModule;
608 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
610 dprintf_module( stddeb, "MODULE_GetOrdinal("NPFMT",'%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 dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
632 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
634 dprintf_module( stddeb, " Found: ordinal=%d\n",
635 *(WORD *)(cpnt + *cpnt + 1) );
636 return *(WORD *)(cpnt + *cpnt + 1);
638 cpnt += *cpnt + 1 + sizeof(WORD);
641 /* Now search the non-resident names table */
643 if (!pModule->nrname_handle) return 0; /* No non-resident table */
644 cpnt = (char *)GlobalLock( pModule->nrname_handle );
646 /* Skip the first entry (module description string) */
647 cpnt += *cpnt + 1 + sizeof(WORD);
648 while (*cpnt)
650 dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
651 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
653 dprintf_module( stddeb, " Found: ordinal=%d\n",
654 *(WORD *)(cpnt + *cpnt + 1) );
655 return *(WORD *)(cpnt + *cpnt + 1);
657 cpnt += *cpnt + 1 + sizeof(WORD);
659 return 0;
663 /***********************************************************************
664 * MODULE_GetEntryPoint
666 * Return the entry point for a given ordinal.
668 DWORD MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
670 NE_MODULE *pModule;
671 WORD curOrdinal = 1;
672 BYTE *p;
673 WORD sel, offset;
675 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
677 p = (BYTE *)pModule + pModule->entry_table;
678 while (*p && (curOrdinal + *p <= ordinal))
680 /* Skipping this bundle */
681 curOrdinal += *p;
682 switch(p[1])
684 case 0: p += 2; break; /* unused */
685 case 0xff: p += 2 + *p * 6; break; /* moveable */
686 default: p += 2 + *p * 3; break; /* fixed */
689 if (!*p) return 0;
691 switch(p[1])
693 case 0: /* unused */
694 return 0;
695 case 0xff: /* moveable */
696 p += 2 + 6 * (ordinal - curOrdinal);
697 sel = p[3];
698 offset = *(WORD *)(p + 4);
699 break;
700 default: /* fixed */
701 sel = p[1];
702 p += 2 + 3 * (ordinal - curOrdinal);
703 offset = *(WORD *)(p + 1);
704 break;
707 if (sel == 0xfe) sel = 0xffff; /* constant entry */
708 else sel = NE_SEG_TABLE(pModule)[sel-1].selector;
709 return MAKELONG( offset, sel );
713 /***********************************************************************
714 * MODULE_SetEntryPoint
716 * Change the value of an entry point. Use with caution!
717 * It can only change the offset value, not the selector.
719 BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset )
721 NE_MODULE *pModule;
722 WORD curOrdinal = 1;
723 BYTE *p;
725 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
727 p = (BYTE *)pModule + pModule->entry_table;
728 while (*p && (curOrdinal + *p <= ordinal))
730 /* Skipping this bundle */
731 curOrdinal += *p;
732 switch(p[1])
734 case 0: p += 2; break; /* unused */
735 case 0xff: p += 2 + *p * 6; break; /* moveable */
736 default: p += 2 + *p * 3; break; /* fixed */
739 if (!*p) return FALSE;
741 switch(p[1])
743 case 0: /* unused */
744 return FALSE;
745 case 0xff: /* moveable */
746 p += 2 + 6 * (ordinal - curOrdinal);
747 *(WORD *)(p + 4) = offset;
748 break;
749 default: /* fixed */
750 p += 2 + 3 * (ordinal - curOrdinal);
751 *(WORD *)(p + 1) = offset;
752 break;
754 return TRUE;
758 /***********************************************************************
759 * MODULE_GetEntryPointName
761 * Return the entry point name for a given ordinal.
762 * Used only by relay debugging.
763 * Warning: returned pointer is to a Pascal-type string.
765 LPSTR MODULE_GetEntryPointName( HMODULE hModule, WORD ordinal )
767 register char *cpnt;
768 NE_MODULE *pModule;
770 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
772 /* First search the resident names */
774 cpnt = (char *)pModule + pModule->name_table;
775 while (*cpnt)
777 cpnt += *cpnt + 1 + sizeof(WORD);
778 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
781 /* Now search the non-resident names table */
783 if (!pModule->nrname_handle) return 0; /* No non-resident table */
784 cpnt = (char *)GlobalLock( pModule->nrname_handle );
785 while (*cpnt)
787 cpnt += *cpnt + 1 + sizeof(WORD);
788 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
790 return NULL;
794 /***********************************************************************
795 * MODULE_GetModuleName
797 LPSTR MODULE_GetModuleName( HMODULE hModule )
799 NE_MODULE *pModule;
800 BYTE *p, len;
801 static char buffer[10];
803 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return NULL;
804 p = (BYTE *)pModule + pModule->name_table;
805 len = MIN( *p, 8 );
806 memcpy( buffer, p + 1, len );
807 buffer[len] = '\0';
808 return buffer;
812 /**********************************************************************
813 * MODULE_FindModule
815 * Find a module from a path name.
817 HMODULE MODULE_FindModule( LPCSTR path )
819 HMODULE hModule = hFirstModule;
820 LPCSTR filename, dotptr, modulepath, modulename;
821 BYTE len, *name_table;
823 if (!(filename = strrchr( path, '\\' ))) filename = path;
824 else filename++;
825 if ((dotptr = strrchr( filename, '.' )) != NULL)
826 len = (BYTE)(dotptr - filename);
827 else len = strlen( filename );
829 while(hModule)
831 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
832 if (!pModule) break;
833 modulepath = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
834 if (!(modulename = strrchr( modulepath, '\\' )))
835 modulename = modulepath;
836 else modulename++;
837 if (!strcasecmp( modulename, filename )) return hModule;
839 name_table = (BYTE *)pModule + pModule->name_table;
840 if ((*name_table == len) && !strncasecmp(filename, name_table+1, len))
841 return hModule;
842 hModule = pModule->next;
844 return 0;
848 /**********************************************************************
849 * MODULE_FreeModule
851 * Remove a module from memory.
853 static void MODULE_FreeModule( HMODULE hModule )
855 HMODULE *hPrevModule;
856 NE_MODULE *pModule;
857 SEGTABLEENTRY *pSegment;
858 HMODULE *pModRef;
859 int i;
861 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return;
862 if (pModule->flags & NE_FFLAGS_BUILTIN)
863 return; /* Can't free built-in module */
865 /* FIXME: should call the exit code for the library here */
867 /* Remove it from the linked list */
869 hPrevModule = &hFirstModule;
870 while (*hPrevModule && (*hPrevModule != hModule))
872 hPrevModule = &((NE_MODULE *)GlobalLock( *hPrevModule ))->next;
874 if (*hPrevModule) *hPrevModule = pModule->next;
876 /* Free all the segments */
878 pSegment = NE_SEG_TABLE( pModule );
879 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
881 GlobalFree( pSegment->selector );
884 /* Free the referenced modules */
886 pModRef = NE_MODULE_TABLE( pModule );
887 for (i = 0; i < pModule->modref_count; i++, pModRef++)
889 FreeModule( *pModRef );
892 /* Free the module storage */
894 if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
895 if (pModule->dlls_to_init) GlobalFree( pModule->dlls_to_init );
896 GlobalFree( hModule );
898 /* Remove module from cache */
900 if (hCachedModule == hModule) hCachedModule = 0;
904 HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params);
906 /**********************************************************************
907 * LoadModule (KERNEL.45)
909 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
911 HMODULE hModule;
912 HANDLE hInstance, hPrevInstance;
913 NE_MODULE *pModule;
914 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
915 #ifndef WINELIB /* JBP: Disabled for now in winelib.a */
916 WORD *pModRef, *pDLLs;
917 int i, fd;
919 hModule = MODULE_FindModule( name );
921 if (!hModule) /* We have to load the module */
923 OFSTRUCT ofs;
925 /* Try to load the built-in first if not disabled */
926 if ((hModule = MODULE_LoadBuiltin( name, FALSE ))) return hModule;
928 if (strchr( name, '/' )) name = DOS_GetDosFileName( name );
929 if ((fd = OpenFile( name, &ofs, OF_READ )) == -1)
931 /* Now try the built-in even if disabled */
932 if ((hModule = MODULE_LoadBuiltin( name, TRUE )))
934 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
935 return hModule;
937 return 2; /* File not found */
940 /* Create the module structure */
942 if ((hModule = MODULE_LoadExeHeader( fd, &ofs )) < 32)
944 if(hModule == 21)
945 return PE_LoadModule(fd,&ofs,paramBlock);
946 close( fd );
947 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
948 name, hModule );
949 return hModule;
951 pModule = (NE_MODULE *)GlobalLock( hModule );
953 /* Allocate the segments for this module */
955 MODULE_CreateSegments( hModule );
957 hPrevInstance = 0;
958 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
960 /* Load the referenced DLLs */
962 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
963 pDLLs = (WORD *)GlobalLock( pModule->dlls_to_init );
964 for (i = 0; i < pModule->modref_count; i++, pModRef++)
966 char buffer[256];
967 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
968 memcpy( buffer, pstr + 1, *pstr );
969 strcpy( buffer + *pstr, ".dll" );
970 dprintf_module( stddeb, "Loading '%s'\n", buffer );
971 if (!(*pModRef = MODULE_FindModule( buffer )))
973 /* If the DLL is not loaded yet, load it and store */
974 /* its handle in the list of DLLs to initialize. */
975 HMODULE hDLL;
977 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
979 char *p;
981 /* Try with prepending the path of the current module */
982 GetModuleFileName( hModule, buffer, 256 );
983 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
984 memcpy( p + 1, pstr + 1, *pstr );
985 strcpy( p + 1 + *pstr, ".dll" );
986 hDLL = LoadModule( buffer, (LPVOID)-1 );
988 if (hDLL < 32)
990 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
991 buffer, name, hDLL );
992 return 2; /* file not found */
994 *pModRef = GetExePtr( hDLL );
995 *pDLLs++ = *pModRef;
997 else /* Increment the reference count of the DLL */
999 NE_MODULE *pOldDLL = (NE_MODULE *)GlobalLock( *pModRef );
1000 if (pOldDLL) pOldDLL->count++;
1004 /* Load the segments */
1006 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1008 /* Handle self loading modules */
1009 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1010 SELFLOADHEADER *selfloadheader;
1011 HMODULE hselfload = GetModuleHandle("WINPROCS");
1012 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1013 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1014 "Support for self-loading modules is very experimental\n",
1015 *((BYTE*)pModule + pModule->name_table),
1016 *((BYTE*)pModule + pModule->name_table),
1017 (char *)pModule + pModule->name_table + 1);
1018 NE_LoadSegment( hModule, 1 );
1019 selfloadheader = (SELFLOADHEADER *)
1020 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1021 selfloadheader->EntryAddrProc =
1022 MODULE_GetEntryPoint(hselfload,27);
1023 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1024 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1025 pModule->self_loading_sel = GlobalHandleToSel(
1026 GLOBAL_Alloc (GMEM_ZEROINIT,
1027 0xFF00, hModule, FALSE, FALSE, FALSE)
1029 oldss = IF1632_Saved16_ss;
1030 oldsp = IF1632_Saved16_sp;
1031 IF1632_Saved16_ss = pModule->self_loading_sel;
1032 IF1632_Saved16_sp = 0xFF00;
1033 if (!IF1632_Stack32_base) {
1034 STACK32FRAME* frame32;
1035 char *stack32Top;
1036 /* Setup an initial 32 bit stack frame */
1037 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1038 hModule, FALSE, FALSE,
1039 FALSE );
1041 /* Create the 32-bit stack frame */
1043 *(DWORD *)GlobalLock(hInitialStack32) = 0xDEADBEEF;
1044 stack32Top = (char*)GlobalLock(hInitialStack32) +
1045 0x10000;
1046 frame32 = (STACK32FRAME *)stack32Top - 1;
1047 frame32->saved_esp = (DWORD)stack32Top;
1048 frame32->edi = 0;
1049 frame32->esi = 0;
1050 frame32->edx = 0;
1051 frame32->ecx = 0;
1052 frame32->ebx = 0;
1053 frame32->ebp = 0;
1054 frame32->retaddr = 0;
1055 frame32->codeselector = WINE_CODE_SELECTOR;
1056 /* pTask->esp = (DWORD)frame32; */
1057 IF1632_Stack32_base = WIN16_GlobalLock(hInitialStack32);
1060 CallTo16_word_ww (selfloadheader->BootApp,
1061 pModule->self_loading_sel, hModule, fd);
1062 /* some BootApp procs overwrite the selector of dgroup */
1063 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1064 IF1632_Saved16_ss = oldss;
1065 IF1632_Saved16_sp = oldsp;
1066 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1067 if (hInitialStack32){
1068 GlobalUnlock (hInitialStack32);
1069 GlobalFree (hInitialStack32);
1070 IF1632_Stack32_base = hInitialStack32 = 0;
1073 else
1075 for (i = 1; i <= pModule->seg_count; i++)
1076 NE_LoadSegment( hModule, i );
1079 /* Fixup the functions prologs */
1081 NE_FixupPrologs( hModule );
1083 /* Make sure the usage count is 1 on the first loading of */
1084 /* the module, even if it contains circular DLL references */
1086 pModule->count = 1;
1088 /* Clear built-in flag in case it was set in the EXE file */
1090 pModule->flags &= ~NE_FFLAGS_BUILTIN;
1092 else
1094 pModule = (NE_MODULE *)GlobalLock( hModule );
1095 hPrevInstance = MODULE_GetInstance( hModule );
1096 hInstance = MODULE_CreateInstance( hModule, params );
1097 if (hInstance != hPrevInstance) /* not a library */
1098 NE_LoadSegment( hModule, pModule->dgroup );
1099 pModule->count++;
1101 #else
1102 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE) );
1103 pModule = (NE_MODULE *)GlobalLock( hModule );
1104 pModule->count = 1;
1105 pModule->magic = 0x454e;
1106 hPrevInstance = 0;
1107 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1108 #endif /* WINELIB */
1110 /* Create a task for this instance */
1112 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1114 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1115 params->hEnvironment,
1116 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1117 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1120 return hInstance;
1124 /**********************************************************************
1125 * FreeModule (KERNEL.46)
1127 BOOL FreeModule( HANDLE hModule )
1129 NE_MODULE *pModule;
1131 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1132 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
1134 dprintf_module( stddeb, "FreeModule: %s count %d\n",
1135 MODULE_GetModuleName(hModule), pModule->count );
1136 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1137 return TRUE;
1141 /**********************************************************************
1142 * GetModuleHandle (KERNEL.47)
1144 HMODULE WIN16_GetModuleHandle( SEGPTR name )
1146 #ifdef WINELIB32
1147 if (HIWORD(name) == 0) return GetExePtr( name );
1148 #else
1149 if (HIWORD(name) == 0) return GetExePtr( LOWORD(name) );
1150 #endif
1151 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1154 HMODULE GetModuleHandle( LPCSTR name )
1156 return MODULE_FindModule( name );
1160 /**********************************************************************
1161 * GetModuleUsage (KERNEL.48)
1163 int GetModuleUsage( HANDLE hModule )
1165 NE_MODULE *pModule;
1167 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1168 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
1169 dprintf_module( stddeb, "GetModuleUsage("NPFMT"): returning %d\n",
1170 hModule, pModule->count );
1171 return pModule->count;
1175 /**********************************************************************
1176 * GetModuleFileName (KERNEL.49)
1178 int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1180 NE_MODULE *pModule;
1181 char *name;
1183 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1184 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
1185 name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
1186 strncpy( lpFileName, name, nSize );
1187 lpFileName[nSize-1] = '\0';
1188 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1189 return strlen(lpFileName);
1193 /***********************************************************************
1194 * LoadLibrary (KERNEL.95)
1196 HANDLE LoadLibrary( LPCSTR libname )
1198 HANDLE handle;
1200 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1201 /* This does not increment the module reference count, and will
1202 * therefore cause crashes on FreeLibrary calls.
1203 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1205 handle = LoadModule( libname, (LPVOID)-1 );
1206 if (handle == (HANDLE)2) /* file not found */
1208 char buffer[256];
1209 strcpy( buffer, libname );
1210 strcat( buffer, ".dll" );
1211 handle = LoadModule( buffer, (LPVOID)-1 );
1213 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
1214 return handle;
1218 /***********************************************************************
1219 * FreeLibrary (KERNEL.96)
1221 void FreeLibrary( HANDLE handle )
1223 dprintf_module( stddeb,"FreeLibrary: "NPFMT"\n", handle );
1224 FreeModule( handle );
1228 /***********************************************************************
1229 * WinExec (KERNEL.166)
1231 HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1233 LOADPARAMS params;
1234 HLOCAL cmdShowHandle, cmdLineHandle;
1235 HANDLE handle;
1236 WORD *cmdShowPtr;
1237 char *p, *cmdline, filename[256];
1239 if (!(cmdShowHandle = GlobalAlloc( 0, 2 * sizeof(WORD) ))) return 0;
1240 if (!(cmdLineHandle = GlobalAlloc( 0, 256 ))) return 0;
1242 /* Store nCmdShow */
1244 cmdShowPtr = (WORD *)GlobalLock( cmdShowHandle );
1245 cmdShowPtr[0] = 2;
1246 cmdShowPtr[1] = nCmdShow;
1248 /* Build the filename and command-line */
1250 cmdline = (char *)GlobalLock( cmdLineHandle );
1251 strncpy( filename, lpCmdLine, 256 );
1252 filename[255] = '\0';
1253 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1254 if (*p)
1256 strncpy( cmdline, p + 1, 128 );
1257 cmdline[127] = '\0';
1259 else cmdline[0] = '\0';
1260 *p = '\0';
1262 /* Now load the executable file */
1264 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1265 params.cmdLine = (SEGPTR)WIN16_GlobalLock( cmdLineHandle );
1266 params.showCmd = (SEGPTR)WIN16_GlobalLock( cmdShowHandle );
1267 params.reserved = 0;
1268 handle = LoadModule( filename, &params );
1269 if (handle == (HANDLE)2) /* file not found */
1271 /* Check that the original file name did not have a suffix */
1272 p = strrchr(filename, '.');
1273 if (p && !(strchr(p, '/') || strchr(p, '\\')))
1274 return handle; /* filename already includes a suffix! */
1275 strcat( filename, ".exe" );
1276 handle = LoadModule( filename, &params );
1279 GlobalFree( cmdShowHandle );
1280 GlobalFree( cmdLineHandle );
1282 #if 0
1283 if (handle < (HANDLE)32) /* Error? */
1284 return handle;
1286 /* FIXME: Yield never returns!
1287 We may want to run more applications or start the debugger
1288 before calling Yield. If we don't Yield will be called immdiately
1289 after returning. Why is it needed for Word anyway? */
1290 Yield(); /* program is executed immediately ....needed for word */
1292 #endif
1293 return handle;
1297 /***********************************************************************
1298 * GetProcAddress (KERNEL.50)
1300 FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
1302 WORD ordinal;
1303 SEGPTR ret;
1305 if (!hModule) hModule = GetCurrentTask();
1306 hModule = GetExePtr( hModule );
1308 if (HIWORD(name) != 0)
1310 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1311 dprintf_module( stddeb, "GetProcAddress: "NPFMT" '%s'\n",
1312 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1314 else
1316 ordinal = LOWORD(name);
1317 dprintf_module( stddeb, "GetProcAddress: "NPFMT" %04x\n",
1318 hModule, ordinal );
1320 if (!ordinal) return (FARPROC)0;
1322 ret = MODULE_GetEntryPoint( hModule, ordinal );
1324 dprintf_module( stddeb, "GetProcAddress: returning %08lx\n", ret );
1325 return (FARPROC)ret;
1329 #ifndef WINELIB
1330 /***********************************************************************
1331 * GetWndProcEntry16 (not a Windows API function)
1333 * Return an entry point from the WINPROCS dll.
1335 WNDPROC GetWndProcEntry16( char *name )
1337 WORD ordinal;
1338 static HMODULE hModule = 0;
1340 if (!hModule) hModule = GetModuleHandle( "WINPROCS" );
1341 ordinal = MODULE_GetOrdinal( hModule, name );
1342 return MODULE_GetEntryPoint( hModule, ordinal );
1344 #endif
1347 /**********************************************************************
1348 * ModuleFirst (TOOLHELP.59)
1350 BOOL ModuleFirst( MODULEENTRY *lpme )
1352 lpme->wNext = hFirstModule;
1353 return ModuleNext( lpme );
1357 /**********************************************************************
1358 * ModuleNext (TOOLHELP.60)
1360 BOOL ModuleNext( MODULEENTRY *lpme )
1362 NE_MODULE *pModule;
1364 if (!lpme->wNext) return FALSE;
1365 if (!(pModule = (NE_MODULE *)GlobalLock( lpme->wNext ))) return FALSE;
1366 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1367 MAX_MODULE_NAME );
1368 lpme->szModule[MAX_MODULE_NAME] = '\0';
1369 lpme->hModule = lpme->wNext;
1370 lpme->wcUsage = pModule->count;
1371 strncpy( lpme->szExePath,
1372 ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename,
1373 MAX_PATH );
1374 lpme->szExePath[MAX_PATH] = '\0';
1375 lpme->wNext = pModule->next;
1376 return TRUE;
1380 /**********************************************************************
1381 * ModuleFindName (TOOLHELP.61)
1383 BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1385 lpme->wNext = GetModuleHandle( name );
1386 return ModuleNext( lpme );
1390 /**********************************************************************
1391 * ModuleFindHandle (TOOLHELP.62)
1393 BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
1395 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1396 lpme->wNext = hModule;
1397 return ModuleNext( lpme );