4 * Copyright 1995 Alexandre Julliard
12 #include "wine/winbase16.h"
26 #include "stackframe.h"
29 FARPROC16 (*fnSNOOP16_GetProcAddress16
)(HMODULE16
,DWORD
,FARPROC16
) = NULL
;
30 void (*fnSNOOP16_RegisterDLL
)(NE_MODULE
*,LPCSTR
) = NULL
;
32 #define hFirstModule (pThhook->hExeHead)
34 static NE_MODULE
*pCachedModule
= 0; /* Module cached by NE_OpenFile */
36 static HMODULE16
NE_LoadBuiltin(LPCSTR name
,BOOL32 force
) { return 0; }
37 HMODULE16 (*fnBUILTIN_LoadModule
)(LPCSTR name
,BOOL32 force
) = NE_LoadBuiltin
;
40 /***********************************************************************
43 NE_MODULE
*NE_GetPtr( HMODULE16 hModule
)
45 return (NE_MODULE
*)GlobalLock16( GetExePtr(hModule
) );
49 /***********************************************************************
52 void NE_DumpModule( HMODULE16 hModule
)
60 if (!(pModule
= NE_GetPtr( hModule
)))
62 MSG( "**** %04x is not a module handle\n", hModule
);
66 /* Dump the module info */
68 DUMP( "Module %04x:\n", hModule
);
69 DUMP( "count=%d flags=%04x heap=%d stack=%d\n",
70 pModule
->count
, pModule
->flags
,
71 pModule
->heap_size
, pModule
->stack_size
);
72 DUMP( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
73 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
74 pModule
->seg_count
, pModule
->modref_count
);
75 DUMP( "os_flags=%d swap_area=%d version=%04x\n",
76 pModule
->os_flags
, pModule
->min_swap_area
,
77 pModule
->expected_version
);
78 if (pModule
->flags
& NE_FFLAGS_WIN32
)
79 DUMP( "PE module=%08x\n", pModule
->module32
);
81 /* Dump the file info */
83 DUMP( "Filename: '%s'\n", NE_MODULE_NAME(pModule
) );
85 /* Dump the segment table */
87 DUMP( "Segment table:\n" );
88 pSeg
= NE_SEG_TABLE( pModule
);
89 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
90 DUMP( "%02x: pos=%d size=%d flags=%04x minsize=%d hSeg=%04x\n",
91 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
92 pSeg
->minsize
, pSeg
->hSeg
);
94 /* Dump the resource table */
96 DUMP( "Resource table:\n" );
97 if (pModule
->res_table
)
99 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
100 DUMP( "Alignment: %d\n", *pword
++ );
103 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
104 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
105 DUMP( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
106 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
107 DUMP( "offset=%d len=%d id=%04x\n",
108 pname
->offset
, pname
->length
, pname
->id
);
109 pword
= (WORD
*)pname
;
112 else DUMP( "None\n" );
114 /* Dump the resident name table */
116 DUMP( "Resident-name table:\n" );
117 pstr
= (char *)pModule
+ pModule
->name_table
;
120 DUMP( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
121 *(WORD
*)(pstr
+ *pstr
+ 1) );
122 pstr
+= *pstr
+ 1 + sizeof(WORD
);
125 /* Dump the module reference table */
127 DUMP( "Module ref table:\n" );
128 if (pModule
->modref_table
)
130 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
131 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
134 GetModuleName( *pword
, name
, sizeof(name
) );
135 DUMP( "%d: %04x -> '%s'\n", i
, *pword
, name
);
138 else DUMP( "None\n" );
140 /* Dump the entry table */
142 DUMP( "Entry table:\n" );
143 pstr
= (char *)pModule
+ pModule
->entry_table
;
147 DUMP( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
153 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
159 DUMP( "%d: %02x:%04x (moveable)\n",
160 ordinal
++, pstr
[3], *(WORD
*)(pstr
+ 4) );
170 DUMP( "%d: %04x (fixed)\n",
171 ordinal
++, *(WORD
*)(pstr
+ 1) );
177 /* Dump the non-resident names table */
179 DUMP( "Non-resident names table:\n" );
180 if (pModule
->nrname_handle
)
182 pstr
= (char *)GlobalLock16( pModule
->nrname_handle
);
185 DUMP( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
186 *(WORD
*)(pstr
+ *pstr
+ 1) );
187 pstr
+= *pstr
+ 1 + sizeof(WORD
);
194 /***********************************************************************
197 * Walk the module list and print the modules.
199 void NE_WalkModules(void)
201 HMODULE16 hModule
= hFirstModule
;
202 MSG( "Module Flags Name\n" );
205 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
208 MSG( "Bad module %04x in list\n", hModule
);
211 MSG( " %04x %04x %.*s\n", hModule
, pModule
->flags
,
212 *((char *)pModule
+ pModule
->name_table
),
213 (char *)pModule
+ pModule
->name_table
+ 1 );
214 hModule
= pModule
->next
;
219 /**********************************************************************
222 void NE_RegisterModule( NE_MODULE
*pModule
)
224 pModule
->next
= hFirstModule
;
225 hFirstModule
= pModule
->self
;
229 /***********************************************************************
232 * Lookup the ordinal for a given name.
234 WORD
NE_GetOrdinal( HMODULE16 hModule
, const char *name
)
236 unsigned char buffer
[256], *cpnt
;
240 if (!(pModule
= NE_GetPtr( hModule
))) return 0;
241 assert( !(pModule
->flags
& NE_FFLAGS_WIN32
) );
243 TRACE( module
, "(%04x,'%s')\n", hModule
, name
);
245 /* First handle names of the form '#xxxx' */
247 if (name
[0] == '#') return atoi( name
+ 1 );
249 /* Now copy and uppercase the string */
251 strcpy( buffer
, name
);
252 CharUpper32A( buffer
);
253 len
= strlen( buffer
);
255 /* First search the resident names */
257 cpnt
= (char *)pModule
+ pModule
->name_table
;
259 /* Skip the first entry (module name) */
260 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
263 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
265 TRACE(module
, " Found: ordinal=%d\n",
266 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
267 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
269 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
272 /* Now search the non-resident names table */
274 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
275 cpnt
= (char *)GlobalLock16( pModule
->nrname_handle
);
277 /* Skip the first entry (module description string) */
278 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
281 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
283 TRACE(module
, " Found: ordinal=%d\n",
284 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
285 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
287 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
293 /***********************************************************************
294 * NE_GetEntryPoint (WPROCS.27)
296 * Return the entry point for a given ordinal.
298 FARPROC16
NE_GetEntryPoint( HMODULE16 hModule
, WORD ordinal
)
300 return NE_GetEntryPointEx( hModule
, ordinal
, TRUE
);
302 FARPROC16
NE_GetEntryPointEx( HMODULE16 hModule
, WORD ordinal
, BOOL16 snoop
)
309 if (!(pModule
= NE_GetPtr( hModule
))) return 0;
310 assert( !(pModule
->flags
& NE_FFLAGS_WIN32
) );
312 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
313 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
315 /* Skipping this bundle */
319 case 0: p
+= 2; break; /* unused */
320 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
321 default: p
+= 2 + *p
* 3; break; /* fixed */
330 case 0xff: /* moveable */
331 p
+= 2 + 6 * (ordinal
- curOrdinal
);
333 offset
= *(WORD
*)(p
+ 4);
337 p
+= 2 + 3 * (ordinal
- curOrdinal
);
338 offset
= *(WORD
*)(p
+ 1);
342 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
343 else sel
= GlobalHandleToSel(NE_SEG_TABLE(pModule
)[sel
-1].hSeg
);
345 return (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( sel
, offset
);
346 if (!snoop
|| !fnSNOOP16_GetProcAddress16
)
347 return (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( sel
, offset
);
349 return (FARPROC16
)fnSNOOP16_GetProcAddress16(hModule
,ordinal
,(FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( sel
, offset
));
353 /***********************************************************************
356 * Change the value of an entry point. Use with caution!
357 * It can only change the offset value, not the selector.
359 BOOL16
NE_SetEntryPoint( HMODULE16 hModule
, WORD ordinal
, WORD offset
)
365 if (!(pModule
= NE_GetPtr( hModule
))) return FALSE
;
366 assert( !(pModule
->flags
& NE_FFLAGS_WIN32
) );
368 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
369 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
371 /* Skipping this bundle */
375 case 0: p
+= 2; break; /* unused */
376 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
377 default: p
+= 2 + *p
* 3; break; /* fixed */
380 if (!*p
) return FALSE
;
386 case 0xff: /* moveable */
387 p
+= 2 + 6 * (ordinal
- curOrdinal
);
388 *(WORD
*)(p
+ 4) = offset
;
391 p
+= 2 + 3 * (ordinal
- curOrdinal
);
392 *(WORD
*)(p
+ 1) = offset
;
399 /***********************************************************************
402 HANDLE32
NE_OpenFile( NE_MODULE
*pModule
)
406 static HANDLE32 cachedfd
= -1;
408 TRACE( module
, "(%p) cache: mod=%p fd=%d\n",
409 pModule
, pCachedModule
, cachedfd
);
410 if (pCachedModule
== pModule
) return cachedfd
;
411 CloseHandle( cachedfd
);
412 pCachedModule
= pModule
;
413 name
= NE_MODULE_NAME( pModule
);
414 if ((cachedfd
= CreateFile32A( name
, GENERIC_READ
, FILE_SHARE_READ
,
415 NULL
, OPEN_EXISTING
, 0, -1 )) == -1)
416 MSG( "Can't open file '%s' for module %04x\n", name
, pModule
->self
);
418 /* FIXME: should not be necessary */
419 cachedfd
= ConvertToGlobalHandle(cachedfd
);
420 TRACE(module
, "opened '%s' -> %d\n",
426 /***********************************************************************
429 static HMODULE16
NE_LoadExeHeader( HFILE16 hFile
, OFSTRUCT
*ofs
)
431 IMAGE_DOS_HEADER mz_header
;
432 IMAGE_OS2_HEADER ne_header
;
437 char *buffer
, *fastload
= NULL
;
438 int fastload_offset
= 0, fastload_length
= 0;
440 /* Read a block from either the file or the fast-load area. */
441 #define READ(offset,size,buffer) \
442 ((fastload && ((offset) >= fastload_offset) && \
443 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
444 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
445 (_llseek16( hFile, (offset), SEEK_SET), \
446 _hread16( hFile, (buffer), (size) ) == (size)))
448 _llseek16( hFile
, 0, SEEK_SET
);
449 if ((_hread16(hFile
,&mz_header
,sizeof(mz_header
)) != sizeof(mz_header
)) ||
450 (mz_header
.e_magic
!= IMAGE_DOS_SIGNATURE
))
451 return (HMODULE16
)11; /* invalid exe */
453 _llseek16( hFile
, mz_header
.e_lfanew
, SEEK_SET
);
454 if (_hread16( hFile
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
455 return (HMODULE16
)11; /* invalid exe */
457 if (ne_header
.ne_magic
== IMAGE_NT_SIGNATURE
) return (HMODULE16
)21; /* win32 exe */
458 if (ne_header
.ne_magic
!= IMAGE_OS2_SIGNATURE
) return (HMODULE16
)11; /* invalid exe */
460 if (ne_header
.ne_magic
== IMAGE_OS2_SIGNATURE_LX
) {
461 MSG("Sorry, this is an OS/2 linear executable (LX) file !\n");
462 return (HMODULE16
)12;
465 /* We now have a valid NE header */
467 size
= sizeof(NE_MODULE
) +
469 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
471 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
472 /* resident names table */
473 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
474 /* module ref table */
475 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
476 /* imported names table */
477 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
478 /* entry table length */
479 ne_header
.entry_tab_length
+
480 /* loaded file info */
481 sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1;
483 hModule
= GlobalAlloc16( GMEM_FIXED
| GMEM_ZEROINIT
, size
);
484 if (!hModule
) return (HMODULE16
)11; /* invalid exe */
485 FarSetOwner( hModule
, hModule
);
486 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
487 memcpy( pModule
, &ne_header
, sizeof(ne_header
) );
489 /* check *programs* for default minimal stack size */
490 if ( (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
))
491 && (pModule
->stack_size
< 0x1400) )
492 pModule
->stack_size
= 0x1400;
493 pModule
->module32
= 0;
494 pModule
->self
= hModule
;
495 pModule
->self_loading_sel
= 0;
496 pData
= (BYTE
*)(pModule
+ 1);
498 /* Clear internal Wine flags in case they are set in the EXE file */
500 pModule
->flags
&= ~(NE_FFLAGS_BUILTIN
| NE_FFLAGS_WIN32
);
502 /* Read the fast-load area */
504 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
506 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
507 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
508 TRACE(module
, "Using fast-load area offset=%x len=%d\n",
509 fastload_offset
, fastload_length
);
510 if ((fastload
= HeapAlloc( SystemHeap
, 0, fastload_length
)) != NULL
)
512 _llseek16( hFile
, fastload_offset
, SEEK_SET
);
513 if (_hread16(hFile
, fastload
, fastload_length
) != fastload_length
)
515 HeapFree( SystemHeap
, 0, fastload
);
516 WARN( module
, "Error reading fast-load area!\n");
522 /* Get the segment table */
524 pModule
->seg_table
= (int)pData
- (int)pModule
;
525 buffer
= HeapAlloc( SystemHeap
, 0, ne_header
.n_segment_tab
*
526 sizeof(struct ne_segment_table_entry_s
));
530 struct ne_segment_table_entry_s
*pSeg
;
532 if (!READ( mz_header
.e_lfanew
+ ne_header
.segment_tab_offset
,
533 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
536 HeapFree( SystemHeap
, 0, buffer
);
537 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
538 GlobalFree16( hModule
);
539 return (HMODULE16
)11; /* invalid exe */
541 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
542 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
544 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
545 pData
+= sizeof(SEGTABLEENTRY
);
547 HeapFree( SystemHeap
, 0, buffer
);
551 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
552 GlobalFree16( hModule
);
553 return (HMODULE16
)11; /* invalid exe */
556 /* Get the resource table */
558 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
560 pModule
->res_table
= (int)pData
- (int)pModule
;
561 if (!READ(mz_header
.e_lfanew
+ ne_header
.resource_tab_offset
,
562 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
563 pData
)) return (HMODULE16
)11; /* invalid exe */
564 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
565 NE_InitResourceHandler( hModule
);
567 else pModule
->res_table
= 0; /* No resource table */
569 /* Get the resident names table */
571 pModule
->name_table
= (int)pData
- (int)pModule
;
572 if (!READ( mz_header
.e_lfanew
+ ne_header
.rname_tab_offset
,
573 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
576 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
577 GlobalFree16( hModule
);
578 return (HMODULE16
)11; /* invalid exe */
580 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
582 /* Get the module references table */
584 if (ne_header
.n_mod_ref_tab
> 0)
586 pModule
->modref_table
= (int)pData
- (int)pModule
;
587 if (!READ( mz_header
.e_lfanew
+ ne_header
.moduleref_tab_offset
,
588 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
591 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
592 GlobalFree16( hModule
);
593 return (HMODULE16
)11; /* invalid exe */
595 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
597 else pModule
->modref_table
= 0; /* No module references */
599 /* Get the imported names table */
601 pModule
->import_table
= (int)pData
- (int)pModule
;
602 if (!READ( mz_header
.e_lfanew
+ ne_header
.iname_tab_offset
,
603 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
606 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
607 GlobalFree16( hModule
);
608 return (HMODULE16
)11; /* invalid exe */
610 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
612 /* Get the entry table */
614 pModule
->entry_table
= (int)pData
- (int)pModule
;
615 if (!READ( mz_header
.e_lfanew
+ ne_header
.entry_tab_offset
,
616 ne_header
.entry_tab_length
,
619 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
620 GlobalFree16( hModule
);
621 return (HMODULE16
)11; /* invalid exe */
623 pData
+= ne_header
.entry_tab_length
;
625 /* Store the filename information */
627 pModule
->fileinfo
= (int)pData
- (int)pModule
;
628 size
= sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1;
629 memcpy( pData
, ofs
, size
);
630 ((OFSTRUCT
*)pData
)->cBytes
= size
- 1;
633 /* Free the fast-load area */
636 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
638 /* Get the non-resident names table */
640 if (ne_header
.nrname_tab_length
)
642 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
643 hModule
, FALSE
, FALSE
, FALSE
);
644 if (!pModule
->nrname_handle
)
646 GlobalFree16( hModule
);
647 return (HMODULE16
)11; /* invalid exe */
649 buffer
= GlobalLock16( pModule
->nrname_handle
);
650 _llseek16( hFile
, ne_header
.nrname_tab_offset
, SEEK_SET
);
651 if (_hread16( hFile
, buffer
, ne_header
.nrname_tab_length
)
652 != ne_header
.nrname_tab_length
)
654 GlobalFree16( pModule
->nrname_handle
);
655 GlobalFree16( hModule
);
656 return (HMODULE16
)11; /* invalid exe */
659 else pModule
->nrname_handle
= 0;
661 /* Allocate a segment for the implicitly-loaded DLLs */
663 if (pModule
->modref_count
)
665 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
666 (pModule
->modref_count
+1)*sizeof(HMODULE16
),
667 hModule
, FALSE
, FALSE
, FALSE
);
668 if (!pModule
->dlls_to_init
)
670 if (pModule
->nrname_handle
) GlobalFree16( pModule
->nrname_handle
);
671 GlobalFree16( hModule
);
672 return (HMODULE16
)11; /* invalid exe */
675 else pModule
->dlls_to_init
= 0;
677 NE_RegisterModule( pModule
);
678 if (fnSNOOP16_RegisterDLL
)
679 fnSNOOP16_RegisterDLL(pModule
,ofs
->szPathName
);
684 /***********************************************************************
687 * Load all DLLs implicitly linked to a module.
689 static BOOL32
NE_LoadDLLs( NE_MODULE
*pModule
)
692 WORD
*pModRef
= (WORD
*)((char *)pModule
+ pModule
->modref_table
);
693 WORD
*pDLLs
= (WORD
*)GlobalLock16( pModule
->dlls_to_init
);
695 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
698 BYTE
*pstr
= (BYTE
*)pModule
+ pModule
->import_table
+ *pModRef
;
699 memcpy( buffer
, pstr
+ 1, *pstr
);
700 *(buffer
+ *pstr
) = 0; /* terminate it */
701 if (!strchr(buffer
,'.')) /* only append .dll if no extension yet.
702 handles a request for krnl386.exe*/
703 strcpy( buffer
+ *pstr
, ".dll" );
704 TRACE(module
, "Loading '%s'\n", buffer
);
705 if (!(*pModRef
= GetModuleHandle16( buffer
)))
707 /* If the DLL is not loaded yet, load it and store */
708 /* its handle in the list of DLLs to initialize. */
711 if ((hDLL
= NE_LoadModule( buffer
, NULL
, TRUE
, TRUE
)) == 2)
716 /* Try with prepending the path of the current module */
717 GetModuleFileName16( pModule
->self
, buffer
, sizeof(buffer
) );
718 if (!(p
= strrchr( buffer
, '\\' ))) p
= buffer
;
719 memcpy( p
+ 1, pstr
+ 1, *pstr
);
720 strcpy( p
+ 1 + *pstr
, ".dll" );
721 hDLL
= NE_LoadModule( buffer
, NULL
, TRUE
, TRUE
);
725 /* FIXME: cleanup what was done */
727 MSG( "Could not load '%s' required by '%.*s', error=%d\n",
728 buffer
, *((BYTE
*)pModule
+ pModule
->name_table
),
729 (char *)pModule
+ pModule
->name_table
+ 1, hDLL
);
732 *pModRef
= GetExePtr( hDLL
);
735 else /* Increment the reference count of the DLL */
737 NE_MODULE
*pOldDLL
= NE_GetPtr( *pModRef
);
738 if (pOldDLL
) pOldDLL
->count
++;
745 /**********************************************************************
748 * Implementation of LoadModule16().
750 HINSTANCE16
NE_LoadModule( LPCSTR name
, HINSTANCE16
*hPrevInstance
,
751 BOOL32 implicit
, BOOL32 lib_only
)
754 HINSTANCE16 hInstance
;
759 /* Check if the module is already loaded */
761 if ((hModule
= GetModuleHandle16( name
)) != 0)
764 pModule
= NE_GetPtr( hModule
);
765 if ( pModule
->module32
) return (HINSTANCE16
)21;
767 hInstance
= NE_CreateInstance( pModule
, &prev
, lib_only
);
768 if (hInstance
!= prev
) /* not a library */
769 NE_LoadSegment( pModule
, pModule
->dgroup
);
771 if (hPrevInstance
) *hPrevInstance
= prev
;
774 if (hPrevInstance
) *hPrevInstance
= 0;
776 /* Try to load the built-in first if not disabled */
778 if ((hModule
= fnBUILTIN_LoadModule( name
, FALSE
))) return hModule
;
780 if ((hFile
= OpenFile16( name
, &ofs
, OF_READ
)) == HFILE_ERROR16
)
782 /* Now try the built-in even if disabled */
783 if ((hModule
= fnBUILTIN_LoadModule( name
, TRUE
)))
785 MSG( "Could not load Windows DLL '%s', using built-in module.\n",
789 return 2; /* File not found */
792 /* Create the module structure */
794 hModule
= NE_LoadExeHeader( hFile
, &ofs
);
796 if (hModule
< 32) return hModule
;
797 pModule
= NE_GetPtr( hModule
);
799 /* Allocate the segments for this module */
801 if (!NE_CreateSegments( pModule
) ||
802 !(hInstance
= NE_CreateInstance( pModule
, NULL
, lib_only
)))
804 GlobalFreeAll( hModule
);
805 return 8; /* Insufficient memory */
808 /* Load the referenced DLLs */
810 if (!NE_LoadDLLs( pModule
))
811 return 2; /* File not found (FIXME: free everything) */
813 /* Load the segments */
815 NE_LoadAllSegments( pModule
);
817 /* Fixup the functions prologs */
819 NE_FixupPrologs( pModule
);
821 /* Make sure the usage count is 1 on the first loading of */
822 /* the module, even if it contains circular DLL references */
826 /* Call initialization rountines for all loaded DLLs. Note that
827 * when we load implicitly linked DLLs this will be done by InitTask().
830 if (!implicit
&& (pModule
->flags
& NE_FFLAGS_LIBMODULE
))
831 NE_InitializeDLLs( hModule
);
837 /***********************************************************************
838 * LoadLibrary (KERNEL.95)
840 HINSTANCE16 WINAPI
LoadLibrary16( LPCSTR libname
)
846 TRACE(module
, "(%08x) %s\n", (int)libname
, libname
);
848 /* Check for an extension */
850 if ((p
= strrchr( libname
, '.')) && !strchr( p
, '/' ) && !strchr( p
, '\\'))
852 /* An extension is present -> use the name as is */
853 return NE_LoadModule( libname
, NULL
, FALSE
, TRUE
);
856 /* Now append .dll before loading */
858 if (!(new_name
= HeapAlloc( GetProcessHeap(), 0, strlen(libname
) + 4 )))
860 strcpy( new_name
, libname
);
861 strcat( new_name
, ".dll" );
862 handle
= NE_LoadModule( new_name
, NULL
, FALSE
, TRUE
);
863 HeapFree( GetProcessHeap(), 0, new_name
);
868 /**********************************************************************
871 * Call a DLL's WEP, allowing it to shut down.
872 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
874 static BOOL16
MODULE_CallWEP( HMODULE16 hModule
)
876 FARPROC16 WEP
= (FARPROC16
)0;
877 WORD ordinal
= NE_GetOrdinal( hModule
, "WEP" );
879 if (ordinal
) WEP
= NE_GetEntryPoint( hModule
, ordinal
);
882 WARN(module
, "module %04x doesn't have a WEP\n", hModule
);
885 return Callbacks
->CallWindowsExitProc( WEP
, WEP_FREE_DLL
);
889 /**********************************************************************
892 * Implementation of FreeModule16().
894 static BOOL16
NE_FreeModule( HMODULE16 hModule
, BOOL32 call_wep
)
896 HMODULE16
*hPrevModule
;
901 if (!(pModule
= NE_GetPtr( hModule
))) return FALSE
;
902 hModule
= pModule
->self
;
904 TRACE( module
, "%04x count %d\n", hModule
, pModule
->count
);
906 if (((INT16
)(--pModule
->count
)) > 0 ) return TRUE
;
907 else pModule
->count
= 0;
909 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
910 return FALSE
; /* Can't free built-in module */
914 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
)
916 TDB
*pTask
= (TDB
*)GlobalLock16( GetCurrentTask() );
917 MODULE_CallWEP( hModule
);
919 /* Free the objects owned by the DLL module */
921 if (pTask
&& pTask
->userhandler
)
922 pTask
->userhandler( hModule
, USIG_DLL_UNLOAD
, 0,
923 pTask
->hInstance
, pTask
->hQueue
);
926 call_wep
= FALSE
; /* We are freeing a task -> no more WEPs */
930 /* Clear magic number just in case */
932 pModule
->magic
= pModule
->self
= 0;
934 /* Remove it from the linked list */
936 hPrevModule
= &hFirstModule
;
937 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
939 hPrevModule
= &(NE_GetPtr( *hPrevModule
))->next
;
941 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
943 /* Free the referenced modules */
945 pModRef
= (HMODULE16
*)NE_MODULE_TABLE( pModule
);
946 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
948 NE_FreeModule( *pModRef
, call_wep
);
951 /* Free the module storage */
953 GlobalFreeAll( hModule
);
955 /* Remove module from cache */
957 if (pCachedModule
== pModule
) pCachedModule
= NULL
;
962 /**********************************************************************
963 * FreeModule16 (KERNEL.46)
965 BOOL16 WINAPI
FreeModule16( HMODULE16 hModule
)
967 return NE_FreeModule( hModule
, TRUE
);
971 /***********************************************************************
972 * FreeLibrary16 (KERNEL.96)
974 void WINAPI
FreeLibrary16( HINSTANCE16 handle
)
976 TRACE(module
,"%04x\n", handle
);
977 FreeModule16( handle
);
981 /**********************************************************************
982 * GetModuleName (KERNEL.27)
984 BOOL16 WINAPI
GetModuleName( HINSTANCE16 hinst
, LPSTR buf
, INT16 count
)
989 if (!(pModule
= NE_GetPtr( hinst
))) return FALSE
;
990 p
= (BYTE
*)pModule
+ pModule
->name_table
;
991 if (count
> *p
) count
= *p
+ 1;
994 memcpy( buf
, p
+ 1, count
- 1 );
1001 /**********************************************************************
1002 * GetModuleUsage (KERNEL.48)
1004 INT16 WINAPI
GetModuleUsage( HINSTANCE16 hModule
)
1006 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
1007 return pModule
? pModule
->count
: 0;
1011 /**********************************************************************
1012 * GetExpWinVer (KERNEL.167)
1014 WORD WINAPI
GetExpWinVer( HMODULE16 hModule
)
1016 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
1017 return pModule
? pModule
->expected_version
: 0;
1021 /**********************************************************************
1022 * GetModuleFileName16 (KERNEL.49)
1024 INT16 WINAPI
GetModuleFileName16( HINSTANCE16 hModule
, LPSTR lpFileName
,
1029 if (!hModule
) hModule
= GetCurrentTask();
1030 if (!(pModule
= NE_GetPtr( hModule
))) return 0;
1031 lstrcpyn32A( lpFileName
, NE_MODULE_NAME(pModule
), nSize
);
1032 TRACE(module
, "%s\n", lpFileName
);
1033 return strlen(lpFileName
);
1037 /**********************************************************************
1038 * GetModuleHandle16 (KERNEL.47)
1040 * Find a module from a path name.
1044 * the win16 module handle if found
1046 * HIWORD (undocumented, see "Undocumented Windows", chapter 5):
1047 * Always hFirstModule
1049 DWORD WINAPI
WIN16_GetModuleHandle( SEGPTR name
)
1051 if (HIWORD(name
) == 0)
1052 return MAKELONG(GetExePtr( (HINSTANCE16
)name
), hFirstModule
);
1053 return MAKELONG(GetModuleHandle16( PTR_SEG_TO_LIN(name
)), hFirstModule
);
1056 HMODULE16 WINAPI
GetModuleHandle16( LPCSTR name
)
1058 HMODULE16 hModule
= hFirstModule
;
1059 LPCSTR filename
, dotptr
, modulepath
, modulename
;
1060 BYTE len
, *name_table
;
1062 if (!(filename
= strrchr( name
, '\\' ))) filename
= name
;
1064 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
1065 len
= (BYTE
)(dotptr
- filename
);
1066 else len
= strlen( filename
);
1070 NE_MODULE
*pModule
= NE_GetPtr( hModule
);
1071 if (!pModule
) break;
1072 modulepath
= NE_MODULE_NAME(pModule
);
1073 if (!(modulename
= strrchr( modulepath
, '\\' )))
1074 modulename
= modulepath
;
1076 if (!lstrcmpi32A( modulename
, filename
)) return hModule
;
1078 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
1079 if ((*name_table
== len
) && !lstrncmpi32A(filename
, name_table
+1, len
))
1081 hModule
= pModule
->next
;
1087 /**********************************************************************
1088 * ModuleFirst (TOOLHELP.59)
1090 BOOL16 WINAPI
ModuleFirst( MODULEENTRY
*lpme
)
1092 lpme
->wNext
= hFirstModule
;
1093 return ModuleNext( lpme
);
1097 /**********************************************************************
1098 * ModuleNext (TOOLHELP.60)
1100 BOOL16 WINAPI
ModuleNext( MODULEENTRY
*lpme
)
1105 if (!lpme
->wNext
) return FALSE
;
1106 if (!(pModule
= NE_GetPtr( lpme
->wNext
))) return FALSE
;
1107 name
= (char *)pModule
+ pModule
->name_table
;
1108 memcpy( lpme
->szModule
, name
+ 1, min(*name
, MAX_MODULE_NAME
) );
1109 lpme
->szModule
[min(*name
, MAX_MODULE_NAME
)] = '\0';
1110 lpme
->hModule
= lpme
->wNext
;
1111 lpme
->wcUsage
= pModule
->count
;
1112 lstrcpyn32A( lpme
->szExePath
, NE_MODULE_NAME(pModule
), sizeof(lpme
->szExePath
) );
1113 lpme
->wNext
= pModule
->next
;
1118 /**********************************************************************
1119 * ModuleFindName (TOOLHELP.61)
1121 BOOL16 WINAPI
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1123 lpme
->wNext
= GetModuleHandle16( name
);
1124 return ModuleNext( lpme
);
1128 /**********************************************************************
1129 * ModuleFindHandle (TOOLHELP.62)
1131 BOOL16 WINAPI
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE16 hModule
)
1133 hModule
= GetExePtr( hModule
);
1134 lpme
->wNext
= hModule
;
1135 return ModuleNext( lpme
);
1138 /***************************************************************************
1139 * MapHModuleLS (KERNEL32.520)
1141 HMODULE16 WINAPI
MapHModuleLS(HMODULE32 hmod
) {
1145 return ((TDB
*)GlobalLock16(GetCurrentTask()))->hInstance
;
1147 return hmod
; /* we already have a 16 bit module handle */
1148 pModule
= (NE_MODULE
*)GlobalLock16(hFirstModule
);
1150 if (pModule
->module32
== hmod
)
1151 return pModule
->self
;
1152 pModule
= (NE_MODULE
*)GlobalLock16(pModule
->next
);
1157 /***************************************************************************
1158 * MapHModuleSL (KERNEL32.521)
1160 HMODULE32 WINAPI
MapHModuleSL(HMODULE16 hmod
) {
1164 TDB
*pTask
= (TDB
*)GlobalLock16(GetCurrentTask());
1166 hmod
= pTask
->hInstance
;
1168 pModule
= (NE_MODULE
*)GlobalLock16(hmod
);
1169 if ( (pModule
->magic
!=IMAGE_OS2_SIGNATURE
) ||
1170 !(pModule
->flags
& NE_FFLAGS_WIN32
)
1173 return pModule
->module32
;
1176 /***************************************************************************
1177 * MapHInstLS (KERNEL32.516)
1179 REGS_ENTRYPOINT(MapHInstLS
) {
1180 EAX_reg(context
) = MapHModuleLS(EAX_reg(context
));
1183 /***************************************************************************
1184 * MapHInstSL (KERNEL32.518)
1186 REGS_ENTRYPOINT(MapHInstSL
) {
1187 EAX_reg(context
) = MapHModuleSL(EAX_reg(context
));
1190 /***************************************************************************
1191 * MapHInstLS_PN (KERNEL32.517)
1193 REGS_ENTRYPOINT(MapHInstLS_PN
) {
1194 if (EAX_reg(context
))
1195 EAX_reg(context
) = MapHModuleLS(EAX_reg(context
));
1198 /***************************************************************************
1199 * MapHInstSL_PN (KERNEL32.519)
1201 REGS_ENTRYPOINT(MapHInstSL_PN
) {
1202 if (EAX_reg(context
))
1203 EAX_reg(context
) = MapHModuleSL(EAX_reg(context
));
1206 /***************************************************************************
1207 * WIN16_MapHInstLS (KERNEL.472)
1209 VOID WINAPI
WIN16_MapHInstLS( CONTEXT
*context
) {
1210 EAX_reg(context
) = MapHModuleLS(EAX_reg(context
));
1213 /***************************************************************************
1214 * WIN16_MapHInstSL (KERNEL.473)
1216 VOID WINAPI
WIN16_MapHInstSL( CONTEXT
*context
) {
1217 EAX_reg(context
) = MapHModuleSL(EAX_reg(context
));