4 * Copyright 1995 Alexandre Julliard
12 #include <sys/types.h>
24 #include "selectors.h"
25 #include "stackframe.h"
31 extern HINSTANCE16
PE_LoadModule( HFILE32 hf
, OFSTRUCT
*ofs
, LOADPARAMS
* params
);
33 extern BOOL32 THREAD_InitDone
;
35 static HMODULE16 hFirstModule
= 0;
36 static HMODULE16 hCachedModule
= 0; /* Module cached by MODULE_OpenFile */
38 static HMODULE32
MODULE_LoadModule(LPCSTR name
,BOOL32 force
) { return 0; }
39 HMODULE32 (*fnBUILTIN_LoadModule
)(LPCSTR name
,BOOL32 force
) = MODULE_LoadModule
;
42 /***********************************************************************
45 NE_MODULE
*MODULE_GetPtr( HMODULE32 hModule
)
47 HMODULE16 hnd
=MODULE_HANDLEtoHMODULE16(hModule
);
51 return (NE_MODULE
*)GlobalLock16(hnd
);
54 /***********************************************************************
55 * MODULE_HANDLEtoHMODULE16
58 MODULE_HANDLEtoHMODULE16(HANDLE32 handle
) {
63 /* this is a HMODULE32 */
65 /* walk the list looking for the correct startaddress */
66 pModule
= (NE_MODULE
*)GlobalLock16( hFirstModule
);
69 if (pModule
->module32
== handle
) return pModule
->self
;
70 pModule
= (NE_MODULE
*)GlobalLock16(pModule
->next
);
74 return GetExePtr(handle
);
77 /***********************************************************************
78 * MODULE_HANDLEtoHMODULE32
79 * return HMODULE32, if possible, HMODULE16 otherwise
82 MODULE_HANDLEtoHMODULE32(HANDLE32 handle
) {
86 return (HMODULE32
)handle
;
88 handle
= GetExePtr(handle
);
91 pModule
= (NE_MODULE
*)GlobalLock16( handle
);
95 if (pModule
->module32
) return pModule
->module32
;
100 /***********************************************************************
103 void MODULE_DumpModule( HMODULE32 hModule
)
111 if (!(pModule
= MODULE_GetPtr( hModule
)))
113 fprintf( stderr
, "**** %04x is not a module handle\n", hModule
);
117 /* Dump the module info */
119 printf( "Module %04x:\n", hModule
);
120 printf( "count=%d flags=%04x heap=%d stack=%d\n",
121 pModule
->count
, pModule
->flags
,
122 pModule
->heap_size
, pModule
->stack_size
);
123 printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
124 pModule
->cs
, pModule
->ip
, pModule
->ss
, pModule
->sp
, pModule
->dgroup
,
125 pModule
->seg_count
, pModule
->modref_count
);
126 printf( "os_flags=%d swap_area=%d version=%04x\n",
127 pModule
->os_flags
, pModule
->min_swap_area
,
128 pModule
->expected_version
);
129 if (pModule
->flags
& NE_FFLAGS_WIN32
)
130 printf( "PE module=%08x\n", pModule
->module32
);
132 /* Dump the file info */
134 printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule
) );
136 /* Dump the segment table */
138 printf( "\nSegment table:\n" );
139 pSeg
= NE_SEG_TABLE( pModule
);
140 for (i
= 0; i
< pModule
->seg_count
; i
++, pSeg
++)
141 printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
142 i
+ 1, pSeg
->filepos
, pSeg
->size
, pSeg
->flags
,
143 pSeg
->minsize
, pSeg
->selector
);
145 /* Dump the resource table */
147 printf( "\nResource table:\n" );
148 if (pModule
->res_table
)
150 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->res_table
);
151 printf( "Alignment: %d\n", *pword
++ );
154 struct resource_typeinfo_s
*ptr
= (struct resource_typeinfo_s
*)pword
;
155 struct resource_nameinfo_s
*pname
= (struct resource_nameinfo_s
*)(ptr
+ 1);
156 printf( "id=%04x count=%d\n", ptr
->type_id
, ptr
->count
);
157 for (i
= 0; i
< ptr
->count
; i
++, pname
++)
158 printf( "offset=%d len=%d id=%04x\n",
159 pname
->offset
, pname
->length
, pname
->id
);
160 pword
= (WORD
*)pname
;
163 else printf( "None\n" );
165 /* Dump the resident name table */
167 printf( "\nResident-name table:\n" );
168 pstr
= (char *)pModule
+ pModule
->name_table
;
171 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
172 *(WORD
*)(pstr
+ *pstr
+ 1) );
173 pstr
+= *pstr
+ 1 + sizeof(WORD
);
176 /* Dump the module reference table */
178 printf( "\nModule ref table:\n" );
179 if (pModule
->modref_table
)
181 pword
= (WORD
*)((BYTE
*)pModule
+ pModule
->modref_table
);
182 for (i
= 0; i
< pModule
->modref_count
; i
++, pword
++)
184 printf( "%d: %04x -> '%s'\n", i
, *pword
,
185 MODULE_GetModuleName(*pword
));
188 else printf( "None\n" );
190 /* Dump the entry table */
192 printf( "\nEntry table:\n" );
193 pstr
= (char *)pModule
+ pModule
->entry_table
;
197 printf( "Bundle %d-%d: %02x\n", ordinal
, ordinal
+ *pstr
- 1, pstr
[1]);
203 else if ((BYTE
)pstr
[1] == 0xff) /* moveable */
205 struct entry_tab_movable_s
*pe
= (struct entry_tab_movable_s
*)(pstr
+2);
206 for (i
= 0; i
< *pstr
; i
++, pe
++)
207 printf( "%d: %02x:%04x (moveable)\n",
208 ordinal
++, pe
->seg_number
, pe
->offset
);
213 struct entry_tab_fixed_s
*pe
= (struct entry_tab_fixed_s
*)(pstr
+2);
214 for (i
= 0; i
< *pstr
; i
++, pe
++)
215 printf( "%d: %04x (fixed)\n",
216 ordinal
++, pe
->offset
[0] + (pe
->offset
[1] << 8) );
221 /* Dump the non-resident names table */
223 printf( "\nNon-resident names table:\n" );
224 if (pModule
->nrname_handle
)
226 pstr
= (char *)GlobalLock16( pModule
->nrname_handle
);
229 printf( "%*.*s: %d\n", *pstr
, *pstr
, pstr
+ 1,
230 *(WORD
*)(pstr
+ *pstr
+ 1) );
231 pstr
+= *pstr
+ 1 + sizeof(WORD
);
238 /***********************************************************************
241 * Walk the module list and print the modules.
243 void MODULE_WalkModules(void)
245 HMODULE16 hModule
= hFirstModule
;
246 fprintf( stderr
, "Module Flags Name\n" );
249 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
252 fprintf( stderr
, "**** Bad module %04x in list\n", hModule
);
255 fprintf( stderr
, " %04x %04x %.*s\n", hModule
, pModule
->flags
,
256 *((char *)pModule
+ pModule
->name_table
),
257 (char *)pModule
+ pModule
->name_table
+ 1 );
258 hModule
= pModule
->next
;
263 /***********************************************************************
266 int MODULE_OpenFile( HMODULE32 hModule
)
269 DOS_FULL_NAME full_name
;
272 static int cachedfd
= -1;
274 hModule
= MODULE_HANDLEtoHMODULE16(hModule
);
275 TRACE(module
, "(%04x) cache: mod=%04x fd=%d\n",
276 hModule
, hCachedModule
, cachedfd
);
277 if (!(pModule
= MODULE_GetPtr( hModule
))) return -1;
278 if (hCachedModule
== hModule
) return cachedfd
;
280 hCachedModule
= hModule
;
281 name
= NE_MODULE_NAME( pModule
);
282 if (!DOSFS_GetFullName( name
, TRUE
, &full_name
) ||
283 (cachedfd
= open( full_name
.long_name
, O_RDONLY
)) == -1)
284 fprintf( stderr
, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
286 TRACE(module
, "opened '%s' -> %d\n",
292 /***********************************************************************
295 * This function translates NE segment flags to GlobalAlloc flags
297 static WORD
MODULE_Ne2MemFlags(WORD flags
)
301 if (flags
& NE_SEGFLAGS_DISCARDABLE
)
302 memflags
|= GMEM_DISCARDABLE
;
303 if (flags
& NE_SEGFLAGS_MOVEABLE
||
304 ( ! (flags
& NE_SEGFLAGS_DATA
) &&
305 ! (flags
& NE_SEGFLAGS_LOADED
) &&
306 ! (flags
& NE_SEGFLAGS_ALLOCATED
)
309 memflags
|= GMEM_MOVEABLE
;
310 memflags
|= GMEM_ZEROINIT
;
312 memflags
= GMEM_ZEROINIT
| GMEM_FIXED
;
317 /***********************************************************************
318 * MODULE_AllocateSegment (WPROCS.26)
321 DWORD WINAPI
MODULE_AllocateSegment(WORD wFlags
, WORD wSize
, WORD wElem
)
323 WORD size
= wSize
<< wElem
;
324 HANDLE16 hMem
= GlobalAlloc16( MODULE_Ne2MemFlags(wFlags
), size
);
325 return MAKELONG( hMem
, GlobalHandleToSel(hMem
) );
328 /***********************************************************************
329 * MODULE_CreateSegments
331 static BOOL32
MODULE_CreateSegments( HMODULE32 hModule
)
333 SEGTABLEENTRY
*pSegment
;
337 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
338 pSegment
= NE_SEG_TABLE( pModule
);
339 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
341 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
342 if (i
== pModule
->ss
) minsize
+= pModule
->stack_size
;
343 /* The DGROUP is allocated by MODULE_CreateInstance */
344 if (i
== pModule
->dgroup
) continue;
345 pSegment
->selector
= GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment
->flags
),
347 !(pSegment
->flags
& NE_SEGFLAGS_DATA
),
349 FALSE
/*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
350 if (!pSegment
->selector
) return FALSE
;
353 pModule
->dgroup_entry
= pModule
->dgroup
? pModule
->seg_table
+
354 (pModule
->dgroup
- 1) * sizeof(SEGTABLEENTRY
) : 0;
359 /***********************************************************************
362 HINSTANCE16
MODULE_GetInstance( HMODULE32 hModule
)
364 SEGTABLEENTRY
*pSegment
;
367 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
368 if (pModule
->dgroup
== 0) return hModule
;
370 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
372 return pSegment
->selector
;
376 /***********************************************************************
377 * MODULE_CreateInstance
379 HINSTANCE16
MODULE_CreateInstance( HMODULE16 hModule
, LOADPARAMS
*params
)
381 SEGTABLEENTRY
*pSegment
;
384 HINSTANCE16 hNewInstance
, hPrevInstance
;
386 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
387 if (pModule
->dgroup
== 0) return hModule
;
389 pSegment
= NE_SEG_TABLE( pModule
) + pModule
->dgroup
- 1;
390 hPrevInstance
= pSegment
->selector
;
392 /* if it's a library, create a new instance only the first time */
395 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
) return hPrevInstance
;
396 if (params
== (LOADPARAMS
*)-1) return hPrevInstance
;
399 minsize
= pSegment
->minsize
? pSegment
->minsize
: 0x10000;
400 if (pModule
->ss
== pModule
->dgroup
) minsize
+= pModule
->stack_size
;
401 minsize
+= pModule
->heap_size
;
402 hNewInstance
= GLOBAL_Alloc( GMEM_ZEROINIT
| GMEM_FIXED
,
403 minsize
, hModule
, FALSE
, FALSE
, FALSE
);
404 if (!hNewInstance
) return 0;
405 pSegment
->selector
= hNewInstance
;
410 /***********************************************************************
411 * MODULE_CreateDummyModule
413 * Create a dummy NE module for Win32 or Winelib.
415 HMODULE32
MODULE_CreateDummyModule( const OFSTRUCT
*ofs
)
419 SEGTABLEENTRY
*pSegment
;
422 const char* basename
;
424 INT32 of_size
= sizeof(OFSTRUCT
) - sizeof(ofs
->szPathName
)
425 + strlen(ofs
->szPathName
) + 1;
426 INT32 size
= sizeof(NE_MODULE
) +
427 /* loaded file info */
429 /* segment table: DS,CS */
430 2 * sizeof(SEGTABLEENTRY
) +
433 /* several empty tables */
436 hModule
= GlobalAlloc16( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
437 if (!hModule
) return (HMODULE32
)11; /* invalid exe */
439 FarSetOwner( hModule
, hModule
);
440 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
442 /* Set all used entries */
443 pModule
->magic
= IMAGE_OS2_SIGNATURE
;
450 pModule
->heap_size
= 0xe000;
451 pModule
->stack_size
= 0x1000;
452 pModule
->seg_count
= 2;
453 pModule
->modref_count
= 0;
454 pModule
->nrname_size
= 0;
455 pModule
->fileinfo
= sizeof(NE_MODULE
);
456 pModule
->os_flags
= NE_OSFLAGS_WINDOWS
;
457 pModule
->expected_version
= 0x030a;
458 pModule
->self
= hModule
;
460 /* Set loaded file information */
461 memcpy( pModule
+ 1, ofs
, of_size
);
462 ((OFSTRUCT
*)(pModule
+1))->cBytes
= of_size
- 1;
464 pSegment
= (SEGTABLEENTRY
*)((char*)(pModule
+ 1) + of_size
);
465 pModule
->seg_table
= pModule
->dgroup_entry
= (int)pSegment
- (int)pModule
;
468 pSegment
->flags
= NE_SEGFLAGS_DATA
;
469 pSegment
->minsize
= 0x1000;
476 pStr
= (char *)pSegment
;
477 pModule
->name_table
= (int)pStr
- (int)pModule
;
478 basename
= strrchr(ofs
->szPathName
,'\\');
479 if (!basename
) basename
= ofs
->szPathName
;
481 len
= strlen(basename
);
482 if ((s
= strchr(basename
,'.'))) len
= s
- basename
;
483 if (len
> 8) len
= 8;
485 strncpy( pStr
+1, basename
, len
);
486 if (len
< 8) pStr
[len
+1] = 0;
489 /* All tables zero terminated */
490 pModule
->res_table
= pModule
->import_table
= pModule
->entry_table
=
491 (int)pStr
- (int)pModule
;
493 MODULE_RegisterModule( pModule
);
498 /***********************************************************************
499 * MODULE_LoadExeHeader
501 static HMODULE32
MODULE_LoadExeHeader( HFILE32 hFile
, OFSTRUCT
*ofs
)
503 IMAGE_DOS_HEADER mz_header
;
504 IMAGE_OS2_HEADER ne_header
;
509 char *buffer
, *fastload
= NULL
;
510 int fastload_offset
= 0, fastload_length
= 0;
512 /* Read a block from either the file or the fast-load area. */
513 #define READ(offset,size,buffer) \
514 ((fastload && ((offset) >= fastload_offset) && \
515 ((offset)+(size) <= fastload_offset+fastload_length)) ? \
516 (memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
517 (_llseek32( hFile, (offset), SEEK_SET), \
518 _lread32( hFile, (buffer), (size) ) == (size)))
520 _llseek32( hFile
, 0, SEEK_SET
);
521 if ((_lread32(hFile
,&mz_header
,sizeof(mz_header
)) != sizeof(mz_header
)) ||
522 (mz_header
.e_magic
!= IMAGE_DOS_SIGNATURE
))
523 return (HMODULE32
)11; /* invalid exe */
525 _llseek32( hFile
, mz_header
.e_lfanew
, SEEK_SET
);
526 if (_lread32( hFile
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
527 return (HMODULE32
)11; /* invalid exe */
529 if (ne_header
.ne_magic
== IMAGE_NT_SIGNATURE
) return (HMODULE32
)21; /* win32 exe */
530 if (ne_header
.ne_magic
!= IMAGE_OS2_SIGNATURE
) return (HMODULE32
)11; /* invalid exe */
532 if (ne_header
.ne_magic
== IMAGE_OS2_SIGNATURE_LX
) {
533 fprintf(stderr
, "Sorry, this is an OS/2 linear executable (LX) file !\n");
534 return (HMODULE32
)12;
536 /* We now have a valid NE header */
538 size
= sizeof(NE_MODULE
) +
539 /* loaded file info */
540 sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1+
542 ne_header
.n_segment_tab
* sizeof(SEGTABLEENTRY
) +
544 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
+
545 /* resident names table */
546 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
+
547 /* module ref table */
548 ne_header
.n_mod_ref_tab
* sizeof(WORD
) +
549 /* imported names table */
550 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
+
551 /* entry table length */
552 ne_header
.entry_tab_length
;
554 hModule
= GlobalAlloc16( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
555 if (!hModule
) return (HMODULE32
)11; /* invalid exe */
556 FarSetOwner( hModule
, hModule
);
557 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
558 memcpy( pModule
, &ne_header
, sizeof(ne_header
) );
560 pModule
->module32
= 0;
561 pModule
->self
= hModule
;
562 pModule
->self_loading_sel
= 0;
563 pData
= (BYTE
*)(pModule
+ 1);
565 /* Clear internal Wine flags in case they are set in the EXE file */
567 pModule
->flags
&= ~(NE_FFLAGS_BUILTIN
|NE_FFLAGS_WIN32
|NE_FFLAGS_IMPLICIT
);
569 /* Read the fast-load area */
571 if (ne_header
.additional_flags
& NE_AFLAGS_FASTLOAD
)
573 fastload_offset
=ne_header
.fastload_offset
<<ne_header
.align_shift_count
;
574 fastload_length
=ne_header
.fastload_length
<<ne_header
.align_shift_count
;
575 TRACE(module
, "Using fast-load area offset=%x len=%d\n",
576 fastload_offset
, fastload_length
);
577 if ((fastload
= HeapAlloc( SystemHeap
, 0, fastload_length
)) != NULL
)
579 _llseek32( hFile
, fastload_offset
, SEEK_SET
);
580 if (_lread32(hFile
, fastload
, fastload_length
) != fastload_length
)
582 HeapFree( SystemHeap
, 0, fastload
);
583 fprintf(stderr
, "Error reading fast-load area !\n");
589 /* Store the filename information */
591 pModule
->fileinfo
= (int)pData
- (int)pModule
;
592 size
= sizeof(OFSTRUCT
)-sizeof(ofs
->szPathName
)+strlen(ofs
->szPathName
)+1;
593 memcpy( pData
, ofs
, size
);
594 ((OFSTRUCT
*)pData
)->cBytes
= size
- 1;
597 /* Get the segment table */
599 pModule
->seg_table
= (int)pData
- (int)pModule
;
600 buffer
= HeapAlloc( SystemHeap
, 0, ne_header
.n_segment_tab
*
601 sizeof(struct ne_segment_table_entry_s
));
605 struct ne_segment_table_entry_s
*pSeg
;
607 if (!READ( mz_header
.e_lfanew
+ ne_header
.segment_tab_offset
,
608 ne_header
.n_segment_tab
* sizeof(struct ne_segment_table_entry_s
),
611 HeapFree( SystemHeap
, 0, buffer
);
612 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
613 GlobalFree16( hModule
);
614 return (HMODULE32
)11; /* invalid exe */
616 pSeg
= (struct ne_segment_table_entry_s
*)buffer
;
617 for (i
= ne_header
.n_segment_tab
; i
> 0; i
--, pSeg
++)
619 memcpy( pData
, pSeg
, sizeof(*pSeg
) );
620 pData
+= sizeof(SEGTABLEENTRY
);
622 HeapFree( SystemHeap
, 0, buffer
);
626 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
627 GlobalFree16( hModule
);
628 return (HMODULE32
)11; /* invalid exe */
631 /* Get the resource table */
633 if (ne_header
.resource_tab_offset
< ne_header
.rname_tab_offset
)
635 pModule
->res_table
= (int)pData
- (int)pModule
;
636 if (!READ(mz_header
.e_lfanew
+ ne_header
.resource_tab_offset
,
637 ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
,
638 pData
)) return (HMODULE32
)11; /* invalid exe */
639 pData
+= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
640 NE_InitResourceHandler( hModule
);
642 else pModule
->res_table
= 0; /* No resource table */
644 /* Get the resident names table */
646 pModule
->name_table
= (int)pData
- (int)pModule
;
647 if (!READ( mz_header
.e_lfanew
+ ne_header
.rname_tab_offset
,
648 ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
,
651 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
652 GlobalFree16( hModule
);
653 return (HMODULE32
)11; /* invalid exe */
655 pData
+= ne_header
.moduleref_tab_offset
- ne_header
.rname_tab_offset
;
657 /* Get the module references table */
659 if (ne_header
.n_mod_ref_tab
> 0)
661 pModule
->modref_table
= (int)pData
- (int)pModule
;
662 if (!READ( mz_header
.e_lfanew
+ ne_header
.moduleref_tab_offset
,
663 ne_header
.n_mod_ref_tab
* sizeof(WORD
),
666 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
667 GlobalFree16( hModule
);
668 return (HMODULE32
)11; /* invalid exe */
670 pData
+= ne_header
.n_mod_ref_tab
* sizeof(WORD
);
672 else pModule
->modref_table
= 0; /* No module references */
674 /* Get the imported names table */
676 pModule
->import_table
= (int)pData
- (int)pModule
;
677 if (!READ( mz_header
.e_lfanew
+ ne_header
.iname_tab_offset
,
678 ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
,
681 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
682 GlobalFree16( hModule
);
683 return (HMODULE32
)11; /* invalid exe */
685 pData
+= ne_header
.entry_tab_offset
- ne_header
.iname_tab_offset
;
687 /* Get the entry table */
689 pModule
->entry_table
= (int)pData
- (int)pModule
;
690 if (!READ( mz_header
.e_lfanew
+ ne_header
.entry_tab_offset
,
691 ne_header
.entry_tab_length
,
694 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
695 GlobalFree16( hModule
);
696 return (HMODULE32
)11; /* invalid exe */
698 pData
+= ne_header
.entry_tab_length
;
700 /* Free the fast-load area */
703 if (fastload
) HeapFree( SystemHeap
, 0, fastload
);
705 /* Get the non-resident names table */
707 if (ne_header
.nrname_tab_length
)
709 pModule
->nrname_handle
= GLOBAL_Alloc( 0, ne_header
.nrname_tab_length
,
710 hModule
, FALSE
, FALSE
, FALSE
);
711 if (!pModule
->nrname_handle
)
713 GlobalFree16( hModule
);
714 return (HMODULE32
)11; /* invalid exe */
716 buffer
= GlobalLock16( pModule
->nrname_handle
);
717 _llseek32( hFile
, ne_header
.nrname_tab_offset
, SEEK_SET
);
718 if (_lread32( hFile
, buffer
, ne_header
.nrname_tab_length
)
719 != ne_header
.nrname_tab_length
)
721 GlobalFree16( pModule
->nrname_handle
);
722 GlobalFree16( hModule
);
723 return (HMODULE32
)11; /* invalid exe */
726 else pModule
->nrname_handle
= 0;
728 /* Allocate a segment for the implicitly-loaded DLLs */
730 if (pModule
->modref_count
)
732 pModule
->dlls_to_init
= GLOBAL_Alloc(GMEM_ZEROINIT
,
733 (pModule
->modref_count
+1)*sizeof(HMODULE32
),
734 hModule
, FALSE
, FALSE
, FALSE
);
735 if (!pModule
->dlls_to_init
)
737 if (pModule
->nrname_handle
) GlobalFree16( pModule
->nrname_handle
);
738 GlobalFree16( hModule
);
739 return (HMODULE32
)11; /* invalid exe */
742 else pModule
->dlls_to_init
= 0;
744 MODULE_RegisterModule( pModule
);
749 /***********************************************************************
752 * Lookup the ordinal for a given name.
754 WORD
MODULE_GetOrdinal( HMODULE32 hModule
, const char *name
)
756 unsigned char buffer
[256], *cpnt
;
760 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
762 TRACE(module
, "(%04x,'%s')\n",
765 /* First handle names of the form '#xxxx' */
767 if (name
[0] == '#') return atoi( name
+ 1 );
769 /* Now copy and uppercase the string */
771 strcpy( buffer
, name
);
772 CharUpper32A( buffer
);
773 len
= strlen( buffer
);
775 /* First search the resident names */
777 cpnt
= (char *)pModule
+ pModule
->name_table
;
779 /* Skip the first entry (module name) */
780 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
783 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
785 TRACE(module
, " Found: ordinal=%d\n",
786 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
787 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
789 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
792 /* Now search the non-resident names table */
794 if (!pModule
->nrname_handle
) return 0; /* No non-resident table */
795 cpnt
= (char *)GlobalLock16( pModule
->nrname_handle
);
797 /* Skip the first entry (module description string) */
798 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
801 if (((BYTE
)*cpnt
== len
) && !memcmp( cpnt
+1, buffer
, len
))
803 TRACE(module
, " Found: ordinal=%d\n",
804 *(WORD
*)(cpnt
+ *cpnt
+ 1) );
805 return *(WORD
*)(cpnt
+ *cpnt
+ 1);
807 cpnt
+= *cpnt
+ 1 + sizeof(WORD
);
813 /***********************************************************************
814 * MODULE_GetEntryPoint
816 * Return the entry point for a given ordinal.
818 FARPROC16
MODULE_GetEntryPoint( HMODULE32 hModule
, WORD ordinal
)
825 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
827 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
828 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
830 /* Skipping this bundle */
834 case 0: p
+= 2; break; /* unused */
835 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
836 default: p
+= 2 + *p
* 3; break; /* fixed */
845 case 0xff: /* moveable */
846 p
+= 2 + 6 * (ordinal
- curOrdinal
);
848 offset
= *(WORD
*)(p
+ 4);
852 p
+= 2 + 3 * (ordinal
- curOrdinal
);
853 offset
= *(WORD
*)(p
+ 1);
857 if (sel
== 0xfe) sel
= 0xffff; /* constant entry */
858 else sel
= (WORD
)(DWORD
)NE_SEG_TABLE(pModule
)[sel
-1].selector
;
859 return (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( sel
, offset
);
863 /***********************************************************************
864 * EntryAddrProc (WPROCS.27)
866 FARPROC16 WINAPI
EntryAddrProc( HMODULE16 hModule
, WORD ordinal
)
868 return MODULE_GetEntryPoint( hModule
, ordinal
);
872 /***********************************************************************
873 * MODULE_SetEntryPoint
875 * Change the value of an entry point. Use with caution!
876 * It can only change the offset value, not the selector.
878 BOOL16
MODULE_SetEntryPoint( HMODULE32 hModule
, WORD ordinal
, WORD offset
)
884 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
886 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
887 while (*p
&& (curOrdinal
+ *p
<= ordinal
))
889 /* Skipping this bundle */
893 case 0: p
+= 2; break; /* unused */
894 case 0xff: p
+= 2 + *p
* 6; break; /* moveable */
895 default: p
+= 2 + *p
* 3; break; /* fixed */
898 if (!*p
) return FALSE
;
904 case 0xff: /* moveable */
905 p
+= 2 + 6 * (ordinal
- curOrdinal
);
906 *(WORD
*)(p
+ 4) = offset
;
909 p
+= 2 + 3 * (ordinal
- curOrdinal
);
910 *(WORD
*)(p
+ 1) = offset
;
917 /***********************************************************************
918 * MODULE_GetWndProcEntry16 (not a Windows API function)
920 * Return an entry point from the WPROCS dll.
922 FARPROC16
MODULE_GetWndProcEntry16( LPCSTR name
)
924 FARPROC16 ret
= NULL
;
928 /* FIXME: hack for Winelib */
929 extern LRESULT
ColorDlgProc(HWND16
,UINT16
,WPARAM16
,LPARAM
);
930 extern LRESULT
FileOpenDlgProc(HWND16
,UINT16
,WPARAM16
,LPARAM
);
931 extern LRESULT
FileSaveDlgProc(HWND16
,UINT16
,WPARAM16
,LPARAM
);
932 extern LRESULT
FindTextDlgProc(HWND16
,UINT16
,WPARAM16
,LPARAM
);
933 extern LRESULT
PrintDlgProc(HWND16
,UINT16
,WPARAM16
,LPARAM
);
934 extern LRESULT
PrintSetupDlgProc(HWND16
,UINT16
,WPARAM16
,LPARAM
);
935 extern LRESULT
ReplaceTextDlgProc(HWND16
,UINT16
,WPARAM16
,LPARAM
);
937 if (!strcmp(name
,"ColorDlgProc"))
938 return (FARPROC16
)ColorDlgProc
;
939 if (!strcmp(name
,"FileOpenDlgProc"))
940 return (FARPROC16
)FileOpenDlgProc
;
941 if (!strcmp(name
,"FileSaveDlgProc"))
942 return (FARPROC16
)FileSaveDlgProc
;
943 if (!strcmp(name
,"FindTextDlgProc"))
944 return (FARPROC16
)FindTextDlgProc
;
945 if (!strcmp(name
,"PrintDlgProc"))
946 return (FARPROC16
)PrintDlgProc
;
947 if (!strcmp(name
,"PrintSetupDlgProc"))
948 return (FARPROC16
)PrintSetupDlgProc
;
949 if (!strcmp(name
,"ReplaceTextDlgProc"))
950 return (FARPROC16
)ReplaceTextDlgProc
;
951 fprintf(stderr
,"warning: No mapping for %s(), add one in library/miscstubs.c\n",name
);
958 static HMODULE32 hModule
= 0;
960 if (!hModule
) hModule
= GetModuleHandle16( "WPROCS" );
961 ordinal
= MODULE_GetOrdinal( hModule
, name
);
962 if (!(ret
= MODULE_GetEntryPoint( hModule
, ordinal
)))
964 fprintf( stderr
, "GetWndProc16: %s not found\n", name
);
972 /***********************************************************************
973 * MODULE_GetModuleName
975 LPSTR
MODULE_GetModuleName( HMODULE32 hModule
)
979 static char buffer
[10];
981 if (!(pModule
= MODULE_GetPtr( hModule
))) return NULL
;
982 p
= (BYTE
*)pModule
+ pModule
->name_table
;
984 memcpy( buffer
, p
+ 1, len
);
990 /**********************************************************************
991 * MODULE_RegisterModule
993 void MODULE_RegisterModule( NE_MODULE
*pModule
)
995 pModule
->next
= hFirstModule
;
996 hFirstModule
= pModule
->self
;
1000 /**********************************************************************
1003 * Find a module from a path name.
1005 HMODULE32
MODULE_FindModule( LPCSTR path
)
1007 HMODULE32 hModule
= hFirstModule
;
1008 LPCSTR filename
, dotptr
, modulepath
, modulename
;
1009 BYTE len
, *name_table
;
1011 if (!(filename
= strrchr( path
, '\\' ))) filename
= path
;
1013 if ((dotptr
= strrchr( filename
, '.' )) != NULL
)
1014 len
= (BYTE
)(dotptr
- filename
);
1015 else len
= strlen( filename
);
1019 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
1020 if (!pModule
) break;
1021 modulepath
= NE_MODULE_NAME(pModule
);
1022 if (!(modulename
= strrchr( modulepath
, '\\' )))
1023 modulename
= modulepath
;
1025 if (!lstrcmpi32A( modulename
, filename
)) return hModule
;
1027 name_table
= (BYTE
*)pModule
+ pModule
->name_table
;
1028 if ((*name_table
== len
) && !lstrncmpi32A(filename
, name_table
+1, len
))
1030 hModule
= pModule
->next
;
1036 /**********************************************************************
1039 * Call a DLL's WEP, allowing it to shut down.
1040 * FIXME: we always pass the WEP WEP_FREE_DLL, never WEP_SYSTEM_EXIT
1042 static BOOL16
MODULE_CallWEP( HMODULE16 hModule
)
1044 FARPROC16 WEP
= (FARPROC16
)0;
1045 WORD ordinal
= MODULE_GetOrdinal( hModule
, "WEP" );
1047 if (ordinal
) WEP
= MODULE_GetEntryPoint( hModule
, ordinal
);
1050 WARN(module
, "module %04x doesn't have a WEP\n", hModule
);
1053 return Callbacks
->CallWindowsExitProc( WEP
, WEP_FREE_DLL
);
1057 /**********************************************************************
1060 * Remove a module from memory.
1062 BOOL16
MODULE_FreeModule( HMODULE32 hModule
, TDB
* pTaskContext
)
1064 HMODULE16
*hPrevModule
;
1066 SEGTABLEENTRY
*pSegment
;
1070 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
1071 hModule
= pModule
->self
;
1073 if (((INT16
)(--pModule
->count
)) > 0 ) return TRUE
;
1074 else pModule
->count
= 0;
1076 if (pModule
->flags
& NE_FFLAGS_BUILTIN
)
1077 return FALSE
; /* Can't free built-in module */
1079 if (pModule
->flags
& NE_FFLAGS_LIBMODULE
)
1081 MODULE_CallWEP( hModule
);
1083 /* Free the objects owned by the DLL module */
1085 if( pTaskContext
&& pTaskContext
->userhandler
)
1087 pTaskContext
->userhandler( hModule
, USIG_DLL_UNLOAD
, 0,
1088 pTaskContext
->hInstance
,
1089 pTaskContext
->hQueue
);
1092 /* Clear magic number just in case */
1094 pModule
->magic
= pModule
->self
= 0;
1096 /* Remove it from the linked list */
1098 hPrevModule
= &hFirstModule
;
1099 while (*hPrevModule
&& (*hPrevModule
!= hModule
))
1101 hPrevModule
= &(MODULE_GetPtr( *hPrevModule
))->next
;
1103 if (*hPrevModule
) *hPrevModule
= pModule
->next
;
1105 /* Free all the segments */
1107 pSegment
= NE_SEG_TABLE( pModule
);
1108 for (i
= 1; i
<= pModule
->seg_count
; i
++, pSegment
++)
1110 GlobalFree16( pSegment
->selector
);
1113 /* Free the referenced modules */
1115 pModRef
= (HMODULE16
*)NE_MODULE_TABLE( pModule
);
1116 for (i
= 0; i
< pModule
->modref_count
; i
++, pModRef
++)
1118 FreeModule16( *pModRef
);
1121 /* Free the module storage */
1123 if (pModule
->nrname_handle
) GlobalFree16( pModule
->nrname_handle
);
1124 if (pModule
->dlls_to_init
) GlobalFree16( pModule
->dlls_to_init
);
1125 GlobalFree16( hModule
);
1127 /* Remove module from cache */
1129 if (hCachedModule
== hModule
) hCachedModule
= 0;
1135 /**********************************************************************
1138 * Implementation of LoadModule()
1140 HINSTANCE16
MODULE_Load( LPCSTR name
, LPVOID paramBlock
, UINT16 uFlags
)
1143 HINSTANCE16 hInstance
, hPrevInstance
;
1145 LOADPARAMS
*params
= (LOADPARAMS
*)paramBlock
;
1151 lstrcpyn32A( ofs
.szPathName
, name
, sizeof(ofs
.szPathName
) );
1152 if ((hModule
= MODULE_CreateDummyModule( &ofs
)) < 32) return hModule
;
1153 pModule
= (NE_MODULE
*)GlobalLock16( hModule
);
1155 hInstance
= MODULE_CreateInstance( hModule
, params
);
1159 hModule
= MODULE_FindModule( name
);
1161 if (!hModule
) /* We have to load the module */
1163 /* Try to load the built-in first if not disabled */
1164 if ((hModule
= fnBUILTIN_LoadModule( name
, FALSE
)))
1165 return MODULE_HANDLEtoHMODULE16( hModule
);
1167 if ((hFile
= OpenFile32( name
, &ofs
, OF_READ
)) == HFILE_ERROR32
)
1169 /* Now try the built-in even if disabled */
1170 if ((hModule
= fnBUILTIN_LoadModule( name
, TRUE
)))
1172 fprintf( stderr
, "Warning: could not load Windows DLL '%s', using built-in module.\n", name
);
1173 return MODULE_HANDLEtoHMODULE16( hModule
);
1175 return 2; /* File not found */
1178 /* Create the module structure */
1180 hModule
= MODULE_LoadExeHeader( hFile
, &ofs
);
1184 hModule
= PE_LoadModule( hFile
, &ofs
, paramBlock
);
1185 else _lclose32( hFile
);
1188 fprintf( stderr
, "LoadModule: can't load '%s', error=%d\n",
1193 pModule
= MODULE_GetPtr( hModule
);
1194 pModule
->flags
|= uFlags
; /* stamp implicitly loaded modules */
1196 /* Allocate the segments for this module */
1198 MODULE_CreateSegments( hModule
);
1200 hInstance
= MODULE_CreateInstance(hModule
,(LOADPARAMS
*)paramBlock
);
1202 /* Load the referenced DLLs */
1204 if (!NE_LoadDLLs( pModule
)) return 2; /* File not found */
1206 /* Load the segments */
1208 NE_LoadAllSegments( pModule
);
1210 /* Fixup the functions prologs */
1212 NE_FixupPrologs( pModule
);
1214 /* Make sure the usage count is 1 on the first loading of */
1215 /* the module, even if it contains circular DLL references */
1219 /* Call initialization rountines for all loaded DLLs. Note that
1220 * when we load implicitly linked DLLs this will be done by InitTask().
1223 if ((pModule
->flags
& (NE_FFLAGS_LIBMODULE
| NE_FFLAGS_IMPLICIT
)) ==
1224 NE_FFLAGS_LIBMODULE
)
1225 NE_InitializeDLLs( hModule
);
1227 else /* module is already loaded, just create a new data segment if it's a task */
1229 pModule
= MODULE_GetPtr( hModule
);
1230 hPrevInstance
= MODULE_GetInstance( hModule
);
1231 hInstance
= MODULE_CreateInstance( hModule
, params
);
1232 if (hInstance
!= hPrevInstance
) /* not a library */
1233 NE_LoadSegment( pModule
, pModule
->dgroup
);
1238 /* Create a task for this instance */
1240 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) && (paramBlock
!= (LPVOID
)-1))
1245 pModule
->flags
|= NE_FFLAGS_GUI
;
1247 /* PowerPoint passes NULL as showCmd */
1248 if (params
->showCmd
)
1249 showcmd
= *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1);
1251 showcmd
= 0; /* FIXME: correct */
1253 hTask
= TASK_CreateTask( hModule
, hInstance
, hPrevInstance
,
1254 params
->hEnvironment
,
1255 (LPSTR
)PTR_SEG_TO_LIN( params
->cmdLine
),
1258 if( hTask
&& TASK_GetNextTask(hTask
)) Yield16();
1265 /**********************************************************************
1266 * LoadModule16 (KERNEL.45)
1268 HINSTANCE16
LoadModule16( LPCSTR name
, LPVOID paramBlock
)
1270 return MODULE_Load( name
, paramBlock
, 0 );
1273 /**********************************************************************
1274 * LoadModule32 (KERNEL32.499)
1278 * This should get implemented via CreateProcess -- MODULE_Load
1279 * is resolutely 16-bit.
1281 DWORD
LoadModule32( LPCSTR name
, LPVOID paramBlock
)
1284 LOADPARAMS32
*p
= paramBlock
;
1286 PROCESSINFORMATION pi
;
1287 st
.cb
= sizeof(STARTUPINFO
);
1288 st
.wShowWindow
= p
->lpCmdShow
[2] ; WRONG
1290 BOOL32 ret
= CreateProcess32A( name
, p
->lpCmdLine
,
1291 NULL
, NULL
, FALSE
, 0, p
->lpEnvAddress
,
1294 /* handle errors appropriately */
1296 CloseHandle32(pi
.hProcess
);
1297 CloseHandle32(pi
.hThread
);
1300 return MODULE_Load( name
, paramBlock
, 0 );
1305 /**********************************************************************
1306 * FreeModule16 (KERNEL.46)
1308 BOOL16 WINAPI
FreeModule16( HMODULE16 hModule
)
1312 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
1313 TRACE(module
, "%s count %d\n",
1314 MODULE_GetModuleName(hModule
), pModule
->count
);
1316 return MODULE_FreeModule( hModule
, GlobalLock16(GetCurrentTask()) );
1320 /**********************************************************************
1321 * GetModuleHandle16 (KERNEL.47)
1323 HMODULE16 WINAPI
WIN16_GetModuleHandle( SEGPTR name
)
1325 if (HIWORD(name
) == 0) return MODULE_HANDLEtoHMODULE16( (HINSTANCE16
)name
);
1326 return MODULE_FindModule( PTR_SEG_TO_LIN(name
) );
1329 HMODULE16 WINAPI
GetModuleHandle16( LPCSTR name
)
1331 return MODULE_FindModule( name
);
1334 /***********************************************************************
1335 * GetModuleHandle (KERNEL32.237)
1337 HMODULE32 WINAPI
GetModuleHandle32A(LPCSTR module
)
1341 TRACE(win32
, "%s\n", module
? module
: "NULL");
1342 /* Freecell uses the result of GetModuleHandleA(0) as the hInstance in
1343 all calls to e.g. CreateWindowEx. */
1344 if (module
== NULL
) {
1345 TDB
*pTask
= (TDB
*)GlobalLock16( GetCurrentTask() );
1346 hModule
= pTask
->hInstance
;
1348 hModule
= MODULE_FindModule(module
);
1349 return MODULE_HANDLEtoHMODULE32(hModule
);
1352 HMODULE32 WINAPI
GetModuleHandle32W(LPCWSTR module
)
1355 LPSTR modulea
= HEAP_strdupWtoA( GetProcessHeap(), 0, module
);
1356 hModule
= GetModuleHandle32A( modulea
);
1357 HeapFree( GetProcessHeap(), 0, modulea
);
1362 /**********************************************************************
1363 * GetModuleUsage (KERNEL.48)
1365 INT16 WINAPI
GetModuleUsage( HINSTANCE16 hModule
)
1369 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1370 TRACE(module
, "(%04x): returning %d\n",
1371 hModule
, pModule
->count
);
1372 return pModule
->count
;
1376 /**********************************************************************
1377 * GetModuleFileName16 (KERNEL.49)
1379 INT16 WINAPI
GetModuleFileName16( HINSTANCE16 hModule
, LPSTR lpFileName
,
1384 if (!hModule
) hModule
= GetCurrentTask();
1385 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1386 lstrcpyn32A( lpFileName
, NE_MODULE_NAME(pModule
), nSize
);
1387 TRACE(module
, "%s\n", lpFileName
);
1388 return strlen(lpFileName
);
1392 /***********************************************************************
1393 * GetModuleFileName32A (KERNEL32.235)
1395 DWORD WINAPI
GetModuleFileName32A( HMODULE32 hModule
, LPSTR lpFileName
,
1402 TDB
*pTask
= (TDB
*)GlobalLock16( GetCurrentTask() );
1403 hModule
= pTask
->hInstance
;
1405 if (!(pModule
= MODULE_GetPtr( hModule
))) return 0;
1406 lstrcpyn32A( lpFileName
, NE_MODULE_NAME(pModule
), size
);
1407 TRACE(module
, "%s\n", lpFileName
);
1408 return strlen(lpFileName
);
1412 /***********************************************************************
1413 * GetModuleFileName32W (KERNEL32.236)
1415 DWORD WINAPI
GetModuleFileName32W( HMODULE32 hModule
, LPWSTR lpFileName
,
1418 LPSTR fnA
= (char*)HeapAlloc( GetProcessHeap(), 0, size
);
1419 DWORD res
= GetModuleFileName32A( hModule
, fnA
, size
);
1420 lstrcpynAtoW( lpFileName
, fnA
, size
);
1421 HeapFree( GetProcessHeap(), 0, fnA
);
1426 /**********************************************************************
1427 * GetModuleName (KERNEL.27)
1429 BOOL16 WINAPI
GetModuleName( HINSTANCE16 hinst
, LPSTR buf
, INT16 nSize
)
1431 LPSTR name
= MODULE_GetModuleName(hinst
);
1433 if (!name
) return FALSE
;
1434 lstrcpyn32A( buf
, name
, nSize
);
1439 /***********************************************************************
1440 * LoadLibraryEx32W (KERNEL.513)
1443 HMODULE32 WINAPI
LoadLibraryEx32W16( LPCSTR libname
, HANDLE16 hf
,
1446 fprintf(stderr
,"LoadLibraryEx32W(%s,%d,%08lx)\n",libname
,hf
,flags
);
1447 return LoadLibraryEx32A(libname
, hf
,flags
);
1450 /***********************************************************************
1451 * LoadLibraryEx32A (KERNEL32)
1453 HMODULE32 WINAPI
LoadLibraryEx32A(LPCSTR libname
,HFILE32 hfile
,DWORD flags
)
1457 hmod
= PE_LoadLibraryEx32A(libname
,PROCESS_Current(),hfile
,flags
);
1461 strcpy( buffer
, libname
);
1462 strcat( buffer
, ".dll" );
1463 hmod
= PE_LoadLibraryEx32A(buffer
,PROCESS_Current(),hfile
,flags
);
1465 /* initialize all DLLs, which haven't been initialized yet. */
1466 PE_InitializeDLLs( PROCESS_Current(), DLL_PROCESS_ATTACH
, NULL
);
1470 /***********************************************************************
1471 * LoadLibraryA (KERNEL32)
1473 HMODULE32 WINAPI
LoadLibrary32A(LPCSTR libname
) {
1474 return LoadLibraryEx32A(libname
,0,0);
1477 /***********************************************************************
1478 * LoadLibraryW (KERNEL32)
1480 HMODULE32 WINAPI
LoadLibrary32W(LPCWSTR libnameW
)
1482 return LoadLibraryEx32W(libnameW
,0,0);
1485 /***********************************************************************
1486 * LoadLibraryExW (KERNEL32)
1488 HMODULE32 WINAPI
LoadLibraryEx32W(LPCWSTR libnameW
,HFILE32 hfile
,DWORD flags
)
1490 LPSTR libnameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, libnameW
);
1491 HMODULE32 ret
= LoadLibraryEx32A( libnameA
, hfile
, flags
);
1493 HeapFree( GetProcessHeap(), 0, libnameA
);
1497 /***********************************************************************
1500 BOOL32 WINAPI
FreeLibrary32(HINSTANCE32 hLibModule
)
1502 TRACE(module
,"hLibModule=%08x\n", hLibModule
);
1503 return MODULE_FreeModule(hLibModule
,
1504 GlobalLock16(GetCurrentTask()) );
1508 /***********************************************************************
1509 * LoadLibrary (KERNEL.95)
1511 HINSTANCE16 WINAPI
LoadLibrary16( LPCSTR libname
)
1517 fprintf( stderr
, "LoadLibrary not supported in Winelib\n" );
1520 TRACE(module
, "(%08x) %s\n", (int)libname
, libname
);
1522 handle
= MODULE_Load( libname
, (LPVOID
)-1, 0 );
1523 if (handle
== (HINSTANCE16
)2) /* file not found */
1526 lstrcpyn32A( buffer
, libname
, 252 );
1527 strcat( buffer
, ".dll" );
1528 handle
= MODULE_Load( buffer
, (LPVOID
)-1, 0 );
1534 /***********************************************************************
1535 * PrivateLoadLibrary (KERNEL32)
1537 * FIXME: rough guesswork, don't know what "Private" means
1539 HINSTANCE32 WINAPI
PrivateLoadLibrary(LPCSTR libname
)
1541 return (HINSTANCE32
)LoadLibrary16(libname
);
1545 /***********************************************************************
1546 * FreeLibrary16 (KERNEL.96)
1548 void WINAPI
FreeLibrary16( HINSTANCE16 handle
)
1550 TRACE(module
,"%04x\n", handle
);
1551 FreeModule16( handle
);
1555 /***********************************************************************
1556 * PrivateFreeLibrary (KERNEL32)
1558 * FIXME: rough guesswork, don't know what "Private" means
1560 void WINAPI
PrivateFreeLibrary(HINSTANCE32 handle
)
1562 FreeLibrary16((HINSTANCE16
)handle
);
1566 /***********************************************************************
1567 * WinExec16 (KERNEL.166)
1569 HINSTANCE16 WINAPI
WinExec16( LPCSTR lpCmdLine
, UINT16 nCmdShow
)
1571 return WinExec32( lpCmdLine
, nCmdShow
);
1575 /***********************************************************************
1576 * WinExec32 (KERNEL32.566)
1578 HINSTANCE32 WINAPI
WinExec32( LPCSTR lpCmdLine
, UINT32 nCmdShow
)
1581 HGLOBAL16 cmdShowHandle
, cmdLineHandle
;
1582 HINSTANCE32 handle
= 2;
1584 char *p
, *cmdline
, filename
[256];
1585 static int use_load_module
= 1;
1586 int spacelimit
= 0, exhausted
= 0;
1589 return 2; /* File not found */
1590 if (!(cmdShowHandle
= GlobalAlloc16( 0, 2 * sizeof(WORD
) )))
1591 return 8; /* Out of memory */
1592 if (!(cmdLineHandle
= GlobalAlloc16( 0, 2048 )))
1594 GlobalFree16( cmdShowHandle
);
1595 return 8; /* Out of memory */
1598 /* Keep trying to load a file by trying different filenames; e.g.,
1599 for the cmdline "abcd efg hij", try "abcd" with args "efg hij",
1600 then "abcd efg" with arg "hij", and finally "abcd efg hij" with
1603 while(!exhausted
&& handle
== 2) {
1606 /* Store nCmdShow */
1608 cmdShowPtr
= (WORD
*)GlobalLock16( cmdShowHandle
);
1610 cmdShowPtr
[1] = nCmdShow
;
1612 /* Build the filename and command-line */
1614 cmdline
= (char *)GlobalLock16( cmdLineHandle
);
1615 lstrcpyn32A(filename
, lpCmdLine
,
1616 sizeof(filename
) - 4 /* for extension */);
1618 /* Keep grabbing characters until end-of-string, tab, or until the
1619 number of spaces is greater than the spacelimit */
1621 for (p
= filename
; ; p
++) {
1624 if(spacecount
> spacelimit
) {
1630 if(*p
== '\0' || *p
== '\t') {
1637 lstrcpyn32A( cmdline
+ 1, p
+ 1, 255 );
1641 cmdline
[0] = strlen( cmdline
+ 1 );
1643 /* this is a (hopefully acceptable hack to get the whole
1644 commandline for PROCESS_Create
1645 we put it after the processed one */
1646 lstrcpyn32A(cmdline
+ (unsigned char)cmdline
[0] +2,
1647 lpCmdLine
, 2048 - 256);
1649 /* Now load the executable file */
1651 if (use_load_module
)
1653 /* Winelib: Use LoadModule() only for the program itself */
1654 if (__winelib
) use_load_module
= 0;
1655 params
.hEnvironment
= (HGLOBAL16
)SELECTOROF( GetDOSEnvironment() );
1656 params
.cmdLine
= (SEGPTR
)WIN16_GlobalLock16( cmdLineHandle
);
1657 params
.showCmd
= (SEGPTR
)WIN16_GlobalLock16( cmdShowHandle
);
1658 params
.reserved
= 0;
1659 handle
= LoadModule32( filename
, ¶ms
);
1660 if (handle
== 2) /* file not found */
1662 /* Check that the original file name did not have a suffix */
1663 p
= strrchr(filename
, '.');
1664 /* if there is a '.', check if either \ OR / follow */
1665 if (!p
|| strchr(p
, '/') || strchr(p
, '\\'))
1667 p
= filename
+ strlen(filename
);
1668 strcpy( p
, ".exe" );
1669 handle
= LoadModule16( filename
, ¶ms
);
1670 *p
= '\0'; /* Remove extension */
1675 handle
= 2; /* file not found */
1679 /* Try to start it as a unix program */
1683 DOS_FULL_NAME full_name
;
1684 const char *unixfilename
= NULL
;
1685 const char *argv
[256], **argptr
;
1686 int iconic
= (nCmdShow
== SW_SHOWMINIMIZED
||
1687 nCmdShow
== SW_SHOWMINNOACTIVE
);
1689 THREAD_InitDone
= FALSE
; /* we didn't init this process */
1690 /* get unixfilename */
1691 if (strchr(filename
, '/') ||
1692 strchr(filename
, ':') ||
1693 strchr(filename
, '\\'))
1695 if (DOSFS_GetFullName( filename
, TRUE
, &full_name
))
1696 unixfilename
= full_name
.long_name
;
1698 else unixfilename
= filename
;
1704 if (iconic
) *argptr
++ = "-iconic";
1705 *argptr
++ = unixfilename
;
1709 while (*p
&& (*p
== ' ' || *p
== '\t')) *p
++ = '\0';
1712 while (*p
&& *p
!= ' ' && *p
!= '\t') p
++;
1717 execvp(argv
[0], (char**)argv
);
1727 if (iconic
) *argptr
++ = "-iconic";
1728 *argptr
++ = lpCmdLine
;
1732 execvp(argv
[0] , (char**)argv
);
1735 fprintf(stderr
, "WinExec: can't exec 'wine %s'\n",
1741 } /* while (!exhausted && handle < 32) */
1743 GlobalFree16( cmdShowHandle
);
1744 GlobalFree16( cmdLineHandle
);
1749 /***********************************************************************
1750 * WIN32_GetProcAddress16 (KERNEL32.36)
1751 * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
1753 FARPROC16 WINAPI
WIN32_GetProcAddress16( HMODULE32 hModule
, LPSTR name
)
1759 fprintf(stderr
,"WIN32_GetProcAddress16: hModule may not be 0!\n");
1760 return (FARPROC16
)0;
1762 hModule
= MODULE_HANDLEtoHMODULE16(hModule
);
1764 ordinal
= MODULE_GetOrdinal( hModule
, name
);
1765 TRACE(module
, "%04x '%s'\n",
1768 ordinal
= LOWORD(name
);
1769 TRACE(module
, "%04x %04x\n",
1772 if (!ordinal
) return (FARPROC16
)0;
1773 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1774 TRACE(module
,"returning %08x\n",(UINT32
)ret
);
1778 /***********************************************************************
1779 * GetProcAddress16 (KERNEL.50)
1781 FARPROC16 WINAPI
GetProcAddress16( HMODULE16 hModule
, SEGPTR name
)
1786 if (!hModule
) hModule
= GetCurrentTask();
1787 hModule
= MODULE_HANDLEtoHMODULE16( hModule
);
1789 if (HIWORD(name
) != 0)
1791 ordinal
= MODULE_GetOrdinal( hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1792 TRACE(module
, "%04x '%s'\n",
1793 hModule
, (LPSTR
)PTR_SEG_TO_LIN(name
) );
1797 ordinal
= LOWORD(name
);
1798 TRACE(module
, "%04x %04x\n",
1801 if (!ordinal
) return (FARPROC16
)0;
1803 ret
= MODULE_GetEntryPoint( hModule
, ordinal
);
1805 TRACE(module
, "returning %08x\n", (UINT32
)ret
);
1810 /***********************************************************************
1811 * GetProcAddress32 (KERNEL32.257)
1813 FARPROC32 WINAPI
GetProcAddress32( HMODULE32 hModule
, LPCSTR function
)
1817 if (HIWORD(function
))
1818 TRACE(win32
,"(%08lx,%s)\n",(DWORD
)hModule
,function
);
1820 TRACE(win32
,"(%08lx,%p)\n",(DWORD
)hModule
,function
);
1821 if (!(pModule
= MODULE_GetPtr( hModule
)))
1822 return (FARPROC32
)0;
1823 if (!pModule
->module32
)
1825 fprintf(stderr
,"Oops, Module 0x%08lx has got no module32?\n",
1826 (DWORD
)MODULE_HANDLEtoHMODULE32(hModule
)
1828 return (FARPROC32
)0;
1830 return PE_FindExportedFunction( PROCESS_Current(), pModule
->module32
,
1834 /***********************************************************************
1835 * RtlImageNtHeaders (NTDLL)
1837 LPIMAGE_NT_HEADERS WINAPI
RtlImageNtHeader(HMODULE32 hModule
)
1840 * return hModule+(((IMAGE_DOS_HEADER*)hModule)->e_lfanew);
1841 * but we could get HMODULE16 or the like (think builtin modules)
1846 if (!(pModule
= MODULE_GetPtr( hModule
)))
1847 return (LPIMAGE_NT_HEADERS
)0;
1848 if (!(pModule
->flags
& NE_FFLAGS_WIN32
) || !pModule
->module32
)
1849 return (LPIMAGE_NT_HEADERS
)0;
1850 return PE_HEADER(pModule
->module32
);
1854 /**********************************************************************
1855 * GetExpWinVer (KERNEL.167)
1857 WORD WINAPI
GetExpWinVer( HMODULE16 hModule
)
1859 NE_MODULE
*pModule
= MODULE_GetPtr( hModule
);
1860 return pModule
? pModule
->expected_version
: 0;
1864 /**********************************************************************
1865 * IsSharedSelector (KERNEL.345)
1867 BOOL16 WINAPI
IsSharedSelector( HANDLE16 selector
)
1869 /* Check whether the selector belongs to a DLL */
1870 NE_MODULE
*pModule
= MODULE_GetPtr( selector
);
1871 if (!pModule
) return FALSE
;
1872 return (pModule
->flags
& NE_FFLAGS_LIBMODULE
) != 0;
1876 /**********************************************************************
1877 * ModuleFirst (TOOLHELP.59)
1879 BOOL16 WINAPI
ModuleFirst( MODULEENTRY
*lpme
)
1881 lpme
->wNext
= hFirstModule
;
1882 return ModuleNext( lpme
);
1886 /**********************************************************************
1887 * ModuleNext (TOOLHELP.60)
1889 BOOL16 WINAPI
ModuleNext( MODULEENTRY
*lpme
)
1894 if (!lpme
->wNext
) return FALSE
;
1895 if (!(pModule
= MODULE_GetPtr( lpme
->wNext
))) return FALSE
;
1896 name
= (char *)pModule
+ pModule
->name_table
;
1897 memcpy( lpme
->szModule
, name
+ 1, *name
);
1898 lpme
->szModule
[(BYTE
)*name
] = '\0';
1899 lpme
->hModule
= lpme
->wNext
;
1900 lpme
->wcUsage
= pModule
->count
;
1901 strncpy( lpme
->szExePath
, NE_MODULE_NAME(pModule
), MAX_PATH
);
1902 lpme
->szExePath
[MAX_PATH
] = '\0';
1903 lpme
->wNext
= pModule
->next
;
1908 /**********************************************************************
1909 * ModuleFindName (TOOLHELP.61)
1911 BOOL16 WINAPI
ModuleFindName( MODULEENTRY
*lpme
, LPCSTR name
)
1913 lpme
->wNext
= GetModuleHandle16( name
);
1914 return ModuleNext( lpme
);
1918 /**********************************************************************
1919 * ModuleFindHandle (TOOLHELP.62)
1921 BOOL16 WINAPI
ModuleFindHandle( MODULEENTRY
*lpme
, HMODULE16 hModule
)
1923 hModule
= MODULE_HANDLEtoHMODULE16( hModule
);
1924 lpme
->wNext
= hModule
;
1925 return ModuleNext( lpme
);