4 * Copyright 1995 Alexandre Julliard
13 #include "wine/winbase16.h"
28 #include "stackframe.h"
29 #include "debugtools.h"
31 #include "loadorder.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 /***********************************************************************
53 NE_MODULE
*NE_GetPtr( HMODULE16 hModule
)
55 return (NE_MODULE
*)GlobalLock16( GetExePtr(hModule
) );
59 /***********************************************************************
62 void NE_DumpModule( HMODULE16 hModule
)
72 if (!(pModule
= NE_GetPtr( hModule
)))
74 MESSAGE( "**** %04x is not a module handle\n", hModule
);
78 /* Dump the module info */
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 */
95 DPRINTF( "Filename: '%s'\n", NE_MODULE_NAME(pModule
) );
97 /* Dump the segment table */
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 */
108 DPRINTF( "Resource table:\n" );
109 if (pModule
->res_table
)
111 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
112 DPRINTF( "Alignment: %d\n", *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 */
128 DPRINTF( "Resident-name table:\n" );
129 pstr
= (char *)pModule
+ pModule
->name_table
;
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 */
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
++)
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 */
154 DPRINTF( "Entry table:\n" );
155 bundle
= (ET_BUNDLE
*)((BYTE
*)pModule
+pModule
->entry_table
);
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
);
165 DPRINTF("%d: %02x:%04x (fixed)\n", ordinal
++, entry
->segnum
, entry
->offs
);
168 } while ( (bundle
->next
)
169 && (bundle
= ((ET_BUNDLE
*)((BYTE
*)pModule
+ bundle
->next
))) );
171 /* Dump the non-resident names table */
173 DPRINTF( "Non-resident names table:\n" );
174 if (pModule
->nrname_handle
)
176 pstr
= (char *)GlobalLock16( pModule
->nrname_handle
);
179 DPRINTF( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
180 *(WORD
*)(pstr
+ *pstr
+ 1) );
181 pstr
+= *pstr
+ 1 + sizeof(WORD
);
188 /***********************************************************************
191 * Walk the module list and print the modules.
193 void NE_WalkModules(void)
195 HMODULE16 hModule
= hFirstModule
;
196 MESSAGE( "Module Flags Name\n" );
199 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
202 MESSAGE( "Bad module %04x in list\n", hModule
);
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 /**********************************************************************
216 void NE_RegisterModule( NE_MODULE
*pModule
)
218 pModule
->next
= hFirstModule
;
219 hFirstModule
= pModule
->self
;
223 /***********************************************************************
226 * Lookup the ordinal for a given name.
228 WORD
NE_GetOrdinal( HMODULE16 hModule
, const char *name
)
230 unsigned char buffer
[256], *cpnt
;
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
);
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
);
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
);
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
)
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
))
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
++)
320 offset
= entry
->offs
;
322 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
323 else sel
= GlobalHandleToSel16(NE_SEG_TABLE(pModule
)[sel
-1].hSeg
);
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
);
329 return (FARPROC16
)fnSNOOP16_GetProcAddress16(hModule
,ordinal
,(FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( sel
, offset
));
333 /***********************************************************************
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
)
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
);
357 entry
= (ET_ENTRY
*)((BYTE
*)bundle
+6);
358 for (i
=0; i
< (ordinal
- bundle
->first
- 1); i
++)
361 entry
->offs
= offset
;
366 /***********************************************************************
369 HANDLE
NE_OpenFile( NE_MODULE
*pModule
)
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
);
385 /* FIXME: should not be necessary */
386 cachedfd
= ConvertToGlobalHandle(cachedfd
);
387 TRACE("opened '%s' -> %d\n",
393 /***********************************************************************
396 static HMODULE16
NE_LoadExeHeader( HFILE16 hFile
, OFSTRUCT
*ofs
)
398 IMAGE_DOS_HEADER mz_header
;
399 IMAGE_OS2_HEADER ne_header
;
403 BYTE
*pData
, *pTempEntryTable
;
404 char *buffer
, *fastload
= NULL
;
405 int fastload_offset
= 0, fastload_length
= 0;
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
) +
438 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
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 */
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
) );
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");
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
));
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
),
508 HeapFree( SystemHeap
, 0, buffer
);
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
);
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
,
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
),
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
,
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
);
602 HeapFree( SystemHeap
, 0, fastload
);
603 GlobalFree16( hModule
);
604 return (HMODULE16
)11; /* invalid exe */
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
++))
619 bundle
->last
+= nr_entries
;
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);*/
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);*/
644 if (bundle
->first
== bundle
->last
)
646 bundle
->first
+= nr_entries
;
647 bundle
->last
+= nr_entries
;
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
;
658 (BYTE
*)entry
+= sizeof(ET_BUNDLE
);
662 HeapFree( SystemHeap
, 0, pTempEntryTable
);
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;
686 /* Free the fast-load area */
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
);
738 /***********************************************************************
741 * Load all DLLs implicitly linked to a module.
743 static BOOL
NE_LoadDLLs( NE_MODULE
*pModule
)
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
++)
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. */
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
);
772 *pModRef
= GetExePtr( hDLL
);
775 else /* Increment the reference count of the DLL */
779 pOldDLL
= NE_GetPtr( *pModRef
);
780 if (pOldDLL
) pOldDLL
->count
++;
787 /**********************************************************************
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 );
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 */
833 /**********************************************************************
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
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
)
855 if ((hFile
= OpenFile16( name
, &ofs
, OF_READ
)) == HFILE_ERROR16
)
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
);
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
) )
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
)
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
);
907 case MODULE_LOADORDER_ELFDLL
:
908 TRACE("Trying elfdll '%s'\n", libname
);
909 hinst
= ELFDLL_LoadModule16(libname
, implicit
);
912 case MODULE_LOADORDER_BI
:
913 TRACE("Trying built-in '%s'\n", libname
);
914 hinst
= fnBUILTIN_LoadModule(libname
, TRUE
);
918 ERR("Got invalid loadorder type %d (%s index %d)\n", plo
->loadorder
[i
], plo
->modulename
, i
);
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 */
934 hModule
= GetModuleHandle16(libname
);
937 ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get module handle\n",
939 return 6; /* ERROR_INVALID_HANDLE seems most appropriate */
942 pModule
= NE_GetPtr(hModule
);
945 ERR("Serious trouble. Just loaded module '%s' (hinst=0x%04x), but can't get NE_MODULE pointer\n",
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
);
964 /* We quit searching when we get another error than 'File not found' */
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
;
981 STARTUPINFOA startup
;
982 PROCESS_INFORMATION info
;
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 */
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
);
1007 /* Main case: load first instance of NE module */
1009 if ( (hModule
= MODULE_LoadModule16( name
, FALSE
, lib_only
)) < 32 )
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
)
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
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 )))
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 /**********************************************************************
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
)
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
);
1103 /* Main case: load first instance of NE module */
1106 /* If we didn't get a file handle, return */
1108 if ( hFile
== HFILE_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
);
1120 hFile16
= FILE_AllocDosHandle( hFile
);
1124 hModule
= NE_LoadExeHeader( hFile16
, ofs
);
1125 _lclose16( hFile16
);
1129 SetLastError( hModule
);
1133 if ( !( pModule
= NE_GetPtr( hModule
) )
1134 || ( pModule
->flags
& NE_FFLAGS_LIBMODULE
) )
1136 GlobalFreeAll16( hModule
);
1137 SetLastError( ERROR_BAD_FORMAT
);
1142 SYSLEVEL_LeaveWin16Lock();
1144 if ( !PROCESS_Create( pModule
, cmd_line
, env
,
1145 psa
, tsa
, inherit
, flags
, startup
, info
) )
1151 SYSLEVEL_LeaveWin16Lock();
1155 /**********************************************************************
1158 BOOL
NE_InitProcess( NE_MODULE
*pModule
)
1160 HINSTANCE16 hInstance
, hPrevInstance
;
1163 SEGTABLEENTRY
*pSegTable
= NE_SEG_TABLE( pModule
);
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
);
1180 /* Load first instance of NE module */
1182 pModule
->flags
|= NE_FFLAGS_GUI
; /* FIXME: is this necessary? */
1184 hInstance
= NE_DoLoadModule( pModule
);
1187 if ( hInstance
< 32 )
1189 SetLastError( hInstance
);
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();
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
;
1226 dirsep1
=strrchr(libname
,'\\');
1227 dirsep2
=strrchr(libname
,'/');
1228 dirsep1
=MAX(dirsep1
,dirsep2
);
1230 dirsep1
=(LPSTR
)libname
;
1233 lstrcpynA(strippedname
,dirsep1
,256);
1234 dirsep1
=strchr(strippedname
,'.');
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
)
1245 return LoadModule16(libname
, (LPVOID
)-1 );
1249 /**********************************************************************
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
);
1263 WARN("module %04x doesn't have a WEP\n", hModule
);
1266 return Callbacks
->CallWindowsExitProc( WEP
, WEP_FREE_DLL
);
1270 /**********************************************************************
1273 * Implementation of FreeModule16().
1275 static BOOL16
NE_FreeModule( HMODULE16 hModule
, BOOL call_wep
)
1277 HMODULE16
*hPrevModule
;
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
);
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
;
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
)
1372 if (!(pModule
= NE_GetPtr( hinst
))) return FALSE
;
1373 p
= (BYTE
*)pModule
+ pModule
->name_table
;
1374 if (count
> *p
) count
= *p
+ 1;
1377 memcpy( buf
, p
+ 1, count
- 1 );
1378 buf
[count
-1] = '\0';
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
,
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)
1432 * the win16 module handle if found
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
;
1448 BYTE len
, *name_table
;
1452 TRACE("(%s)\n", name
);
1455 return GetExePtr(LOWORD(name
));
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
))
1479 /* If uppercased 'name' matches exactly the module name of a module:
1482 for (s
= tmpstr
; *s
; 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
))
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
);
1510 if (s
[-1]=='/' || s
[-1]=='\\' || s
[-1]==':')
1515 /* search this in loaded filename list */
1516 for (hModule
= hFirstModule
; hModule
; hModule
= pModule
->next
)
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]==':')
1535 /* case insensitive compare ... */
1536 if (!lstrcmpiA(loadedfn
, s
))
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
);
1548 return MapHModuleLS( hModule
);
1551 if (!strcmp(tmpstr
,"MSDOS"))
1554 if (!strcmp(tmpstr
,"TIMER"))
1556 FIXME("Eh... Should return caller's code segment, expect crash\n");
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
)
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
;
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
)
1624 /***************************************************************************
1625 * IsRomFile16 (KERNEL.326)
1627 BOOL16 WINAPI
IsRomFile16( HFILE16 unused
)
1632 /***************************************************************************
1633 * MapHModuleLS (KERNEL32.520)
1635 HMODULE16 WINAPI
MapHModuleLS(HMODULE hmod
) {
1639 return ((TDB
*)GlobalLock16(GetCurrentTask()))->hInstance
;
1641 return hmod
; /* we already have a 16 bit module handle */
1642 pModule
= (NE_MODULE
*)GlobalLock16(hFirstModule
);
1644 if (pModule
->module32
== hmod
)
1645 return pModule
->self
;
1646 pModule
= (NE_MODULE
*)GlobalLock16(pModule
->next
);
1651 /***************************************************************************
1652 * MapHModuleSL (KERNEL32.521)
1654 HMODULE WINAPI
MapHModuleSL(HMODULE16 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
)
1667 return pModule
->module32
;
1670 /***************************************************************************
1671 * MapHInstLS (KERNEL32.516)
1673 void WINAPI
REGS_FUNC(MapHInstLS
)( CONTEXT
*context
)
1676 EAX_reg(context
) = MapHModuleLS(EAX_reg(context
));
1680 /***************************************************************************
1681 * MapHInstSL (KERNEL32.518)
1683 void WINAPI
REGS_FUNC(MapHInstSL
)( CONTEXT
*context
)
1686 EAX_reg(context
) = MapHModuleSL(EAX_reg(context
));
1690 /***************************************************************************
1691 * MapHInstLS_PN (KERNEL32.517)
1693 void WINAPI
REGS_FUNC(MapHInstLS_PN
)( CONTEXT
*context
)
1696 if (EAX_reg(context
))
1697 EAX_reg(context
) = MapHModuleLS(EAX_reg(context
));
1701 /***************************************************************************
1702 * MapHInstSL_PN (KERNEL32.519)
1704 void WINAPI
REGS_FUNC(MapHInstSL_PN
)( CONTEXT
*context
)
1707 if (EAX_reg(context
))
1708 EAX_reg(context
) = MapHModuleSL(EAX_reg(context
));
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
));