Take advantage of the new registers saved in the STACK16FRAME to turn
[wine/multimedia.git] / loader / ne / module.c
blob49bea39973b945f7a857324233f2365d31ab4d62
1 /*
2 * NE modules
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <ctype.h>
13 #include "wine/winbase16.h"
14 #include "winerror.h"
15 #include "module.h"
16 #include "neexe.h"
17 #include "peexe.h"
18 #include "toolhelp.h"
19 #include "file.h"
20 #include "ldt.h"
21 #include "callback.h"
22 #include "heap.h"
23 #include "task.h"
24 #include "global.h"
25 #include "process.h"
26 #include "toolhelp.h"
27 #include "snoop.h"
28 #include "stackframe.h"
29 #include "debugtools.h"
30 #include "file.h"
31 #include "loadorder.h"
32 #include "elfdll.h"
33 #include "toolhelp.h"
35 DEFAULT_DEBUG_CHANNEL(module)
37 FARPROC16 (*fnSNOOP16_GetProcAddress16)(HMODULE16,DWORD,FARPROC16) = NULL;
38 void (*fnSNOOP16_RegisterDLL)(NE_MODULE*,LPCSTR) = NULL;
40 #define hFirstModule (pThhook->hExeHead)
42 static NE_MODULE *pCachedModule = 0; /* Module cached by NE_OpenFile */
44 static HMODULE16 NE_LoadBuiltin(LPCSTR name,BOOL force) { return 0; }
45 HMODULE16 (*fnBUILTIN_LoadModule)(LPCSTR name,BOOL force) = NE_LoadBuiltin;
46 static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep );
48 static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only );
50 /***********************************************************************
51 * NE_GetPtr
53 NE_MODULE *NE_GetPtr( HMODULE16 hModule )
55 return (NE_MODULE *)GlobalLock16( GetExePtr(hModule) );
59 /***********************************************************************
60 * NE_DumpModule
62 void NE_DumpModule( HMODULE16 hModule )
64 int i, ordinal;
65 SEGTABLEENTRY *pSeg;
66 BYTE *pstr;
67 WORD *pword;
68 NE_MODULE *pModule;
69 ET_BUNDLE *bundle;
70 ET_ENTRY *entry;
72 if (!(pModule = NE_GetPtr( hModule )))
74 MESSAGE( "**** %04x is not a module handle\n", hModule );
75 return;
78 /* Dump the module info */
79 DPRINTF( "---\n" );
80 DPRINTF( "Module %04x:\n", hModule );
81 DPRINTF( "count=%d flags=%04x heap=%d stack=%d\n",
82 pModule->count, pModule->flags,
83 pModule->heap_size, pModule->stack_size );
84 DPRINTF( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
85 pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
86 pModule->seg_count, pModule->modref_count );
87 DPRINTF( "os_flags=%d swap_area=%d version=%04x\n",
88 pModule->os_flags, pModule->min_swap_area,
89 pModule->expected_version );
90 if (pModule->flags & NE_FFLAGS_WIN32)
91 DPRINTF( "PE module=%08x\n", pModule->module32 );
93 /* Dump the file info */
94 DPRINTF( "---\n" );
95 DPRINTF( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
97 /* Dump the segment table */
98 DPRINTF( "---\n" );
99 DPRINTF( "Segment table:\n" );
100 pSeg = NE_SEG_TABLE( pModule );
101 for (i = 0; i < pModule->seg_count; i++, pSeg++)
102 DPRINTF( "%02x: pos=%d size=%d flags=%04x minsize=%d hSeg=%04x\n",
103 i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
104 pSeg->minsize, pSeg->hSeg );
106 /* Dump the resource table */
107 DPRINTF( "---\n" );
108 DPRINTF( "Resource table:\n" );
109 if (pModule->res_table)
111 pword = (WORD *)((BYTE *)pModule + pModule->res_table);
112 DPRINTF( "Alignment: %d\n", *pword++ );
113 while (*pword)
115 struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
116 struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
117 DPRINTF( "id=%04x count=%d\n", ptr->type_id, ptr->count );
118 for (i = 0; i < ptr->count; i++, pname++)
119 DPRINTF( "offset=%d len=%d id=%04x\n",
120 pname->offset, pname->length, pname->id );
121 pword = (WORD *)pname;
124 else DPRINTF( "None\n" );
126 /* Dump the resident name table */
127 DPRINTF( "---\n" );
128 DPRINTF( "Resident-name table:\n" );
129 pstr = (char *)pModule + pModule->name_table;
130 while (*pstr)
132 DPRINTF( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
133 *(WORD *)(pstr + *pstr + 1) );
134 pstr += *pstr + 1 + sizeof(WORD);
137 /* Dump the module reference table */
138 DPRINTF( "---\n" );
139 DPRINTF( "Module ref table:\n" );
140 if (pModule->modref_table)
142 pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
143 for (i = 0; i < pModule->modref_count; i++, pword++)
145 char name[10];
146 GetModuleName16( *pword, name, sizeof(name) );
147 DPRINTF( "%d: %04x -> '%s'\n", i, *pword, name );
150 else DPRINTF( "None\n" );
152 /* Dump the entry table */
153 DPRINTF( "---\n" );
154 DPRINTF( "Entry table:\n" );
155 bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);
156 do {
157 entry = (ET_ENTRY *)((BYTE *)bundle+6);
158 DPRINTF( "Bundle %d-%d: %02x\n", bundle->first, bundle->last, entry->type);
159 ordinal = bundle->first;
160 while (ordinal < bundle->last)
162 if (entry->type == 0xff)
163 DPRINTF("%d: %02x:%04x (moveable)\n", ordinal++, entry->segnum, entry->offs);
164 else
165 DPRINTF("%d: %02x:%04x (fixed)\n", ordinal++, entry->segnum, entry->offs);
166 entry++;
168 } while ( (bundle->next)
169 && (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
171 /* Dump the non-resident names table */
172 DPRINTF( "---\n" );
173 DPRINTF( "Non-resident names table:\n" );
174 if (pModule->nrname_handle)
176 pstr = (char *)GlobalLock16( pModule->nrname_handle );
177 while (*pstr)
179 DPRINTF( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
180 *(WORD *)(pstr + *pstr + 1) );
181 pstr += *pstr + 1 + sizeof(WORD);
184 DPRINTF( "\n" );
188 /***********************************************************************
189 * NE_WalkModules
191 * Walk the module list and print the modules.
193 void NE_WalkModules(void)
195 HMODULE16 hModule = hFirstModule;
196 MESSAGE( "Module Flags Name\n" );
197 while (hModule)
199 NE_MODULE *pModule = NE_GetPtr( hModule );
200 if (!pModule)
202 MESSAGE( "Bad module %04x in list\n", hModule );
203 return;
205 MESSAGE( " %04x %04x %.*s\n", hModule, pModule->flags,
206 *((char *)pModule + pModule->name_table),
207 (char *)pModule + pModule->name_table + 1 );
208 hModule = pModule->next;
213 /**********************************************************************
214 * NE_RegisterModule
216 void NE_RegisterModule( NE_MODULE *pModule )
218 pModule->next = hFirstModule;
219 hFirstModule = pModule->self;
223 /***********************************************************************
224 * NE_GetOrdinal
226 * Lookup the ordinal for a given name.
228 WORD NE_GetOrdinal( HMODULE16 hModule, const char *name )
230 unsigned char buffer[256], *cpnt;
231 BYTE len;
232 NE_MODULE *pModule;
234 if (!(pModule = NE_GetPtr( hModule ))) return 0;
235 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
237 TRACE("(%04x,'%s')\n", hModule, name );
239 /* First handle names of the form '#xxxx' */
241 if (name[0] == '#') return atoi( name + 1 );
243 /* Now copy and uppercase the string */
245 strcpy( buffer, name );
246 CharUpperA( buffer );
247 len = strlen( buffer );
249 /* First search the resident names */
251 cpnt = (char *)pModule + pModule->name_table;
253 /* Skip the first entry (module name) */
254 cpnt += *cpnt + 1 + sizeof(WORD);
255 while (*cpnt)
257 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
259 TRACE(" Found: ordinal=%d\n",
260 *(WORD *)(cpnt + *cpnt + 1) );
261 return *(WORD *)(cpnt + *cpnt + 1);
263 cpnt += *cpnt + 1 + sizeof(WORD);
266 /* Now search the non-resident names table */
268 if (!pModule->nrname_handle) return 0; /* No non-resident table */
269 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
271 /* Skip the first entry (module description string) */
272 cpnt += *cpnt + 1 + sizeof(WORD);
273 while (*cpnt)
275 if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
277 TRACE(" Found: ordinal=%d\n",
278 *(WORD *)(cpnt + *cpnt + 1) );
279 return *(WORD *)(cpnt + *cpnt + 1);
281 cpnt += *cpnt + 1 + sizeof(WORD);
283 return 0;
287 /***********************************************************************
288 * NE_GetEntryPoint (WPROCS.27)
290 * Return the entry point for a given ordinal.
292 FARPROC16 NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
294 return NE_GetEntryPointEx( hModule, ordinal, TRUE );
296 FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop )
298 NE_MODULE *pModule;
299 WORD sel, offset, i;
301 ET_ENTRY *entry;
302 ET_BUNDLE *bundle;
304 if (!(pModule = NE_GetPtr( hModule ))) return 0;
305 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
307 bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
308 while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
310 if (!(bundle->next))
311 return 0;
312 bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
315 entry = (ET_ENTRY *)((BYTE *)bundle+6);
316 for (i=0; i < (ordinal - bundle->first - 1); i++)
317 entry++;
319 sel = entry->segnum;
320 offset = entry->offs;
322 if (sel == 0xfe) sel = 0xffff; /* constant entry */
323 else sel = GlobalHandleToSel16(NE_SEG_TABLE(pModule)[sel-1].hSeg);
324 if (sel==0xffff)
325 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
326 if (!snoop || !fnSNOOP16_GetProcAddress16)
327 return (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset );
328 else
329 return (FARPROC16)fnSNOOP16_GetProcAddress16(hModule,ordinal,(FARPROC16)PTR_SEG_OFF_TO_SEGPTR( sel, offset ));
333 /***********************************************************************
334 * NE_SetEntryPoint
336 * Change the value of an entry point. Use with caution!
337 * It can only change the offset value, not the selector.
339 BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
341 NE_MODULE *pModule;
342 ET_ENTRY *entry;
343 ET_BUNDLE *bundle;
344 int i;
346 if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
347 assert( !(pModule->flags & NE_FFLAGS_WIN32) );
349 bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
350 while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
352 bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
353 if (!(bundle->next))
354 return 0;
357 entry = (ET_ENTRY *)((BYTE *)bundle+6);
358 for (i=0; i < (ordinal - bundle->first - 1); i++)
359 entry++;
361 entry->offs = offset;
362 return TRUE;
366 /***********************************************************************
367 * NE_OpenFile
369 HANDLE NE_OpenFile( NE_MODULE *pModule )
371 char *name;
373 static HANDLE cachedfd = -1;
375 TRACE("(%p) cache: mod=%p fd=%d\n",
376 pModule, pCachedModule, cachedfd );
377 if (pCachedModule == pModule) return cachedfd;
378 CloseHandle( cachedfd );
379 pCachedModule = pModule;
380 name = NE_MODULE_NAME( pModule );
381 if ((cachedfd = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
382 NULL, OPEN_EXISTING, 0, -1 )) == -1)
383 MESSAGE( "Can't open file '%s' for module %04x\n", name, pModule->self );
384 else
385 /* FIXME: should not be necessary */
386 cachedfd = ConvertToGlobalHandle(cachedfd);
387 TRACE("opened '%s' -> %d\n",
388 name, cachedfd );
389 return cachedfd;
393 /***********************************************************************
394 * NE_LoadExeHeader
396 static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
398 IMAGE_DOS_HEADER mz_header;
399 IMAGE_OS2_HEADER ne_header;
400 int size;
401 HMODULE16 hModule;
402 NE_MODULE *pModule;
403 BYTE *pData, *pTempEntryTable;
404 char *buffer, *fastload = NULL;
405 int fastload_offset = 0, fastload_length = 0;
406 ET_ENTRY *entry;
407 ET_BUNDLE *bundle, *oldbundle;
409 /* Read a block from either the file or the fast-load area. */
410 #define READ(offset,size,buffer) \
411 ((fastload && ((offset) >= fastload_offset) && \
412 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
413 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
414 (_llseek16( hFile, (offset), SEEK_SET), \
415 _hread16( hFile, (buffer), (size) ) == (size)))
417 _llseek16( hFile, 0, SEEK_SET );
418 if ((_hread16(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
419 (mz_header.e_magic != IMAGE_DOS_SIGNATURE))
420 return (HMODULE16)11; /* invalid exe */
422 _llseek16( hFile, mz_header.e_lfanew, SEEK_SET );
423 if (_hread16( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
424 return (HMODULE16)11; /* invalid exe */
426 if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE16)21; /* win32 exe */
427 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE16)11; /* invalid exe */
429 if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
430 MESSAGE("Sorry, this is an OS/2 linear executable (LX) file !\n");
431 return (HMODULE16)12;
434 /* We now have a valid NE header */
436 size = sizeof(NE_MODULE) +
437 /* segment table */
438 ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
439 /* resource table */
440 ne_header.rname_tab_offset - ne_header.resource_tab_offset +
441 /* resident names table */
442 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
443 /* module ref table */
444 ne_header.n_mod_ref_tab * sizeof(WORD) +
445 /* imported names table */
446 ne_header.entry_tab_offset - ne_header.iname_tab_offset +
447 /* entry table length */
448 ne_header.entry_tab_length +
449 /* entry table extra conversion space */
450 sizeof(ET_BUNDLE) +
451 2 * (ne_header.entry_tab_length - ne_header.n_mov_entry_points*6) +
452 /* loaded file info */
453 sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
455 hModule = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, size );
456 if (!hModule) return (HMODULE16)11; /* invalid exe */
457 FarSetOwner16( hModule, hModule );
458 pModule = (NE_MODULE *)GlobalLock16( hModule );
459 memcpy( pModule, &ne_header, sizeof(ne_header) );
460 pModule->count = 0;
461 /* check *programs* for default minimal stack size */
462 if ( (!(pModule->flags & NE_FFLAGS_LIBMODULE))
463 && (pModule->stack_size < 0x1400) )
464 pModule->stack_size = 0x1400;
465 pModule->module32 = 0;
466 pModule->self = hModule;
467 pModule->self_loading_sel = 0;
468 pData = (BYTE *)(pModule + 1);
470 /* Clear internal Wine flags in case they are set in the EXE file */
472 pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
474 /* Read the fast-load area */
476 if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
478 fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
479 fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
480 TRACE("Using fast-load area offset=%x len=%d\n",
481 fastload_offset, fastload_length );
482 if ((fastload = HeapAlloc( SystemHeap, 0, fastload_length )) != NULL)
484 _llseek16( hFile, fastload_offset, SEEK_SET);
485 if (_hread16(hFile, fastload, fastload_length) != fastload_length)
487 HeapFree( SystemHeap, 0, fastload );
488 WARN("Error reading fast-load area!\n");
489 fastload = NULL;
494 /* Get the segment table */
496 pModule->seg_table = (int)pData - (int)pModule;
497 buffer = HeapAlloc( SystemHeap, 0, ne_header.n_segment_tab *
498 sizeof(struct ne_segment_table_entry_s));
499 if (buffer)
501 int i;
502 struct ne_segment_table_entry_s *pSeg;
504 if (!READ( mz_header.e_lfanew + ne_header.segment_tab_offset,
505 ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
506 buffer ))
508 HeapFree( SystemHeap, 0, buffer );
509 if (fastload)
510 HeapFree( SystemHeap, 0, fastload );
511 GlobalFree16( hModule );
512 return (HMODULE16)11; /* invalid exe */
514 pSeg = (struct ne_segment_table_entry_s *)buffer;
515 for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
517 memcpy( pData, pSeg, sizeof(*pSeg) );
518 pData += sizeof(SEGTABLEENTRY);
520 HeapFree( SystemHeap, 0, buffer );
522 else
524 if (fastload)
525 HeapFree( SystemHeap, 0, fastload );
526 GlobalFree16( hModule );
527 return (HMODULE16)11; /* invalid exe */
530 /* Get the resource table */
532 if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
534 pModule->res_table = (int)pData - (int)pModule;
535 if (!READ(mz_header.e_lfanew + ne_header.resource_tab_offset,
536 ne_header.rname_tab_offset - ne_header.resource_tab_offset,
537 pData )) return (HMODULE16)11; /* invalid exe */
538 pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
539 NE_InitResourceHandler( hModule );
541 else pModule->res_table = 0; /* No resource table */
543 /* Get the resident names table */
545 pModule->name_table = (int)pData - (int)pModule;
546 if (!READ( mz_header.e_lfanew + ne_header.rname_tab_offset,
547 ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
548 pData ))
550 if (fastload)
551 HeapFree( SystemHeap, 0, fastload );
552 GlobalFree16( hModule );
553 return (HMODULE16)11; /* invalid exe */
555 pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
557 /* Get the module references table */
559 if (ne_header.n_mod_ref_tab > 0)
561 pModule->modref_table = (int)pData - (int)pModule;
562 if (!READ( mz_header.e_lfanew + ne_header.moduleref_tab_offset,
563 ne_header.n_mod_ref_tab * sizeof(WORD),
564 pData ))
566 if (fastload)
567 HeapFree( SystemHeap, 0, fastload );
568 GlobalFree16( hModule );
569 return (HMODULE16)11; /* invalid exe */
571 pData += ne_header.n_mod_ref_tab * sizeof(WORD);
573 else pModule->modref_table = 0; /* No module references */
575 /* Get the imported names table */
577 pModule->import_table = (int)pData - (int)pModule;
578 if (!READ( mz_header.e_lfanew + ne_header.iname_tab_offset,
579 ne_header.entry_tab_offset - ne_header.iname_tab_offset,
580 pData ))
582 if (fastload)
583 HeapFree( SystemHeap, 0, fastload );
584 GlobalFree16( hModule );
585 return (HMODULE16)11; /* invalid exe */
587 pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
589 /* Load entry table, convert it to the optimized version used by Windows */
591 if ((pTempEntryTable = HeapAlloc( SystemHeap, 0, ne_header.entry_tab_length)) != NULL)
593 BYTE nr_entries, type, *s;
595 TRACE("Converting entry table.\n");
596 pModule->entry_table = (int)pData - (int)pModule;
597 if (!READ( mz_header.e_lfanew + ne_header.entry_tab_offset,
598 ne_header.entry_tab_length, pTempEntryTable ))
600 HeapFree( SystemHeap, 0, pTempEntryTable );
601 if (fastload)
602 HeapFree( SystemHeap, 0, fastload );
603 GlobalFree16( hModule );
604 return (HMODULE16)11; /* invalid exe */
607 s = pTempEntryTable;
608 TRACE("entry table: offs %04x, len %04x, entries %d\n", ne_header.entry_tab_offset, ne_header.entry_tab_length, *s);
610 bundle = (ET_BUNDLE *)pData;
611 TRACE("first bundle: %p\n", bundle);
612 memset(bundle, 0, sizeof(ET_BUNDLE)); /* in case no entry table exists */
613 entry = (ET_ENTRY *)((BYTE *)bundle+6);
615 while ((nr_entries = *s++))
617 if ((type = *s++))
619 bundle->last += nr_entries;
620 if (type == 0xff)
621 while (nr_entries--)
623 entry->type = type;
624 entry->flags = *s++;
625 s += 2;
626 entry->segnum = *s++;
627 entry->offs = *(WORD *)s; s += 2;
628 /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
629 entry++;
631 else
632 while (nr_entries--)
634 entry->type = type;
635 entry->flags = *s++;
636 entry->segnum = type;
637 entry->offs = *(WORD *)s; s += 2;
638 /*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
639 entry++;
642 else
644 if (bundle->first == bundle->last)
646 bundle->first += nr_entries;
647 bundle->last += nr_entries;
649 else
651 oldbundle = bundle;
652 oldbundle->next = ((int)entry - (int)pModule);
653 bundle = (ET_BUNDLE *)entry;
654 TRACE("new bundle: %p\n", bundle);
655 bundle->first = bundle->last =
656 oldbundle->last + nr_entries;
657 bundle->next = 0;
658 (BYTE *)entry += sizeof(ET_BUNDLE);
662 HeapFree( SystemHeap, 0, pTempEntryTable );
664 else
666 if (fastload)
667 HeapFree( SystemHeap, 0, fastload );
668 GlobalFree16( hModule );
669 return (HMODULE16)11; /* invalid exe */
672 pData += ne_header.entry_tab_length + sizeof(ET_BUNDLE) +
673 2 * (ne_header.entry_tab_length - ne_header.n_mov_entry_points*6);
675 if ((DWORD)entry > (DWORD)pData)
676 ERR("converted entry table bigger than reserved space !!!\nentry: %p, pData: %p. Please report !\n", entry, pData);
678 /* Store the filename information */
680 pModule->fileinfo = (int)pData - (int)pModule;
681 size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
682 memcpy( pData, ofs, size );
683 ((OFSTRUCT *)pData)->cBytes = size - 1;
684 pData += size;
686 /* Free the fast-load area */
688 #undef READ
689 if (fastload)
690 HeapFree( SystemHeap, 0, fastload );
692 /* Get the non-resident names table */
694 if (ne_header.nrname_tab_length)
696 pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
697 hModule, FALSE, FALSE, FALSE );
698 if (!pModule->nrname_handle)
700 GlobalFree16( hModule );
701 return (HMODULE16)11; /* invalid exe */
703 buffer = GlobalLock16( pModule->nrname_handle );
704 _llseek16( hFile, ne_header.nrname_tab_offset, SEEK_SET );
705 if (_hread16( hFile, buffer, ne_header.nrname_tab_length )
706 != ne_header.nrname_tab_length)
708 GlobalFree16( pModule->nrname_handle );
709 GlobalFree16( hModule );
710 return (HMODULE16)11; /* invalid exe */
713 else pModule->nrname_handle = 0;
715 /* Allocate a segment for the implicitly-loaded DLLs */
717 if (pModule->modref_count)
719 pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
720 (pModule->modref_count+1)*sizeof(HMODULE16),
721 hModule, FALSE, FALSE, FALSE );
722 if (!pModule->dlls_to_init)
724 if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
725 GlobalFree16( hModule );
726 return (HMODULE16)11; /* invalid exe */
729 else pModule->dlls_to_init = 0;
731 NE_RegisterModule( pModule );
732 if (fnSNOOP16_RegisterDLL)
733 fnSNOOP16_RegisterDLL(pModule,ofs->szPathName);
734 return hModule;
738 /***********************************************************************
739 * NE_LoadDLLs
741 * Load all DLLs implicitly linked to a module.
743 static BOOL NE_LoadDLLs( NE_MODULE *pModule )
745 int i;
746 WORD *pModRef = (WORD *)((char *)pModule + pModule->modref_table);
747 WORD *pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
749 for (i = 0; i < pModule->modref_count; i++, pModRef++)
751 char buffer[260];
752 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
753 memcpy( buffer, pstr + 1, *pstr );
754 *(buffer + *pstr) = 0; /* terminate it */
756 TRACE("Loading '%s'\n", buffer );
757 if (!(*pModRef = GetModuleHandle16( buffer )))
759 /* If the DLL is not loaded yet, load it and store */
760 /* its handle in the list of DLLs to initialize. */
761 HMODULE16 hDLL;
763 if ((hDLL = MODULE_LoadModule16( buffer, TRUE, TRUE )) < 32)
765 /* FIXME: cleanup what was done */
767 MESSAGE( "Could not load '%s' required by '%.*s', error=%d\n",
768 buffer, *((BYTE*)pModule + pModule->name_table),
769 (char *)pModule + pModule->name_table + 1, hDLL );
770 return FALSE;
772 *pModRef = GetExePtr( hDLL );
773 *pDLLs++ = *pModRef;
775 else /* Increment the reference count of the DLL */
777 NE_MODULE *pOldDLL;
779 pOldDLL = NE_GetPtr( *pModRef );
780 if (pOldDLL) pOldDLL->count++;
783 return TRUE;
787 /**********************************************************************
788 * NE_DoLoadModule
790 * Load first instance of NE module from file.
792 * pModule must point to a module structure prepared by NE_LoadExeHeader.
793 * This routine must never be called twice on a module.
796 static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule )
798 HINSTANCE16 hInstance;
800 /* Allocate the segments for this module */
802 if (!NE_CreateSegments( pModule ) ||
803 !(hInstance = NE_CreateInstance( pModule, NULL, FALSE )))
805 GlobalFreeAll16( pModule->self );
806 return 8; /* Insufficient memory */
809 /* Load the referenced DLLs */
811 if (!NE_LoadDLLs( pModule ))
813 NE_FreeModule( pModule->self, 0 );
814 return 2;
817 /* Load the segments */
819 NE_LoadAllSegments( pModule );
821 /* Fixup the functions prologs */
823 NE_FixupPrologs( pModule );
825 /* Make sure the usage count is 1 on the first loading of */
826 /* the module, even if it contains circular DLL references */
828 pModule->count = 1;
830 return hInstance;
833 /**********************************************************************
834 * NE_LoadModule
836 * Load first instance of NE module. (Note: caller is responsible for
837 * ensuring the module isn't already loaded!)
839 * If the module turns out to be an executable module, only a
840 * handle to a module stub is returned; this needs to be initialized
841 * by calling NE_DoLoadModule later, in the context of the newly
842 * created process.
844 * If lib_only is TRUE, however, the module is perforce treated
845 * like a DLL module, even if it is an executable module.
848 HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit, BOOL lib_only )
850 NE_MODULE *pModule;
851 HMODULE16 hModule;
852 HFILE16 hFile;
853 OFSTRUCT ofs;
855 if ((hFile = OpenFile16( name, &ofs, OF_READ )) == HFILE_ERROR16)
857 char buffer[260];
859 if(implicit)
861 /* 4 == strlen(".dll") */
862 strncpy(buffer, name, sizeof(buffer) - 1 - 4);
863 strcat(buffer, ".dll");
864 if ((hFile = OpenFile16( buffer, &ofs, OF_READ )) == HFILE_ERROR16)
865 return 2; /* File not found */
869 hModule = NE_LoadExeHeader( hFile, &ofs );
870 _lclose16( hFile );
872 if (hModule < 32) return hModule;
873 pModule = NE_GetPtr( hModule );
874 if ( !pModule ) return hModule;
876 if ( !lib_only && !( pModule->flags & NE_FFLAGS_LIBMODULE ) )
877 return hModule;
879 return NE_DoLoadModule( pModule );
883 /**********************************************************************
884 * MODULE_LoadModule16
886 * Load a NE module in the order of the loadorder specification.
887 * The caller is responsible that the module is not loaded already.
890 static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only )
892 HINSTANCE16 hinst;
893 int i;
894 module_loadorder_t *plo;
896 plo = MODULE_GetLoadOrder(libname);
898 for(i = 0; i < MODULE_LOADORDER_NTYPES; i++)
900 switch(plo->loadorder[i])
902 case MODULE_LOADORDER_DLL:
903 TRACE("Trying native dll '%s'\n", libname);
904 hinst = NE_LoadModule(libname, implicit, lib_only);
905 break;
907 case MODULE_LOADORDER_ELFDLL:
908 TRACE("Trying elfdll '%s'\n", libname);
909 hinst = ELFDLL_LoadModule16(libname, implicit);
910 break;
912 case MODULE_LOADORDER_BI:
913 TRACE("Trying built-in '%s'\n", libname);
914 hinst = fnBUILTIN_LoadModule(libname, TRUE);
915 break;
917 default:
918 ERR("Got invalid loadorder type %d (%s index %d)\n", plo->loadorder[i], plo->modulename, i);
919 /* Fall through */
921 case MODULE_LOADORDER_SO: /* This is not supported for NE modules */
922 case MODULE_LOADORDER_INVALID: /* We ignore this as it is an empty entry */
923 hinst = 2;
924 break;
927 if(hinst >= 32)
929 if(!implicit)
931 HMODULE16 hModule;
932 NE_MODULE *pModule;
934 hModule = GetModuleHandle16(libname);
935 if(!hModule)
937 ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get module handle\n",
938 libname, hinst);
939 return 6; /* ERROR_INVALID_HANDLE seems most appropriate */
942 pModule = NE_GetPtr(hModule);
943 if(!pModule)
945 ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get NE_MODULE pointer\n",
946 libname, hinst);
947 return 6; /* ERROR_INVALID_HANDLE seems most appropriate */
950 TRACE("Loaded module '%s' at 0x%04x, \n", libname, hinst);
953 * Call initialization routines for all loaded DLLs. Note that
954 * when we load implicitly linked DLLs this will be done by InitTask().
956 if(pModule->flags & NE_FFLAGS_LIBMODULE)
957 NE_InitializeDLLs(hModule);
959 return hinst;
962 if(hinst != 2)
964 /* We quit searching when we get another error than 'File not found' */
965 break;
968 return hinst; /* The last error that occured */
972 /**********************************************************************
973 * LoadModule16 (KERNEL.45)
975 HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
977 BOOL lib_only = !paramBlock || (paramBlock == (LPVOID)-1);
978 LOADPARAMS16 *params;
979 LPSTR cmd_line, new_cmd_line;
980 LPCVOID env = NULL;
981 STARTUPINFOA startup;
982 PROCESS_INFORMATION info;
983 HMODULE16 hModule;
984 NE_MODULE *pModule;
985 PDB *pdb;
987 /* Load module */
989 if ( (hModule = GetModuleHandle16(name) ) != 0 )
991 /* Special case: second instance of an already loaded NE module */
993 if ( !( pModule = NE_GetPtr( hModule ) ) ) return (HINSTANCE16)11;
994 if ( pModule->module32 ) return (HINSTANCE16)21;
996 /* Increment refcount */
998 pModule->count++;
1000 /* If library module, we just retrieve the instance handle */
1002 if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
1003 return NE_CreateInstance( pModule, NULL, TRUE );
1005 else
1007 /* Main case: load first instance of NE module */
1009 if ( (hModule = MODULE_LoadModule16( name, FALSE, lib_only )) < 32 )
1010 return hModule;
1012 if ( !(pModule = NE_GetPtr( hModule )) )
1013 return (HINSTANCE16)11;
1015 /* If library module, we're finished */
1017 if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
1018 return hModule;
1023 * At this point, we need to create a new process.
1025 * pModule points either to an already loaded module, whose refcount
1026 * has already been incremented (to avoid having the module vanish
1027 * in the meantime), or else to a stub module which contains only header
1028 * information.
1030 * All remaining initialization (really loading the module in the second
1031 * case, and creating the new instance in both cases) are to be done in
1032 * the context of the new process. This happens in the NE_InitProcess
1033 * routine, which will be called from the 32-bit process initialization.
1037 params = (LOADPARAMS16 *)paramBlock;
1038 cmd_line = (LPSTR)PTR_SEG_TO_LIN( params->cmdLine );
1039 if (!cmd_line) cmd_line = "";
1040 else if (*cmd_line) cmd_line++; /* skip the length byte */
1042 if (!(new_cmd_line = HeapAlloc( GetProcessHeap(), 0,
1043 strlen(cmd_line)+strlen(name)+2 )))
1044 return 0;
1045 strcpy( new_cmd_line, name );
1046 strcat( new_cmd_line, " " );
1047 strcat( new_cmd_line, cmd_line );
1049 if (params->hEnvironment) env = GlobalLock16( params->hEnvironment );
1051 memset( &info, '\0', sizeof(info) );
1052 memset( &startup, '\0', sizeof(startup) );
1053 startup.cb = sizeof(startup);
1054 if (params->showCmd)
1056 startup.dwFlags = STARTF_USESHOWWINDOW;
1057 startup.wShowWindow = ((UINT16 *)PTR_SEG_TO_LIN(params->showCmd))[1];
1060 SYSLEVEL_ReleaseWin16Lock();
1061 pdb = PROCESS_Create( pModule, new_cmd_line, env,
1062 NULL, NULL, TRUE, 0, &startup, &info );
1063 SYSLEVEL_RestoreWin16Lock();
1065 CloseHandle( info.hThread );
1066 CloseHandle( info.hProcess );
1068 if (params->hEnvironment) GlobalUnlock16( params->hEnvironment );
1069 HeapFree( GetProcessHeap(), 0, new_cmd_line );
1071 return GetProcessDword( info.dwProcessId, GPD_HINSTANCE16 );
1074 /**********************************************************************
1075 * NE_CreateProcess
1077 BOOL NE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line, LPCSTR env,
1078 LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
1079 BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
1080 LPPROCESS_INFORMATION info )
1082 HMODULE16 hModule;
1083 NE_MODULE *pModule;
1084 HFILE16 hFile16;
1086 SYSLEVEL_EnterWin16Lock();
1088 /* Special case: second instance of an already loaded NE module */
1090 if ( ( hModule = GetModuleHandle16( ofs->szPathName ) ) != 0 )
1092 if ( !( pModule = NE_GetPtr( hModule) )
1093 || ( pModule->flags & NE_FFLAGS_LIBMODULE )
1094 || pModule->module32 )
1096 SetLastError( ERROR_BAD_FORMAT );
1097 goto error;
1100 pModule->count++;
1103 /* Main case: load first instance of NE module */
1104 else
1106 /* If we didn't get a file handle, return */
1108 if ( hFile == HFILE_ERROR )
1109 goto error;
1111 /* Allocate temporary HFILE16 for NE_LoadFileModule */
1113 if (!DuplicateHandle( GetCurrentProcess(), hFile,
1114 GetCurrentProcess(), &hFile,
1115 0, FALSE, DUPLICATE_SAME_ACCESS ))
1117 SetLastError( ERROR_INVALID_HANDLE );
1118 goto error;
1120 hFile16 = FILE_AllocDosHandle( hFile );
1122 /* Load module */
1124 hModule = NE_LoadExeHeader( hFile16, ofs );
1125 _lclose16( hFile16 );
1127 if ( hModule < 32 )
1129 SetLastError( hModule );
1130 goto error;
1133 if ( !( pModule = NE_GetPtr( hModule ) )
1134 || ( pModule->flags & NE_FFLAGS_LIBMODULE) )
1136 GlobalFreeAll16( hModule );
1137 SetLastError( ERROR_BAD_FORMAT );
1138 goto error;
1142 SYSLEVEL_LeaveWin16Lock();
1144 if ( !PROCESS_Create( pModule, cmd_line, env,
1145 psa, tsa, inherit, flags, startup, info ) )
1146 return FALSE;
1148 return TRUE;
1150 error:
1151 SYSLEVEL_LeaveWin16Lock();
1152 return FALSE;
1155 /**********************************************************************
1156 * NE_InitProcess
1158 BOOL NE_InitProcess( NE_MODULE *pModule )
1160 HINSTANCE16 hInstance, hPrevInstance;
1161 BOOL retv = TRUE;
1163 SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
1164 WORD sp;
1165 TDB *pTask;
1167 SYSLEVEL_EnterWin16Lock();
1169 if ( pModule->count > 0 )
1171 /* Second instance of an already loaded NE module */
1172 /* Note that the refcount was already incremented by the parent */
1174 hInstance = NE_CreateInstance( pModule, &hPrevInstance, FALSE );
1175 if ( hInstance != hPrevInstance ) /* not a library */
1176 NE_LoadSegment( pModule, pModule->dgroup );
1178 else
1180 /* Load first instance of NE module */
1182 pModule->flags |= NE_FFLAGS_GUI; /* FIXME: is this necessary? */
1184 hInstance = NE_DoLoadModule( pModule );
1185 hPrevInstance = 0;
1187 if ( hInstance < 32 )
1189 SetLastError( hInstance );
1190 retv = FALSE;
1194 /* Enter instance handles into task struct */
1196 pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1197 pTask->hInstance = hInstance;
1198 pTask->hPrevInstance = hPrevInstance;
1200 /* Use DGROUP for 16-bit stack */
1202 if (!(sp = pModule->sp))
1203 sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
1204 sp &= ~1; sp -= sizeof(STACK16FRAME);
1205 pTask->teb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( hInstance, sp );
1207 SYSLEVEL_LeaveWin16Lock();
1209 return retv;
1212 /***********************************************************************
1213 * LoadLibrary16 (KERNEL.95)
1215 * In Win95 LoadLibrary16("c:/junkname/user.foo") returns the HINSTANCE
1216 * to user.exe. As GetModuleHandle as of 990425 explicitly asks _not_
1217 * to change its handling of extensions, we have to try a stripped down
1218 * libname here too (bon 990425)
1220 HINSTANCE16 WINAPI LoadLibrary16( LPCSTR libname )
1222 char strippedname[256];
1223 char *dirsep1,*dirsep2;
1224 HINSTANCE16 ret;
1226 dirsep1=strrchr(libname,'\\');
1227 dirsep2=strrchr(libname,'/');
1228 dirsep1=MAX(dirsep1,dirsep2);
1229 if (!dirsep1)
1230 dirsep1 =(LPSTR)libname;
1231 else
1232 dirsep1++;
1233 lstrcpynA(strippedname,dirsep1,256);
1234 dirsep1=strchr(strippedname,'.');
1235 if (dirsep1)
1236 *dirsep1=0;
1238 TRACE("looking for (%p) %s and %s \n",
1239 libname, libname,strippedname );
1241 /* Load library module */
1242 ret= LoadModule16( strippedname, (LPVOID)-1 );
1243 if (ret > HINSTANCE_ERROR)
1244 return ret;
1245 return LoadModule16(libname, (LPVOID)-1 );
1249 /**********************************************************************
1250 * MODULE_CallWEP
1252 * Call a DLL's WEP, allowing it to shut down.
1253 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
1255 static BOOL16 MODULE_CallWEP( HMODULE16 hModule )
1257 FARPROC16 WEP = (FARPROC16)0;
1258 WORD ordinal = NE_GetOrdinal( hModule, "WEP" );
1260 if (ordinal) WEP = NE_GetEntryPoint( hModule, ordinal );
1261 if (!WEP)
1263 WARN("module %04x doesn't have a WEP\n", hModule );
1264 return FALSE;
1266 return Callbacks->CallWindowsExitProc( WEP, WEP_FREE_DLL );
1270 /**********************************************************************
1271 * NE_FreeModule
1273 * Implementation of FreeModule16().
1275 static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep )
1277 HMODULE16 *hPrevModule;
1278 NE_MODULE *pModule;
1279 HMODULE16 *pModRef;
1280 int i;
1282 if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
1283 hModule = pModule->self;
1285 TRACE("%04x count %d\n", hModule, pModule->count );
1287 if (((INT16)(--pModule->count)) > 0 ) return TRUE;
1288 else pModule->count = 0;
1290 if (pModule->flags & NE_FFLAGS_BUILTIN)
1291 return FALSE; /* Can't free built-in module */
1293 if (call_wep && !(pModule->flags & NE_FFLAGS_WIN32))
1295 if (pModule->flags & NE_FFLAGS_LIBMODULE)
1297 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
1298 MODULE_CallWEP( hModule );
1300 /* Free the objects owned by the DLL module */
1302 if (pTask && pTask->userhandler)
1303 pTask->userhandler( hModule, USIG16_DLL_UNLOAD, 0,
1304 pTask->hInstance, pTask->hQueue );
1306 PROCESS_CallUserSignalProc( USIG_DLL_UNLOAD_WIN16, hModule );
1308 else
1309 call_wep = FALSE; /* We are freeing a task -> no more WEPs */
1313 /* Clear magic number just in case */
1315 pModule->magic = pModule->self = 0;
1317 /* Remove it from the linked list */
1319 hPrevModule = &hFirstModule;
1320 while (*hPrevModule && (*hPrevModule != hModule))
1322 hPrevModule = &(NE_GetPtr( *hPrevModule ))->next;
1324 if (*hPrevModule) *hPrevModule = pModule->next;
1326 /* Free the referenced modules */
1328 pModRef = (HMODULE16*)NE_MODULE_TABLE( pModule );
1329 for (i = 0; i < pModule->modref_count; i++, pModRef++)
1331 NE_FreeModule( *pModRef, call_wep );
1334 /* Free the module storage */
1336 GlobalFreeAll16( hModule );
1338 /* Remove module from cache */
1340 if (pCachedModule == pModule) pCachedModule = NULL;
1341 return TRUE;
1345 /**********************************************************************
1346 * FreeModule16 (KERNEL.46)
1348 BOOL16 WINAPI FreeModule16( HMODULE16 hModule )
1350 return NE_FreeModule( hModule, TRUE );
1354 /***********************************************************************
1355 * FreeLibrary16 (KERNEL.96)
1357 void WINAPI FreeLibrary16( HINSTANCE16 handle )
1359 TRACE("%04x\n", handle );
1360 FreeModule16( handle );
1364 /**********************************************************************
1365 * GetModuleName (KERNEL.27)
1367 BOOL16 WINAPI GetModuleName16( HINSTANCE16 hinst, LPSTR buf, INT16 count )
1369 NE_MODULE *pModule;
1370 BYTE *p;
1372 if (!(pModule = NE_GetPtr( hinst ))) return FALSE;
1373 p = (BYTE *)pModule + pModule->name_table;
1374 if (count > *p) count = *p + 1;
1375 if (count > 0)
1377 memcpy( buf, p + 1, count - 1 );
1378 buf[count-1] = '\0';
1380 return TRUE;
1384 /**********************************************************************
1385 * GetModuleUsage (KERNEL.48)
1387 INT16 WINAPI GetModuleUsage16( HINSTANCE16 hModule )
1389 NE_MODULE *pModule = NE_GetPtr( hModule );
1390 return pModule ? pModule->count : 0;
1394 /**********************************************************************
1395 * GetExpWinVer (KERNEL.167)
1397 WORD WINAPI GetExpWinVer16( HMODULE16 hModule )
1399 NE_MODULE *pModule = NE_GetPtr( hModule );
1400 return pModule ? pModule->expected_version : 0;
1404 /**********************************************************************
1405 * GetModuleFileName16 (KERNEL.49)
1407 INT16 WINAPI GetModuleFileName16( HINSTANCE16 hModule, LPSTR lpFileName,
1408 INT16 nSize )
1410 NE_MODULE *pModule;
1412 if (!hModule) hModule = GetCurrentTask();
1413 if (!(pModule = NE_GetPtr( hModule ))) return 0;
1414 lstrcpynA( lpFileName, NE_MODULE_NAME(pModule), nSize );
1415 TRACE("%s\n", lpFileName );
1416 return strlen(lpFileName);
1420 /**********************************************************************
1421 * GetModuleHandle16 (KERNEL.47)
1423 * Find a module from a module name.
1425 * NOTE: The current implementation works the same way the Windows 95 one
1426 * does. Do not try to 'fix' it, fix the callers.
1427 * + It does not do ANY extension handling (except that strange .EXE bit)!
1428 * + It does not care about paths, just about basenames. (same as Windows)
1430 * RETURNS
1431 * LOWORD:
1432 * the win16 module handle if found
1433 * 0 if not
1434 * HIWORD (undocumented, see "Undocumented Windows", chapter 5):
1435 * Always hFirstModule
1437 DWORD WINAPI WIN16_GetModuleHandle( SEGPTR name )
1439 if (HIWORD(name) == 0)
1440 return MAKELONG(GetExePtr( (HINSTANCE16)name), hFirstModule );
1441 return MAKELONG(GetModuleHandle16( PTR_SEG_TO_LIN(name)), hFirstModule );
1444 HMODULE16 WINAPI GetModuleHandle16( LPCSTR name )
1446 HMODULE16 hModule = hFirstModule;
1447 LPSTR s;
1448 BYTE len, *name_table;
1449 char tmpstr[128];
1450 NE_MODULE *pModule;
1452 TRACE("(%s)\n", name);
1454 if (!HIWORD(name))
1455 return GetExePtr(LOWORD(name));
1457 len = strlen(name);
1458 if (!len)
1459 return 0;
1461 strncpy(tmpstr, name, sizeof(tmpstr));
1462 tmpstr[sizeof(tmpstr)-1] = '\0';
1464 /* If 'name' matches exactly the module name of a module:
1465 * Return its handle.
1467 for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1469 pModule = NE_GetPtr( hModule );
1470 if (!pModule) break;
1471 if (pModule->flags & NE_FFLAGS_WIN32) continue;
1472 if (pModule->flags & NE_FFLAGS_WIN32) continue;
1474 name_table = (BYTE *)pModule + pModule->name_table;
1475 if ((*name_table == len) && !strncmp(name, name_table+1, len))
1476 return hModule;
1479 /* If uppercased 'name' matches exactly the module name of a module:
1480 * Return its handle
1482 for (s = tmpstr; *s; s++)
1483 *s = toupper(*s);
1485 for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1487 pModule = NE_GetPtr( hModule );
1488 if (!pModule) break;
1490 name_table = (BYTE *)pModule + pModule->name_table;
1491 /* FIXME: the lstrncmpiA is WRONG. It should not be case insensitive,
1492 * but case sensitive! (Unfortunately Winword 6 and subdlls have
1493 * lowercased module names, but try to load uppercase DLLs, so this
1494 * 'i' compare is just a quickfix until the loader handles that
1495 * correctly. -MM 990705
1497 if ((*name_table == len) && !lstrncmpiA(tmpstr, name_table+1, len))
1498 return hModule;
1501 /* If the base filename of 'name' matches the base filename of the module
1502 * filename of some module (case-insensitive compare):
1503 * Return its handle.
1506 /* basename: search backwards in passed name to \ / or : */
1507 s = tmpstr + strlen(tmpstr);
1508 while (s > tmpstr)
1510 if (s[-1]=='/' || s[-1]=='\\' || s[-1]==':')
1511 break;
1512 s--;
1515 /* search this in loaded filename list */
1516 for (hModule = hFirstModule; hModule ; hModule = pModule->next)
1518 char *loadedfn;
1519 OFSTRUCT *ofs;
1521 pModule = NE_GetPtr( hModule );
1522 if (!pModule) break;
1523 if (!pModule->fileinfo) continue;
1524 if (pModule->flags & NE_FFLAGS_WIN32) continue;
1526 ofs = (OFSTRUCT*)((BYTE *)pModule + pModule->fileinfo);
1527 loadedfn = ((char*)ofs->szPathName) + strlen(ofs->szPathName);
1528 /* basename: search backwards in pathname to \ / or : */
1529 while (loadedfn > (char*)ofs->szPathName)
1531 if (loadedfn[-1]=='/' || loadedfn[-1]=='\\' || loadedfn[-1]==':')
1532 break;
1533 loadedfn--;
1535 /* case insensitive compare ... */
1536 if (!lstrcmpiA(loadedfn, s))
1537 return hModule;
1540 /* If the extension of 'name' is '.EXE' and the base filename of 'name'
1541 * matches the base filename of the module filename of some 32-bit module:
1542 * Return the corresponding 16-bit dummy module handle.
1544 if (len >= 4 && !strcasecmp(name+len-4, ".EXE"))
1546 HMODULE hModule = GetModuleHandleA( name );
1547 if ( hModule )
1548 return MapHModuleLS( hModule );
1551 if (!strcmp(tmpstr,"MSDOS"))
1552 return 1;
1554 if (!strcmp(tmpstr,"TIMER"))
1556 FIXME("Eh... Should return caller's code segment, expect crash\n");
1557 return 0;
1560 return 0;
1564 /**********************************************************************
1565 * ModuleFirst (TOOLHELP.59)
1567 BOOL16 WINAPI ModuleFirst16( MODULEENTRY *lpme )
1569 lpme->wNext = hFirstModule;
1570 return ModuleNext16( lpme );
1574 /**********************************************************************
1575 * ModuleNext (TOOLHELP.60)
1577 BOOL16 WINAPI ModuleNext16( MODULEENTRY *lpme )
1579 NE_MODULE *pModule;
1580 char *name;
1582 if (!lpme->wNext) return FALSE;
1583 if (!(pModule = NE_GetPtr( lpme->wNext ))) return FALSE;
1584 name = (char *)pModule + pModule->name_table;
1585 memcpy( lpme->szModule, name + 1, min(*name, MAX_MODULE_NAME) );
1586 lpme->szModule[min(*name, MAX_MODULE_NAME)] = '\0';
1587 lpme->hModule = lpme->wNext;
1588 lpme->wcUsage = pModule->count;
1589 lstrcpynA( lpme->szExePath, NE_MODULE_NAME(pModule), sizeof(lpme->szExePath) );
1590 lpme->wNext = pModule->next;
1591 return TRUE;
1595 /**********************************************************************
1596 * ModuleFindName (TOOLHELP.61)
1598 BOOL16 WINAPI ModuleFindName16( MODULEENTRY *lpme, LPCSTR name )
1600 lpme->wNext = GetModuleHandle16( name );
1601 return ModuleNext16( lpme );
1605 /**********************************************************************
1606 * ModuleFindHandle (TOOLHELP.62)
1608 BOOL16 WINAPI ModuleFindHandle16( MODULEENTRY *lpme, HMODULE16 hModule )
1610 hModule = GetExePtr( hModule );
1611 lpme->wNext = hModule;
1612 return ModuleNext16( lpme );
1616 /***************************************************************************
1617 * IsRomModule16 (KERNEL.323)
1619 BOOL16 WINAPI IsRomModule16( HMODULE16 unused )
1621 return FALSE;
1624 /***************************************************************************
1625 * IsRomFile16 (KERNEL.326)
1627 BOOL16 WINAPI IsRomFile16( HFILE16 unused )
1629 return FALSE;
1632 /***************************************************************************
1633 * MapHModuleLS (KERNEL32.520)
1635 HMODULE16 WINAPI MapHModuleLS(HMODULE hmod) {
1636 NE_MODULE *pModule;
1638 if (!hmod)
1639 return ((TDB*)GlobalLock16(GetCurrentTask()))->hInstance;
1640 if (!HIWORD(hmod))
1641 return hmod; /* we already have a 16 bit module handle */
1642 pModule = (NE_MODULE*)GlobalLock16(hFirstModule);
1643 while (pModule) {
1644 if (pModule->module32 == hmod)
1645 return pModule->self;
1646 pModule = (NE_MODULE*)GlobalLock16(pModule->next);
1648 return 0;
1651 /***************************************************************************
1652 * MapHModuleSL (KERNEL32.521)
1654 HMODULE WINAPI MapHModuleSL(HMODULE16 hmod) {
1655 NE_MODULE *pModule;
1657 if (!hmod) {
1658 TDB *pTask = (TDB*)GlobalLock16(GetCurrentTask());
1660 hmod = pTask->hModule;
1662 pModule = (NE_MODULE*)GlobalLock16(hmod);
1663 if ( (pModule->magic!=IMAGE_OS2_SIGNATURE) ||
1664 !(pModule->flags & NE_FFLAGS_WIN32)
1666 return 0;
1667 return pModule->module32;
1670 /***************************************************************************
1671 * MapHInstLS (KERNEL32.516)
1673 void WINAPI REGS_FUNC(MapHInstLS)( CONTEXT *context )
1675 #ifdef __i386__
1676 EAX_reg(context) = MapHModuleLS(EAX_reg(context));
1677 #endif
1680 /***************************************************************************
1681 * MapHInstSL (KERNEL32.518)
1683 void WINAPI REGS_FUNC(MapHInstSL)( CONTEXT *context )
1685 #ifdef __i386__
1686 EAX_reg(context) = MapHModuleSL(EAX_reg(context));
1687 #endif
1690 /***************************************************************************
1691 * MapHInstLS_PN (KERNEL32.517)
1693 void WINAPI REGS_FUNC(MapHInstLS_PN)( CONTEXT *context )
1695 #ifdef __i386__
1696 if (EAX_reg(context))
1697 EAX_reg(context) = MapHModuleLS(EAX_reg(context));
1698 #endif
1701 /***************************************************************************
1702 * MapHInstSL_PN (KERNEL32.519)
1704 void WINAPI REGS_FUNC(MapHInstSL_PN)( CONTEXT *context )
1706 #ifdef __i386__
1707 if (EAX_reg(context))
1708 EAX_reg(context) = MapHModuleSL(EAX_reg(context));
1709 #endif
1712 /***************************************************************************
1713 * WIN16_MapHInstLS (KERNEL.472)
1715 VOID WINAPI WIN16_MapHInstLS( CONTEXT86 *context )
1717 EAX_reg(context) = MapHModuleLS(EAX_reg(context));
1720 /***************************************************************************
1721 * WIN16_MapHInstSL (KERNEL.473)
1723 VOID WINAPI WIN16_MapHInstSL( CONTEXT86 *context )
1725 EAX_reg(context) = MapHModuleSL(EAX_reg(context));