Release 951226
[wine/multimedia.git] / loader / module.c
blobd46529dee6f2d00b14d4719458af0fbb6af702b4
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 if ((cachedfd = open( DOS_GetUnixFileName( name ), O_RDONLY )) == -1)
275 fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module "NPFMT"\n",
276 name, hModule );
277 dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
278 name, cachedfd );
279 return cachedfd;
281 /***********************************************************************
282 * MODULE_Ne2MemFlags
285 /* This function translates NE segment flags to GlobalAlloc flags */
287 static WORD MODULE_Ne2MemFlags(WORD flags)
289 WORD memflags = 0;
290 #if 0
291 if (flags & NE_SEGFLAGS_DISCARDABLE)
292 memflags |= GMEM_DISCARDABLE;
293 if (flags & NE_SEGFLAGS_MOVEABLE ||
294 ( ! (flags & NE_SEGFLAGS_DATA) &&
295 ! (flags & NE_SEGFLAGS_LOADED) &&
296 ! (flags & NE_SEGFLAGS_ALLOCATED)
299 memflags |= GMEM_MOVEABLE;
300 memflags |= GMEM_ZEROINIT;
301 #else
302 memflags = GMEM_ZEROINIT | GMEM_FIXED;
303 return memflags;
304 #endif
307 /***********************************************************************
308 * MODULE_AllocateSegment (WINPROCS.26)
311 DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
313 WORD size = wSize << wElem;
314 HANDLE hMem = GlobalAlloc( MODULE_Ne2MemFlags(wFlags), size);
315 #ifdef WINELIB32
316 return (DWORD)GlobalLock(hMem);
317 #else
318 WORD selector = HIWORD(GlobalLock(hMem));
319 return MAKELONG(hMem, selector);
320 #endif
323 /***********************************************************************
324 * MODULE_CreateSegments
326 #ifndef WINELIB32
327 static BOOL MODULE_CreateSegments( HMODULE hModule )
329 SEGTABLEENTRY *pSegment;
330 NE_MODULE *pModule;
331 int i, minsize;
333 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
334 pSegment = NE_SEG_TABLE( pModule );
335 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
337 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
338 if (i == pModule->ss) minsize += pModule->stack_size;
339 /* The DGROUP is allocated by MODULE_CreateInstance */
340 if (i == pModule->dgroup) continue;
341 pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
342 minsize, hModule,
343 !(pSegment->flags & NE_SEGFLAGS_DATA),
344 FALSE,
345 FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
346 if (!pSegment->selector) return FALSE;
349 pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
350 (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
351 return TRUE;
353 #endif
356 /***********************************************************************
357 * MODULE_GetInstance
359 #ifndef WINELIB32
360 static HINSTANCE MODULE_GetInstance( HMODULE hModule )
362 SEGTABLEENTRY *pSegment;
363 NE_MODULE *pModule;
365 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
366 if (pModule->dgroup == 0) return hModule;
368 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
370 return pSegment->selector;
372 #endif
375 /***********************************************************************
376 * MODULE_CreateInstance
378 HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
380 SEGTABLEENTRY *pSegment;
381 NE_MODULE *pModule;
382 int minsize;
383 HINSTANCE hNewInstance, hPrevInstance;
385 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
386 if (pModule->dgroup == 0) return hModule;
388 pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
389 hPrevInstance = pSegment->selector;
391 /* if it's a library, create a new instance only the first time */
392 if (hPrevInstance)
394 if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
395 if (params == (LOADPARAMS*)-1) return hPrevInstance;
398 minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
399 if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
400 minsize += pModule->heap_size;
401 hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
402 minsize, hModule, FALSE, FALSE, FALSE );
403 if (!hNewInstance) return 0;
404 pSegment->selector = hNewInstance;
405 return hNewInstance;
409 /***********************************************************************
410 * MODULE_LoadExeHeader
412 HMODULE MODULE_LoadExeHeader( int fd, OFSTRUCT *ofs )
414 struct mz_header_s mz_header;
415 struct ne_header_s ne_header;
416 int size;
417 HMODULE hModule;
418 NE_MODULE *pModule;
419 BYTE *pData;
420 char *buffer, *fastload = NULL;
421 int fastload_offset = 0, fastload_length = 0;
423 /* Read a block from either the file or the fast-load area. */
424 #define READ(offset,size,buffer) \
425 ((fastload && ((offset) >= fastload_offset) && \
426 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
427 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
428 (lseek( fd, mz_header.ne_offset+(offset), SEEK_SET), \
429 read( fd, (buffer), (size) ) == (size)))
431 lseek( fd, 0, SEEK_SET );
432 if ((read( fd, &mz_header, sizeof(mz_header) ) != sizeof(mz_header)) ||
433 (mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11; /* invalid exe */
435 lseek( fd, mz_header.ne_offset, SEEK_SET );
436 if (read( fd, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
437 return (HMODULE)11; /* invalid exe */
439 if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21; /* win32 exe */
440 if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE)11; /* invalid exe */
442 /* We now have a valid NE header */
444 size = sizeof(NE_MODULE) +
445 /* loaded file info */
446 sizeof(LOADEDFILEINFO) + strlen(ofs->szPathName) +
447 /* segment table */
448 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
449 /* resource table */
450 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
451 /* resident names table */
452 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
453 /* module ref table */
454 ne_header.n_mod_ref_tab * sizeof(WORD) +
455 /* imported names table */
456 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
457 /* entry table length */
458 ne_header.entry_tab_length;
460 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
461 if (!hModule) return (HMODULE)11; /* invalid exe */
462 FarSetOwner( hModule, (WORD)(DWORD)hModule );
463 pModule = (NE_MODULE *)GlobalLock( hModule );
464 memcpy( pModule, &ne_header, sizeof(NE_MODULE) );
465 pModule->count = 0;
466 pData = (BYTE *)(pModule + 1);
468 /* Read the fast-load area */
470 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
472 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
473 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
474 dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
475 fastload_offset, fastload_length );
476 if ((fastload = (char *)malloc( fastload_length )) != NULL)
478 lseek( fd, mz_header.ne_offset + fastload_offset, SEEK_SET );
479 if (read( fd, fastload, fastload_length ) != fastload_length)
481 free( fastload );
482 fastload = NULL;
487 /* Store the filename information */
489 pModule->fileinfo = (int)pData - (int)pModule;
490 ((LOADEDFILEINFO*)pData)->length = sizeof(LOADEDFILEINFO)+strlen(ofs->szPathName);
491 ((LOADEDFILEINFO*)pData)->fixed_media = TRUE;
492 ((LOADEDFILEINFO*)pData)->error = 0;
493 ((LOADEDFILEINFO*)pData)->date = 0;
494 ((LOADEDFILEINFO*)pData)->time = 0;
495 strcpy( ((LOADEDFILEINFO*)pData)->filename, ofs->szPathName );
496 pData += ((LOADEDFILEINFO*)pData)->length--;
498 /* Get the segment table */
500 pModule->seg_table = (int)pData - (int)pModule;
501 buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
502 if (buffer)
504 int i;
505 struct ne_segment_table_entry_s *pSeg;
507 if (!READ( ne_header.segment_tab_offset,
508 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
509 buffer )) return (HMODULE)11; /* invalid exe */
510 pSeg = (struct ne_segment_table_entry_s *)buffer;
511 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
513 memcpy( pData, pSeg, sizeof(*pSeg) );
514 pData += sizeof(SEGTABLEENTRY);
516 free( buffer );
518 else return (HMODULE)11; /* invalid exe */
520 /* Get the resource table */
522 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
524 pModule->res_table = (int)pData - (int)pModule;
525 if (!READ(ne_header.resource_tab_offset,
526 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
527 pData )) return (HMODULE)11; /* invalid exe */
528 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
530 else pModule->res_table = 0; /* No resource table */
532 /* Get the resident names table */
534 pModule->name_table = (int)pData - (int)pModule;
535 if (!READ( ne_header.rname_tab_offset,
536 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
537 pData )) return (HMODULE)11; /* invalid exe */
538 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
540 /* Get the module references table */
542 if (ne_header.n_mod_ref_tab > 0)
544 pModule->modref_table = (int)pData - (int)pModule;
545 if (!READ( ne_header.moduleref_tab_offset,
546 ne_header.n_mod_ref_tab * sizeof(WORD),
547 pData )) return (HMODULE)11; /* invalid exe */
548 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
550 else pModule->modref_table = 0; /* No module references */
552 /* Get the imported names table */
554 pModule->import_table = (int)pData - (int)pModule;
555 if (!READ( ne_header.iname_tab_offset,
556 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
557 pData )) return (HMODULE)11; /* invalid exe */
558 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
560 /* Get the entry table */
562 pModule->entry_table = (int)pData - (int)pModule;
563 if (!READ( ne_header.entry_tab_offset,
564 ne_header.entry_tab_length,
565 pData )) return (HMODULE)11; /* invalid exe */
566 pData += ne_header.entry_tab_length;
568 /* Get the non-resident names table */
570 if (ne_header.nrname_tab_length)
572 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
573 hModule, FALSE, FALSE, FALSE );
574 if (!pModule->nrname_handle) return (HMODULE)11; /* invalid exe */
575 buffer = GlobalLock( pModule->nrname_handle );
576 lseek( fd, ne_header.nrname_tab_offset, SEEK_SET );
577 if (read( fd, buffer, ne_header.nrname_tab_length )
578 != ne_header.nrname_tab_length) return (HMODULE)11; /* invalid exe */
580 else pModule->nrname_handle = 0;
582 /* Allocate a segment for the implicitly-loaded DLLs */
584 if (pModule->modref_count)
586 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
587 (pModule->modref_count+1)*sizeof(HMODULE),
588 hModule, FALSE, FALSE, FALSE );
589 if (!pModule->dlls_to_init) return (HMODULE)11; /* invalid exe */
591 else pModule->dlls_to_init = 0;
593 if (debugging_module) MODULE_PrintModule( hModule );
594 pModule->next = hFirstModule;
595 hFirstModule = hModule;
596 return hModule;
600 /***********************************************************************
601 * MODULE_GetOrdinal
603 * Lookup the ordinal for a given name.
605 WORD MODULE_GetOrdinal( HMODULE hModule, char *name )
607 char buffer[256], *cpnt;
608 BYTE len;
609 NE_MODULE *pModule;
611 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
613 dprintf_module( stddeb, "MODULE_GetOrdinal("NPFMT",'%s')\n",
614 hModule, name );
616 /* First handle names of the form '#xxxx' */
618 if (name[0] == '#') return atoi( name + 1 );
620 /* Now copy and uppercase the string */
622 strcpy( buffer, name );
623 AnsiUpper( buffer );
624 len = strlen( buffer );
626 /* First search the resident names */
628 cpnt = (char *)pModule + pModule->name_table;
630 /* Skip the first entry (module name) */
631 cpnt += *cpnt + 1 + sizeof(WORD);
632 while (*cpnt)
634 dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
635 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
637 dprintf_module( stddeb, " Found: ordinal=%d\n",
638 *(WORD *)(cpnt + *cpnt + 1) );
639 return *(WORD *)(cpnt + *cpnt + 1);
641 cpnt += *cpnt + 1 + sizeof(WORD);
644 /* Now search the non-resident names table */
646 if (!pModule->nrname_handle) return 0; /* No non-resident table */
647 cpnt = (char *)GlobalLock( pModule->nrname_handle );
649 /* Skip the first entry (module description string) */
650 cpnt += *cpnt + 1 + sizeof(WORD);
651 while (*cpnt)
653 dprintf_module( stddeb, " Checking '%*.*s'\n", *cpnt, *cpnt, cpnt+1 );
654 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
656 dprintf_module( stddeb, " Found: ordinal=%d\n",
657 *(WORD *)(cpnt + *cpnt + 1) );
658 return *(WORD *)(cpnt + *cpnt + 1);
660 cpnt += *cpnt + 1 + sizeof(WORD);
662 return 0;
666 /***********************************************************************
667 * MODULE_GetEntryPoint
669 * Return the entry point for a given ordinal.
671 SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
673 NE_MODULE *pModule;
674 WORD curOrdinal = 1;
675 BYTE *p;
676 WORD sel, offset;
678 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
680 p = (BYTE *)pModule + pModule->entry_table;
681 while (*p && (curOrdinal + *p <= ordinal))
683 /* Skipping this bundle */
684 curOrdinal += *p;
685 switch(p[1])
687 case 0: p += 2; break; /* unused */
688 case 0xff: p += 2 + *p * 6; break; /* moveable */
689 default: p += 2 + *p * 3; break; /* fixed */
692 if (!*p) return 0;
694 switch(p[1])
696 case 0: /* unused */
697 return 0;
698 case 0xff: /* moveable */
699 p += 2 + 6 * (ordinal - curOrdinal);
700 sel = p[3];
701 offset = *(WORD *)(p + 4);
702 break;
703 default: /* fixed */
704 sel = p[1];
705 p += 2 + 3 * (ordinal - curOrdinal);
706 offset = *(WORD *)(p + 1);
707 break;
710 if (sel == 0xfe) sel = 0xffff; /* constant entry */
711 else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
712 return (SEGPTR)MAKELONG( offset, sel );
716 /***********************************************************************
717 * MODULE_SetEntryPoint
719 * Change the value of an entry point. Use with caution!
720 * It can only change the offset value, not the selector.
722 BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset )
724 NE_MODULE *pModule;
725 WORD curOrdinal = 1;
726 BYTE *p;
728 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
730 p = (BYTE *)pModule + pModule->entry_table;
731 while (*p && (curOrdinal + *p <= ordinal))
733 /* Skipping this bundle */
734 curOrdinal += *p;
735 switch(p[1])
737 case 0: p += 2; break; /* unused */
738 case 0xff: p += 2 + *p * 6; break; /* moveable */
739 default: p += 2 + *p * 3; break; /* fixed */
742 if (!*p) return FALSE;
744 switch(p[1])
746 case 0: /* unused */
747 return FALSE;
748 case 0xff: /* moveable */
749 p += 2 + 6 * (ordinal - curOrdinal);
750 *(WORD *)(p + 4) = offset;
751 break;
752 default: /* fixed */
753 p += 2 + 3 * (ordinal - curOrdinal);
754 *(WORD *)(p + 1) = offset;
755 break;
757 return TRUE;
761 /***********************************************************************
762 * MODULE_GetEntryPointName
764 * Return the entry point name for a given ordinal.
765 * Used only by relay debugging.
766 * Warning: returned pointer is to a Pascal-type string.
768 LPSTR MODULE_GetEntryPointName( HMODULE hModule, WORD ordinal )
770 register char *cpnt;
771 NE_MODULE *pModule;
773 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
775 /* First search the resident names */
777 cpnt = (char *)pModule + pModule->name_table;
778 while (*cpnt)
780 cpnt += *cpnt + 1 + sizeof(WORD);
781 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
784 /* Now search the non-resident names table */
786 if (!pModule->nrname_handle) return 0; /* No non-resident table */
787 cpnt = (char *)GlobalLock( pModule->nrname_handle );
788 while (*cpnt)
790 cpnt += *cpnt + 1 + sizeof(WORD);
791 if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
793 return NULL;
797 /***********************************************************************
798 * MODULE_GetModuleName
800 LPSTR MODULE_GetModuleName( HMODULE hModule )
802 NE_MODULE *pModule;
803 BYTE *p, len;
804 static char buffer[10];
806 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return NULL;
807 p = (BYTE *)pModule + pModule->name_table;
808 len = MIN( *p, 8 );
809 memcpy( buffer, p + 1, len );
810 buffer[len] = '\0';
811 return buffer;
815 /**********************************************************************
816 * MODULE_FindModule
818 * Find a module from a path name.
820 HMODULE MODULE_FindModule( LPCSTR path )
822 HMODULE hModule = hFirstModule;
823 LPCSTR filename, dotptr, modulepath, modulename;
824 BYTE len, *name_table;
826 if (!(filename = strrchr( path, '\\' ))) filename = path;
827 else filename++;
828 if ((dotptr = strrchr( filename, '.' )) != NULL)
829 len = (BYTE)(dotptr - filename);
830 else len = strlen( filename );
832 while(hModule)
834 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
835 if (!pModule) break;
836 modulepath = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
837 if (!(modulename = strrchr( modulepath, '\\' )))
838 modulename = modulepath;
839 else modulename++;
840 if (!strcasecmp( modulename, filename )) return hModule;
842 name_table = (BYTE *)pModule + pModule->name_table;
843 if ((*name_table == len) && !strncasecmp(filename, name_table+1, len))
844 return hModule;
845 hModule = pModule->next;
847 return 0;
851 /**********************************************************************
852 * MODULE_FreeModule
854 * Remove a module from memory.
856 static void MODULE_FreeModule( HMODULE hModule )
858 HMODULE *hPrevModule;
859 NE_MODULE *pModule;
860 SEGTABLEENTRY *pSegment;
861 HMODULE *pModRef;
862 int i;
864 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return;
865 if (pModule->flags & NE_FFLAGS_BUILTIN)
866 return; /* Can't free built-in module */
868 /* FIXME: should call the exit code for the library here */
870 /* Remove it from the linked list */
872 hPrevModule = &hFirstModule;
873 while (*hPrevModule && (*hPrevModule != hModule))
875 hPrevModule = &((NE_MODULE *)GlobalLock( *hPrevModule ))->next;
877 if (*hPrevModule) *hPrevModule = pModule->next;
879 /* Free all the segments */
881 pSegment = NE_SEG_TABLE( pModule );
882 for (i = 1; i <= pModule->seg_count; i++, pSegment++)
884 GlobalFree( pSegment->selector );
887 /* Free the referenced modules */
889 pModRef = (HMODULE*)NE_MODULE_TABLE( pModule );
890 for (i = 0; i < pModule->modref_count; i++, pModRef++)
892 FreeModule( *pModRef );
895 /* Free the module storage */
897 if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
898 if (pModule->dlls_to_init) GlobalFree( pModule->dlls_to_init );
899 GlobalFree( hModule );
901 /* Remove module from cache */
903 if (hCachedModule == hModule) hCachedModule = 0;
907 HINSTANCE PE_LoadModule(int fd, OFSTRUCT *ofs, LOADPARAMS* params);
909 /**********************************************************************
910 * LoadModule (KERNEL.45)
912 HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
914 HMODULE hModule;
915 HANDLE hInstance, hPrevInstance;
916 NE_MODULE *pModule;
917 LOADPARAMS *params = (LOADPARAMS *)paramBlock;
918 #ifndef WINELIB
919 WORD *pModRef, *pDLLs;
920 int i, fd;
922 hModule = MODULE_FindModule( name );
924 if (!hModule) /* We have to load the module */
926 OFSTRUCT ofs;
928 /* Try to load the built-in first if not disabled */
929 if ((hModule = MODULE_LoadBuiltin( name, FALSE ))) return hModule;
931 if (strchr( name, '/' )) name = DOS_GetDosFileName( name );
932 if ((fd = OpenFile( name, &ofs, OF_READ )) == -1)
934 /* Now try the built-in even if disabled */
935 if ((hModule = MODULE_LoadBuiltin( name, TRUE )))
937 fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
938 return hModule;
940 return 2; /* File not found */
943 /* Create the module structure */
945 if ((hModule = MODULE_LoadExeHeader( fd, &ofs )) < 32)
947 if(hModule == 21)
948 return PE_LoadModule(fd,&ofs,paramBlock);
949 close( fd );
950 fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
951 name, hModule );
952 return hModule;
954 pModule = (NE_MODULE *)GlobalLock( hModule );
956 /* Allocate the segments for this module */
958 MODULE_CreateSegments( hModule );
960 hPrevInstance = 0;
961 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
963 /* Load the referenced DLLs */
965 pModRef = (WORD *)((char *)pModule + pModule->modref_table);
966 pDLLs = (WORD *)GlobalLock( pModule->dlls_to_init );
967 for (i = 0; i < pModule->modref_count; i++, pModRef++)
969 char buffer[256];
970 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
971 memcpy( buffer, pstr + 1, *pstr );
972 strcpy( buffer + *pstr, ".dll" );
973 dprintf_module( stddeb, "Loading '%s'\n", buffer );
974 if (!(*pModRef = MODULE_FindModule( buffer )))
976 /* If the DLL is not loaded yet, load it and store */
977 /* its handle in the list of DLLs to initialize. */
978 HMODULE hDLL;
980 if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
982 char *p;
984 /* Try with prepending the path of the current module */
985 GetModuleFileName( hModule, buffer, 256 );
986 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
987 memcpy( p + 1, pstr + 1, *pstr );
988 strcpy( p + 1 + *pstr, ".dll" );
989 hDLL = LoadModule( buffer, (LPVOID)-1 );
991 if (hDLL < 32)
993 fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
994 buffer, name, hDLL );
995 return 2; /* file not found */
997 *pModRef = GetExePtr( hDLL );
998 *pDLLs++ = *pModRef;
1000 else /* Increment the reference count of the DLL */
1002 NE_MODULE *pOldDLL = (NE_MODULE *)GlobalLock( *pModRef );
1003 if (pOldDLL) pOldDLL->count++;
1007 /* Load the segments */
1009 if (pModule->flags & NE_FFLAGS_SELFLOAD)
1011 /* Handle self loading modules */
1012 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
1013 SELFLOADHEADER *selfloadheader;
1014 HMODULE hselfload = GetModuleHandle("WINPROCS");
1015 WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
1016 fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
1017 "Support for self-loading modules is very experimental\n",
1018 *((BYTE*)pModule + pModule->name_table),
1019 *((BYTE*)pModule + pModule->name_table),
1020 (char *)pModule + pModule->name_table + 1);
1021 NE_LoadSegment( hModule, 1 );
1022 selfloadheader = (SELFLOADHEADER *)
1023 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
1024 selfloadheader->EntryAddrProc =
1025 MODULE_GetEntryPoint(hselfload,27);
1026 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
1027 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
1028 pModule->self_loading_sel = GlobalHandleToSel(
1029 GLOBAL_Alloc (GMEM_ZEROINIT,
1030 0xFF00, hModule, FALSE, FALSE, FALSE)
1032 oldss = IF1632_Saved16_ss;
1033 oldsp = IF1632_Saved16_sp;
1034 IF1632_Saved16_ss = pModule->self_loading_sel;
1035 IF1632_Saved16_sp = 0xFF00;
1036 if (!IF1632_Stack32_base) {
1037 STACK32FRAME* frame32;
1038 char *stack32Top;
1039 /* Setup an initial 32 bit stack frame */
1040 hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
1041 hModule, FALSE, FALSE,
1042 FALSE );
1044 /* Create the 32-bit stack frame */
1046 *(DWORD *)GlobalLock(hInitialStack32) = 0xDEADBEEF;
1047 stack32Top = (char*)GlobalLock(hInitialStack32) +
1048 0x10000;
1049 frame32 = (STACK32FRAME *)stack32Top - 1;
1050 frame32->saved_esp = (DWORD)stack32Top;
1051 frame32->edi = 0;
1052 frame32->esi = 0;
1053 frame32->edx = 0;
1054 frame32->ecx = 0;
1055 frame32->ebx = 0;
1056 frame32->ebp = 0;
1057 frame32->retaddr = 0;
1058 frame32->codeselector = WINE_CODE_SELECTOR;
1059 /* pTask->esp = (DWORD)frame32; */
1060 IF1632_Stack32_base = WIN16_GlobalLock(hInitialStack32);
1063 CallTo16_word_ww (selfloadheader->BootApp,
1064 pModule->self_loading_sel, hModule, fd);
1065 /* some BootApp procs overwrite the selector of dgroup */
1066 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
1067 IF1632_Saved16_ss = oldss;
1068 IF1632_Saved16_sp = oldsp;
1069 for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
1070 if (hInitialStack32){
1071 GlobalUnlock (hInitialStack32);
1072 GlobalFree (hInitialStack32);
1073 IF1632_Stack32_base = hInitialStack32 = 0;
1076 else
1078 for (i = 1; i <= pModule->seg_count; i++)
1079 NE_LoadSegment( hModule, i );
1082 /* Fixup the functions prologs */
1084 NE_FixupPrologs( hModule );
1086 /* Make sure the usage count is 1 on the first loading of */
1087 /* the module, even if it contains circular DLL references */
1089 pModule->count = 1;
1091 /* Clear built-in flag in case it was set in the EXE file */
1093 pModule->flags &= ~NE_FFLAGS_BUILTIN;
1095 else
1097 pModule = (NE_MODULE *)GlobalLock( hModule );
1098 hPrevInstance = MODULE_GetInstance( hModule );
1099 hInstance = MODULE_CreateInstance( hModule, params );
1100 if (hInstance != hPrevInstance) /* not a library */
1101 NE_LoadSegment( hModule, pModule->dgroup );
1102 pModule->count++;
1104 #else
1105 hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE) );
1106 pModule = (NE_MODULE *)GlobalLock( hModule );
1107 pModule->count = 1;
1108 pModule->magic = 0x454e;
1109 hPrevInstance = 0;
1110 hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
1111 #endif /* WINELIB */
1113 /* Create a task for this instance */
1115 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
1117 TASK_CreateTask( hModule, hInstance, hPrevInstance,
1118 params->hEnvironment,
1119 (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
1120 *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
1123 return hInstance;
1127 /**********************************************************************
1128 * FreeModule (KERNEL.46)
1130 BOOL FreeModule( HANDLE hModule )
1132 NE_MODULE *pModule;
1134 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1135 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
1137 dprintf_module( stddeb, "FreeModule: %s count %d\n",
1138 MODULE_GetModuleName(hModule), pModule->count );
1139 if (--pModule->count == 0) MODULE_FreeModule( hModule );
1140 return TRUE;
1144 /**********************************************************************
1145 * GetModuleHandle (KERNEL.47)
1147 HMODULE WIN16_GetModuleHandle( SEGPTR name )
1149 #ifdef WINELIB32
1150 if (HIWORD(name) == 0) return GetExePtr( name );
1151 #else
1152 if (HIWORD(name) == 0) return GetExePtr( LOWORD(name) );
1153 #endif
1154 return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
1157 HMODULE GetModuleHandle( LPCSTR name )
1159 return MODULE_FindModule( name );
1163 /**********************************************************************
1164 * GetModuleUsage (KERNEL.48)
1166 int GetModuleUsage( HANDLE hModule )
1168 NE_MODULE *pModule;
1170 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1171 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
1172 dprintf_module( stddeb, "GetModuleUsage("NPFMT"): returning %d\n",
1173 hModule, pModule->count );
1174 return pModule->count;
1178 /**********************************************************************
1179 * GetModuleFileName (KERNEL.49)
1181 int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
1183 NE_MODULE *pModule;
1184 char *name;
1186 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1187 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
1188 name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
1189 lstrcpyn( lpFileName, name, nSize );
1190 dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
1191 return strlen(lpFileName);
1195 /***********************************************************************
1196 * LoadLibrary (KERNEL.95)
1198 HANDLE LoadLibrary( LPCSTR libname )
1200 #ifdef WINELIB
1201 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1202 WINELIB_UNIMP("LoadLibrary()");
1203 return (HANDLE)0;
1204 #else
1205 HANDLE handle;
1207 dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
1209 /* This does not increment the module reference count, and will
1210 * therefore cause crashes on FreeLibrary calls.
1211 if ((handle = MODULE_FindModule( libname )) != 0) return handle;
1213 handle = LoadModule( libname, (LPVOID)-1 );
1214 if (handle == (HANDLE)2) /* file not found */
1216 char buffer[256];
1217 strcpy( buffer, libname );
1218 strcat( buffer, ".dll" );
1219 handle = LoadModule( buffer, (LPVOID)-1 );
1221 if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
1222 return handle;
1223 #endif
1227 /***********************************************************************
1228 * FreeLibrary (KERNEL.96)
1230 void FreeLibrary( HANDLE handle )
1232 dprintf_module( stddeb,"FreeLibrary: "NPFMT"\n", handle );
1233 FreeModule( handle );
1237 /***********************************************************************
1238 * WinExec (KERNEL.166)
1240 HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
1242 LOADPARAMS params;
1243 HLOCAL cmdShowHandle, cmdLineHandle;
1244 HANDLE handle;
1245 WORD *cmdShowPtr;
1246 char *p, *cmdline, filename[256];
1248 if (!(cmdShowHandle = GlobalAlloc( 0, 2 * sizeof(WORD) ))) return 0;
1249 if (!(cmdLineHandle = GlobalAlloc( 0, 256 ))) return 0;
1251 /* Store nCmdShow */
1253 cmdShowPtr = (WORD *)GlobalLock( cmdShowHandle );
1254 cmdShowPtr[0] = 2;
1255 cmdShowPtr[1] = nCmdShow;
1257 /* Build the filename and command-line */
1259 cmdline = (char *)GlobalLock( cmdLineHandle );
1260 strncpy( filename, lpCmdLine, 256 );
1261 filename[255] = '\0';
1262 for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
1263 if (*p)
1265 strncpy( cmdline, p + 1, 128 );
1266 cmdline[127] = '\0';
1268 else cmdline[0] = '\0';
1269 *p = '\0';
1271 /* Now load the executable file */
1273 #ifdef WINELIB32
1274 params.hEnvironment = (HANDLE)GetDOSEnvironment();
1275 #else
1276 params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
1277 #endif
1278 params.cmdLine = (SEGPTR)WIN16_GlobalLock( cmdLineHandle );
1279 params.showCmd = (SEGPTR)WIN16_GlobalLock( cmdShowHandle );
1280 params.reserved = 0;
1281 handle = LoadModule( filename, &params );
1282 if (handle == (HANDLE)2) /* file not found */
1284 /* Check that the original file name did not have a suffix */
1285 p = strrchr(filename, '.');
1286 if (p && !(strchr(p, '/') || strchr(p, '\\')))
1287 return handle; /* filename already includes a suffix! */
1288 strcat( filename, ".exe" );
1289 handle = LoadModule( filename, &params );
1292 GlobalFree( cmdShowHandle );
1293 GlobalFree( cmdLineHandle );
1295 #if 0
1296 if (handle < (HANDLE)32) /* Error? */
1297 return handle;
1299 /* FIXME: Yield never returns!
1300 We may want to run more applications or start the debugger
1301 before calling Yield. If we don't Yield will be called immdiately
1302 after returning. Why is it needed for Word anyway? */
1303 Yield(); /* program is executed immediately ....needed for word */
1305 #endif
1306 return handle;
1310 /***********************************************************************
1311 * GetProcAddress (KERNEL.50)
1313 FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
1315 WORD ordinal;
1316 SEGPTR ret;
1318 if (!hModule) hModule = GetCurrentTask();
1319 hModule = GetExePtr( hModule );
1321 if (HIWORD(name) != 0)
1323 ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1324 dprintf_module( stddeb, "GetProcAddress: "NPFMT" '%s'\n",
1325 hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
1327 else
1329 ordinal = LOWORD(name);
1330 dprintf_module( stddeb, "GetProcAddress: "NPFMT" %04x\n",
1331 hModule, ordinal );
1333 if (!ordinal) return (FARPROC)0;
1335 ret = MODULE_GetEntryPoint( hModule, ordinal );
1337 dprintf_module( stddeb, "GetProcAddress: returning "SPFMT"\n", ret );
1338 return (FARPROC)ret;
1342 /**********************************************************************
1343 * GetExpWinVer (KERNEL.167)
1345 WORD GetExpWinVer( HMODULE hModule )
1347 NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
1349 return pModule->expected_version;
1353 /***********************************************************************
1354 * GetWndProcEntry16 (not a Windows API function)
1356 * Return an entry point from the WINPROCS dll.
1358 #ifndef WINELIB
1359 WNDPROC GetWndProcEntry16( char *name )
1361 WORD ordinal;
1362 static HMODULE hModule = 0;
1364 if (!hModule) hModule = GetModuleHandle( "WINPROCS" );
1365 ordinal = MODULE_GetOrdinal( hModule, name );
1366 return MODULE_GetEntryPoint( hModule, ordinal );
1368 #endif
1371 /**********************************************************************
1372 * ModuleFirst (TOOLHELP.59)
1374 BOOL ModuleFirst( MODULEENTRY *lpme )
1376 lpme->wNext = hFirstModule;
1377 return ModuleNext( lpme );
1381 /**********************************************************************
1382 * ModuleNext (TOOLHELP.60)
1384 BOOL ModuleNext( MODULEENTRY *lpme )
1386 NE_MODULE *pModule;
1388 if (!lpme->wNext) return FALSE;
1389 if (!(pModule = (NE_MODULE *)GlobalLock( lpme->wNext ))) return FALSE;
1390 strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
1391 MAX_MODULE_NAME );
1392 lpme->szModule[MAX_MODULE_NAME] = '\0';
1393 lpme->hModule = lpme->wNext;
1394 lpme->wcUsage = pModule->count;
1395 strncpy( lpme->szExePath,
1396 ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename,
1397 MAX_PATH );
1398 lpme->szExePath[MAX_PATH] = '\0';
1399 lpme->wNext = pModule->next;
1400 return TRUE;
1404 /**********************************************************************
1405 * ModuleFindName (TOOLHELP.61)
1407 BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
1409 lpme->wNext = GetModuleHandle( name );
1410 return ModuleNext( lpme );
1414 /**********************************************************************
1415 * ModuleFindHandle (TOOLHELP.62)
1417 BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
1419 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
1420 lpme->wNext = hModule;
1421 return ModuleNext( lpme );