wine/loader/module.c
Alexandre Julliard 329f0680e4 Release 960414
Sun Apr 14 12:51:27 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/menu.c] [include/dialog.h] [windows/dialog.c]
	Made the resource loading code always use the correct Windows
	layout for Winelib on other CPUs.

	* [include/module.h] [loader/module.c]
	Added self handle in NE_MODULE structure, so we can use a pointer
	instead of a handle.
	Added function MODULE_GetPtr() to validate a HMODULE.

	* [memory/heap.c]
	Implemented Win32 heap management.

	* [memory/selector.c]
	Fix selector limit for huge blocks.

Sat Apr 13 00:19:12 1996  Huw D. M. Davies <h.davies1@physics.oxford.ac.uk>

	* [objects/metafile.c]
	Fixed memcpy bug to allow memory based metafiles to work.

Fri Apr 12 19:25:41 1996  Frans van Dorsselaer  <dorssel@rulhm1.leidenuniv.nl>

	* [controls/edit.c] [controls/EDIT.TODO]
	Complete rewrite.  Everything changed: new features, new bugs.
	Main addition: WordWrap.

Fri Apr 12 20:29:55 1996  Tristan Tarrant <tst@dcs.ed.ac.uk>

	* [resources/sysres_It.rc]
	Fixed a few mistakes in the file and resized some of the controls.

Fri Apr 12 09:55:13 1996  John Harvey <john@division.co.uk>

	* [misc/winsocket.c]
	Fixed broken #if defined that stopped unixware compiling.

	* [win32/resource.c]
        Added missing return to end of FindResource32.

Thu Apr 11 18:00:00 1996  Alex Korobka <alex@phm30.pharm.sunysb.edu>

	* [windows/keyboard.c] [windows/event.c]
	Fixed GetKeyState for mouse buttons.

	* [windows/message.c]
	WM_MOUSEACTIVATE wasn't sent in some cases.

Wed Apr 10 18:59:53 1996  Niels de Carpentier  <niels@cindy.et.tudelft.nl>

	* [objects/font.c]
	Match slightly bigger font if height negative.

Mon Apr  8 13:46:15 1996  Deano Calver <deano@rattie.demon.co.uk>

	* [multimedia/mmsystem.c]
	Changed read's to FILE_read's in mmsystem to fix mmio bug.

Sun Apr  7 21:40:29 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [misc/commdlg.c] [resources/sysres_En.rc] [resources/sysres_De.rc]
	Introduced ColorDlgProc() for ChooseColor() and replaced fitting
	En-,De- resources. 
	As written in TODO: some national language support is needed here.
1996-04-14 13:21:20 +00:00

1594 lines
48 KiB
C

/*
* Modules
*
* Copyright 1995 Alexandre Julliard
*/
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "windows.h"
#include "dlls.h"
#include "dos_fs.h"
#include "file.h"
#include "global.h"
#include "ldt.h"
#include "module.h"
#include "neexe.h"
#include "stackframe.h"
#include "task.h"
#include "toolhelp.h"
#include "stddebug.h"
#include "debug.h"
#include "callback.h"
#include "wine.h"
extern HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params );
static HMODULE hFirstModule = 0;
static HMODULE hCachedModule = 0; /* Module cached by MODULE_OpenFile */
#ifndef WINELIB
static HANDLE hInitialStack32 = 0;
#endif
/***********************************************************************
* MODULE_LoadBuiltin
*
* Load a built-in module. If the 'force' parameter is FALSE, we only
* load the module if it has not been disabled via the -dll option.
*/
#ifndef WINELIB
static HMODULE MODULE_LoadBuiltin( LPCSTR name, BOOL force )
{
HMODULE hModule;
NE_MODULE *pModule;
SEGTABLEENTRY *pSegTable;
BUILTIN_DLL *table;
char dllname[16], *p;
/* Fix the name in case we have a full path and extension */
if ((p = strrchr( name, '\\' ))) name = p + 1;
lstrcpyn( dllname, name, sizeof(dllname) );
if ((p = strrchr( dllname, '.' ))) *p = '\0';
for (table = dll_builtin_table; table->name; table++)
if (!lstrcmpi( table->name, dllname )) break;
if (!table->name) return 0;
if ((table->flags & DLL_FLAG_NOT_USED) && !force) return 0;
hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, table->module_start,
table->module_end - table->module_start,
0, FALSE, FALSE, FALSE, NULL );
if (!hModule) return 0;
FarSetOwner( hModule, hModule );
table->hModule = hModule;
dprintf_module( stddeb, "Built-in %s: hmodule=%04x\n",
table->name, hModule );
pModule = (NE_MODULE *)GlobalLock( hModule );
pModule->self = hModule;
if (pModule->flags & NE_FFLAGS_WIN32)
{
pModule->pe_module = (PE_MODULE *)table;
}
else /* Win16 module */
{
/* Allocate the code segment */
pSegTable = NE_SEG_TABLE( pModule );
pSegTable->selector = GLOBAL_CreateBlock(GMEM_FIXED, table->code_start,
pSegTable->minsize, hModule,
TRUE, TRUE, FALSE, NULL );
if (!pSegTable->selector) return 0;
pSegTable++;
/* Allocate the data segment */
pSegTable->selector = GLOBAL_Alloc( GMEM_FIXED, pSegTable->minsize,
hModule, FALSE, FALSE, FALSE );
if (!pSegTable->selector) return 0;
memcpy( GlobalLock( pSegTable->selector ),
table->data_start, pSegTable->minsize );
}
pModule->next = hFirstModule;
hFirstModule = hModule;
return hModule;
}
#endif
/***********************************************************************
* MODULE_Init
*
* Create the built-in modules.
*/
BOOL MODULE_Init(void)
{
#ifndef WINELIB32
BUILTIN_DLL *dll;
/* Load all modules marked as always used */
for (dll = dll_builtin_table; dll->name; dll++)
if (dll->flags & DLL_FLAG_ALWAYS_USED)
if (!MODULE_LoadBuiltin(dll->name, TRUE)) return FALSE;
#endif
/* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
MODULE_SetEntryPoint( GetModuleHandle( "KERNEL" ), 178, GetWinFlags() );
return TRUE;
}
/***********************************************************************
* MODULE_GetPtr
*/
NE_MODULE *MODULE_GetPtr( HMODULE hModule )
{
NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
if (!pModule || (pModule->magic != NE_SIGNATURE) ||
(pModule->self != hModule)) return NULL;
return pModule;
}
/***********************************************************************
* MODULE_DumpModule
*/
void MODULE_DumpModule( HMODULE hmodule )
{
int i, ordinal;
SEGTABLEENTRY *pSeg;
BYTE *pstr;
WORD *pword;
NE_MODULE *pModule;
if (!(pModule = MODULE_GetPtr( hmodule )))
{
fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
return;
}
/* Dump the module info */
printf( "Module %04x:\n", hmodule );
printf( "count=%d flags=%04x heap=%d stack=%d\n",
pModule->count, pModule->flags,
pModule->heap_size, pModule->stack_size );
printf( "cs:ip=%04x:%04x ss:sp=%04x:%04x ds=%04x nb seg=%d modrefs=%d\n",
pModule->cs, pModule->ip, pModule->ss, pModule->sp, pModule->dgroup,
pModule->seg_count, pModule->modref_count );
printf( "os_flags=%d swap_area=%d version=%04x\n",
pModule->os_flags, pModule->min_swap_area,
pModule->expected_version );
if (pModule->flags & NE_FFLAGS_WIN32)
printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
/* Dump the file info */
printf( "Filename: '%s'\n", NE_MODULE_NAME(pModule) );
/* Dump the segment table */
printf( "\nSegment table:\n" );
pSeg = NE_SEG_TABLE( pModule );
for (i = 0; i < pModule->seg_count; i++, pSeg++)
printf( "%02x: pos=%d size=%d flags=%04x minsize=%d sel=%04x\n",
i + 1, pSeg->filepos, pSeg->size, pSeg->flags,
pSeg->minsize, pSeg->selector );
/* Dump the resource table */
printf( "\nResource table:\n" );
if (pModule->res_table)
{
pword = (WORD *)((BYTE *)pModule + pModule->res_table);
printf( "Alignment: %d\n", *pword++ );
while (*pword)
{
struct resource_typeinfo_s *ptr = (struct resource_typeinfo_s *)pword;
struct resource_nameinfo_s *pname = (struct resource_nameinfo_s *)(ptr + 1);
printf( "id=%04x count=%d\n", ptr->type_id, ptr->count );
for (i = 0; i < ptr->count; i++, pname++)
printf( "offset=%d len=%d id=%04x\n",
pname->offset, pname->length, pname->id );
pword = (WORD *)pname;
}
}
else printf( "None\n" );
/* Dump the resident name table */
printf( "\nResident-name table:\n" );
pstr = (char *)pModule + pModule->name_table;
while (*pstr)
{
printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
*(WORD *)(pstr + *pstr + 1) );
pstr += *pstr + 1 + sizeof(WORD);
}
/* Dump the module reference table */
printf( "\nModule ref table:\n" );
if (pModule->modref_table)
{
pword = (WORD *)((BYTE *)pModule + pModule->modref_table);
for (i = 0; i < pModule->modref_count; i++, pword++)
{
char *name = (char *)pModule + pModule->import_table + *pword;
printf( "%d: %04x -> '%*.*s'\n",
i, *pword, *name, *name, name + 1 );
}
}
else printf( "None\n" );
/* Dump the entry table */
printf( "\nEntry table:\n" );
pstr = (char *)pModule + pModule->entry_table;
ordinal = 1;
while (*pstr)
{
printf( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
if (!pstr[1])
{
ordinal += *pstr;
pstr += 2;
}
else if ((BYTE)pstr[1] == 0xff) /* moveable */
{
struct entry_tab_movable_s *pe = (struct entry_tab_movable_s*)(pstr+2);
for (i = 0; i < *pstr; i++, pe++)
printf( "%d: %02x:%04x (moveable)\n",
ordinal++, pe->seg_number, pe->offset );
pstr = (char *)pe;
}
else /* fixed */
{
struct entry_tab_fixed_s *pe = (struct entry_tab_fixed_s*)(pstr+2);
for (i = 0; i < *pstr; i++, pe++)
printf( "%d: %04x (fixed)\n",
ordinal++, pe->offset[0] + (pe->offset[1] << 8) );
pstr = (char *)pe;
}
}
/* Dump the non-resident names table */
printf( "\nNon-resident names table:\n" );
if (pModule->nrname_handle)
{
pstr = (char *)GlobalLock( pModule->nrname_handle );
while (*pstr)
{
printf( "%*.*s: %d\n", *pstr, *pstr, pstr + 1,
*(WORD *)(pstr + *pstr + 1) );
pstr += *pstr + 1 + sizeof(WORD);
}
}
printf( "\n" );
}
/***********************************************************************
* MODULE_WalkModules
*
* Walk the module list and print the modules.
*/
void MODULE_WalkModules(void)
{
HMODULE hModule = hFirstModule;
fprintf( stderr, "Module Flags Name\n" );
while (hModule)
{
NE_MODULE *pModule = MODULE_GetPtr( hModule );
if (!pModule)
{
fprintf( stderr, "**** Bad module %04x in list\n", hModule );
return;
}
fprintf( stderr, " %04x %04x %.*s\n", hModule, pModule->flags,
*((char *)pModule + pModule->name_table),
(char *)pModule + pModule->name_table + 1 );
hModule = pModule->next;
}
}
/***********************************************************************
* MODULE_OpenFile
*/
int MODULE_OpenFile( HMODULE hModule )
{
NE_MODULE *pModule;
char *name;
const char *unixName;
static int cachedfd = -1;
hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
hModule, hCachedModule, cachedfd );
if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
if (hCachedModule == hModule) return cachedfd;
close( cachedfd );
hCachedModule = hModule;
name = NE_MODULE_NAME( pModule );
if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
(cachedfd = open( unixName, O_RDONLY )) == -1)
fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
name, hModule );
dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
name, cachedfd );
return cachedfd;
}
/***********************************************************************
* MODULE_Ne2MemFlags
*
* This function translates NE segment flags to GlobalAlloc flags
*/
static WORD MODULE_Ne2MemFlags(WORD flags)
{
WORD memflags = 0;
#if 0
if (flags & NE_SEGFLAGS_DISCARDABLE)
memflags |= GMEM_DISCARDABLE;
if (flags & NE_SEGFLAGS_MOVEABLE ||
( ! (flags & NE_SEGFLAGS_DATA) &&
! (flags & NE_SEGFLAGS_LOADED) &&
! (flags & NE_SEGFLAGS_ALLOCATED)
)
)
memflags |= GMEM_MOVEABLE;
memflags |= GMEM_ZEROINIT;
#else
memflags = GMEM_ZEROINIT | GMEM_FIXED;
return memflags;
#endif
}
/***********************************************************************
* MODULE_AllocateSegment (WINPROCS.26)
*/
DWORD MODULE_AllocateSegment(WORD wFlags, WORD wSize, WORD wElem)
{
WORD size = wSize << wElem;
HANDLE hMem = GlobalAlloc( MODULE_Ne2MemFlags(wFlags), size);
#ifdef WINELIB32
return (DWORD)GlobalLock(hMem);
#else
WORD selector = HIWORD(GlobalLock(hMem));
return MAKELONG(hMem, selector);
#endif
}
/***********************************************************************
* MODULE_CreateSegments
*/
#ifndef WINELIB32
static BOOL MODULE_CreateSegments( HMODULE hModule )
{
SEGTABLEENTRY *pSegment;
NE_MODULE *pModule;
int i, minsize;
if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
pSegment = NE_SEG_TABLE( pModule );
for (i = 1; i <= pModule->seg_count; i++, pSegment++)
{
minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
if (i == pModule->ss) minsize += pModule->stack_size;
/* The DGROUP is allocated by MODULE_CreateInstance */
if (i == pModule->dgroup) continue;
pSegment->selector = GLOBAL_Alloc( MODULE_Ne2MemFlags(pSegment->flags),
minsize, hModule,
!(pSegment->flags & NE_SEGFLAGS_DATA),
FALSE,
FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
if (!pSegment->selector) return FALSE;
}
pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
(pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;
return TRUE;
}
#endif
/***********************************************************************
* MODULE_GetInstance
*/
#ifndef WINELIB32
static HINSTANCE MODULE_GetInstance( HMODULE hModule )
{
SEGTABLEENTRY *pSegment;
NE_MODULE *pModule;
if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
if (pModule->dgroup == 0) return hModule;
pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
return pSegment->selector;
}
#endif
/***********************************************************************
* MODULE_CreateInstance
*/
HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
{
SEGTABLEENTRY *pSegment;
NE_MODULE *pModule;
int minsize;
HINSTANCE hNewInstance, hPrevInstance;
if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
if (pModule->dgroup == 0) return hModule;
pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
hPrevInstance = pSegment->selector;
/* if it's a library, create a new instance only the first time */
if (hPrevInstance)
{
if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
if (params == (LOADPARAMS*)-1) return hPrevInstance;
}
minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
minsize += pModule->heap_size;
hNewInstance = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
minsize, hModule, FALSE, FALSE, FALSE );
if (!hNewInstance) return 0;
pSegment->selector = hNewInstance;
return hNewInstance;
}
/***********************************************************************
* MODULE_LoadExeHeader
*/
HMODULE MODULE_LoadExeHeader( HFILE hFile, OFSTRUCT *ofs )
{
struct mz_header_s mz_header;
struct ne_header_s ne_header;
int size;
HMODULE hModule;
NE_MODULE *pModule;
BYTE *pData;
char *buffer, *fastload = NULL;
int fastload_offset = 0, fastload_length = 0;
/* Read a block from either the file or the fast-load area. */
#define READ(offset,size,buffer) \
((fastload && ((offset) >= fastload_offset) && \
((offset)+(size) <= fastload_offset+fastload_length)) ? \
(memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
(_llseek( hFile, mz_header.ne_offset+(offset), SEEK_SET), \
FILE_Read( hFile, (buffer), (size) ) == (size)))
_llseek( hFile, 0, SEEK_SET );
if ((FILE_Read(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
(mz_header.mz_magic != MZ_SIGNATURE)) return (HMODULE)11; /* invalid exe */
_llseek( hFile, mz_header.ne_offset, SEEK_SET );
if (FILE_Read( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
return (HMODULE)11; /* invalid exe */
if (ne_header.ne_magic == PE_SIGNATURE) return (HMODULE)21; /* win32 exe */
if (ne_header.ne_magic != NE_SIGNATURE) return (HMODULE)11; /* invalid exe */
/* We now have a valid NE header */
size = sizeof(NE_MODULE) +
/* loaded file info */
sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1+
/* segment table */
ne_header.n_segment_tab * sizeof(SEGTABLEENTRY) +
/* resource table */
ne_header.rname_tab_offset - ne_header.resource_tab_offset +
/* resident names table */
ne_header.moduleref_tab_offset - ne_header.rname_tab_offset +
/* module ref table */
ne_header.n_mod_ref_tab * sizeof(WORD) +
/* imported names table */
ne_header.entry_tab_offset - ne_header.iname_tab_offset +
/* entry table length */
ne_header.entry_tab_length;
hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, size );
if (!hModule) return (HMODULE)11; /* invalid exe */
FarSetOwner( hModule, hModule );
pModule = (NE_MODULE *)GlobalLock( hModule );
memcpy( pModule, &ne_header, sizeof(ne_header) );
pModule->count = 0;
pModule->pe_module = NULL;
pModule->self = hModule;
pModule->self_loading_sel = 0;
pData = (BYTE *)(pModule + 1);
/* Clear internal Wine flags in case they are set in the EXE file */
pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
/* Read the fast-load area */
if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
{
fastload_offset=ne_header.fastload_offset<<ne_header.align_shift_count;
fastload_length=ne_header.fastload_length<<ne_header.align_shift_count;
dprintf_module( stddeb, "Using fast-load area offset=%x len=%d\n",
fastload_offset, fastload_length );
if ((fastload = (char *)malloc( fastload_length )) != NULL)
{
_llseek( hFile, mz_header.ne_offset + fastload_offset, SEEK_SET );
if (FILE_Read( hFile, fastload, fastload_length ) != fastload_length)
{
free( fastload );
fastload = NULL;
}
}
}
/* Store the filename information */
pModule->fileinfo = (int)pData - (int)pModule;
size = sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
memcpy( pData, ofs, size );
((OFSTRUCT *)pData)->cBytes = size - 1;
pData += size;
/* Get the segment table */
pModule->seg_table = (int)pData - (int)pModule;
buffer = malloc( ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s) );
if (buffer)
{
int i;
struct ne_segment_table_entry_s *pSeg;
if (!READ( ne_header.segment_tab_offset,
ne_header.n_segment_tab * sizeof(struct ne_segment_table_entry_s),
buffer )) return (HMODULE)11; /* invalid exe */
pSeg = (struct ne_segment_table_entry_s *)buffer;
for (i = ne_header.n_segment_tab; i > 0; i--, pSeg++)
{
memcpy( pData, pSeg, sizeof(*pSeg) );
pData += sizeof(SEGTABLEENTRY);
}
free( buffer );
}
else
{
GlobalFree( hModule );
return (HMODULE)11; /* invalid exe */
}
/* Get the resource table */
if (ne_header.resource_tab_offset < ne_header.rname_tab_offset)
{
pModule->res_table = (int)pData - (int)pModule;
if (!READ(ne_header.resource_tab_offset,
ne_header.rname_tab_offset - ne_header.resource_tab_offset,
pData )) return (HMODULE)11; /* invalid exe */
pData += ne_header.rname_tab_offset - ne_header.resource_tab_offset;
}
else pModule->res_table = 0; /* No resource table */
/* Get the resident names table */
pModule->name_table = (int)pData - (int)pModule;
if (!READ( ne_header.rname_tab_offset,
ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
pData ))
{
GlobalFree( hModule );
return (HMODULE)11; /* invalid exe */
}
pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
/* Get the module references table */
if (ne_header.n_mod_ref_tab > 0)
{
pModule->modref_table = (int)pData - (int)pModule;
if (!READ( ne_header.moduleref_tab_offset,
ne_header.n_mod_ref_tab * sizeof(WORD),
pData )) return (HMODULE)11; /* invalid exe */
pData += ne_header.n_mod_ref_tab * sizeof(WORD);
}
else pModule->modref_table = 0; /* No module references */
/* Get the imported names table */
pModule->import_table = (int)pData - (int)pModule;
if (!READ( ne_header.iname_tab_offset,
ne_header.entry_tab_offset - ne_header.iname_tab_offset,
pData ))
{
GlobalFree( hModule );
return (HMODULE)11; /* invalid exe */
}
pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
/* Get the entry table */
pModule->entry_table = (int)pData - (int)pModule;
if (!READ( ne_header.entry_tab_offset,
ne_header.entry_tab_length,
pData ))
{
GlobalFree( hModule );
return (HMODULE)11; /* invalid exe */
}
pData += ne_header.entry_tab_length;
/* Get the non-resident names table */
if (ne_header.nrname_tab_length)
{
pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
hModule, FALSE, FALSE, FALSE );
if (!pModule->nrname_handle)
{
GlobalFree( hModule );
return (HMODULE)11; /* invalid exe */
}
buffer = GlobalLock( pModule->nrname_handle );
_llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length )
!= ne_header.nrname_tab_length)
{
GlobalFree( pModule->nrname_handle );
GlobalFree( hModule );
return (HMODULE)11; /* invalid exe */
}
}
else pModule->nrname_handle = 0;
/* Allocate a segment for the implicitly-loaded DLLs */
if (pModule->modref_count)
{
pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
(pModule->modref_count+1)*sizeof(HMODULE),
hModule, FALSE, FALSE, FALSE );
if (!pModule->dlls_to_init)
{
if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
GlobalFree( hModule );
return (HMODULE)11; /* invalid exe */
}
}
else pModule->dlls_to_init = 0;
pModule->next = hFirstModule;
hFirstModule = hModule;
return hModule;
#undef READ
}
/***********************************************************************
* MODULE_GetOrdinal
*
* Lookup the ordinal for a given name.
*/
WORD MODULE_GetOrdinal( HMODULE hModule, const char *name )
{
char buffer[256], *cpnt;
BYTE len;
NE_MODULE *pModule;
if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
hModule, name );
/* First handle names of the form '#xxxx' */
if (name[0] == '#') return atoi( name + 1 );
/* Now copy and uppercase the string */
strcpy( buffer, name );
AnsiUpper( buffer );
len = strlen( buffer );
/* First search the resident names */
cpnt = (char *)pModule + pModule->name_table;
/* Skip the first entry (module name) */
cpnt += *cpnt + 1 + sizeof(WORD);
while (*cpnt)
{
if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
{
dprintf_module( stddeb, " Found: ordinal=%d\n",
*(WORD *)(cpnt + *cpnt + 1) );
return *(WORD *)(cpnt + *cpnt + 1);
}
cpnt += *cpnt + 1 + sizeof(WORD);
}
/* Now search the non-resident names table */
if (!pModule->nrname_handle) return 0; /* No non-resident table */
cpnt = (char *)GlobalLock( pModule->nrname_handle );
/* Skip the first entry (module description string) */
cpnt += *cpnt + 1 + sizeof(WORD);
while (*cpnt)
{
if (((BYTE)*cpnt == len) && !memcmp( cpnt+1, buffer, len ))
{
dprintf_module( stddeb, " Found: ordinal=%d\n",
*(WORD *)(cpnt + *cpnt + 1) );
return *(WORD *)(cpnt + *cpnt + 1);
}
cpnt += *cpnt + 1 + sizeof(WORD);
}
return 0;
}
/***********************************************************************
* MODULE_GetEntryPoint
*
* Return the entry point for a given ordinal.
*/
SEGPTR MODULE_GetEntryPoint( HMODULE hModule, WORD ordinal )
{
NE_MODULE *pModule;
WORD curOrdinal = 1;
BYTE *p;
WORD sel, offset;
if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
p = (BYTE *)pModule + pModule->entry_table;
while (*p && (curOrdinal + *p <= ordinal))
{
/* Skipping this bundle */
curOrdinal += *p;
switch(p[1])
{
case 0: p += 2; break; /* unused */
case 0xff: p += 2 + *p * 6; break; /* moveable */
default: p += 2 + *p * 3; break; /* fixed */
}
}
if (!*p) return 0;
switch(p[1])
{
case 0: /* unused */
return 0;
case 0xff: /* moveable */
p += 2 + 6 * (ordinal - curOrdinal);
sel = p[3];
offset = *(WORD *)(p + 4);
break;
default: /* fixed */
sel = p[1];
p += 2 + 3 * (ordinal - curOrdinal);
offset = *(WORD *)(p + 1);
break;
}
if (sel == 0xfe) sel = 0xffff; /* constant entry */
else sel = (WORD)(DWORD)NE_SEG_TABLE(pModule)[sel-1].selector;
return (SEGPTR)MAKELONG( offset, sel );
}
/***********************************************************************
* MODULE_SetEntryPoint
*
* Change the value of an entry point. Use with caution!
* It can only change the offset value, not the selector.
*/
BOOL MODULE_SetEntryPoint( HMODULE hModule, WORD ordinal, WORD offset )
{
NE_MODULE *pModule;
WORD curOrdinal = 1;
BYTE *p;
if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
p = (BYTE *)pModule + pModule->entry_table;
while (*p && (curOrdinal + *p <= ordinal))
{
/* Skipping this bundle */
curOrdinal += *p;
switch(p[1])
{
case 0: p += 2; break; /* unused */
case 0xff: p += 2 + *p * 6; break; /* moveable */
default: p += 2 + *p * 3; break; /* fixed */
}
}
if (!*p) return FALSE;
switch(p[1])
{
case 0: /* unused */
return FALSE;
case 0xff: /* moveable */
p += 2 + 6 * (ordinal - curOrdinal);
*(WORD *)(p + 4) = offset;
break;
default: /* fixed */
p += 2 + 3 * (ordinal - curOrdinal);
*(WORD *)(p + 1) = offset;
break;
}
return TRUE;
}
/***********************************************************************
* MODULE_GetEntryPointName
*
* Return the entry point name for a given ordinal.
* Used only by relay debugging.
* Warning: returned pointer is to a Pascal-type string.
*/
LPSTR MODULE_GetEntryPointName( HMODULE hModule, WORD ordinal )
{
register char *cpnt;
NE_MODULE *pModule;
if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
/* First search the resident names */
cpnt = (char *)pModule + pModule->name_table;
while (*cpnt)
{
cpnt += *cpnt + 1 + sizeof(WORD);
if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
}
/* Now search the non-resident names table */
if (!pModule->nrname_handle) return 0; /* No non-resident table */
cpnt = (char *)GlobalLock( pModule->nrname_handle );
while (*cpnt)
{
cpnt += *cpnt + 1 + sizeof(WORD);
if (*(WORD *)(cpnt + *cpnt + 1) == ordinal) return cpnt;
}
return NULL;
}
/***********************************************************************
* MODULE_GetWndProcEntry16 (not a Windows API function)
*
* Return an entry point from the WINPROCS dll.
*/
#ifndef WINELIB
WNDPROC MODULE_GetWndProcEntry16( const char *name )
{
WORD ordinal;
static HMODULE hModule = 0;
if (!hModule) hModule = GetModuleHandle( "WINPROCS" );
ordinal = MODULE_GetOrdinal( hModule, name );
return MODULE_GetEntryPoint( hModule, ordinal );
}
#endif
/***********************************************************************
* MODULE_GetWndProcEntry32 (not a Windows API function)
*
* Return an entry point from the WINPROCS32 dll.
*/
#ifndef WINELIB
WNDPROC MODULE_GetWndProcEntry32( const char *name )
{
static HMODULE hModule = 0;
if (!hModule) hModule = GetModuleHandle( "WINPROCS32" );
return PE_GetProcAddress( hModule, name );
}
#endif
/***********************************************************************
* MODULE_GetModuleName
*/
LPSTR MODULE_GetModuleName( HMODULE hModule )
{
NE_MODULE *pModule;
BYTE *p, len;
static char buffer[10];
if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
p = (BYTE *)pModule + pModule->name_table;
len = MIN( *p, 8 );
memcpy( buffer, p + 1, len );
buffer[len] = '\0';
return buffer;
}
/**********************************************************************
* MODULE_RegisterModule
*/
void MODULE_RegisterModule( HMODULE hModule )
{
NE_MODULE *pModule = MODULE_GetPtr( hModule );
pModule->next = hFirstModule;
hFirstModule = hModule;
}
/**********************************************************************
* MODULE_FindModule
*
* Find a module from a path name.
*/
HMODULE MODULE_FindModule( LPCSTR path )
{
HMODULE hModule = hFirstModule;
LPCSTR filename, dotptr, modulepath, modulename;
BYTE len, *name_table;
if (!(filename = strrchr( path, '\\' ))) filename = path;
else filename++;
if ((dotptr = strrchr( filename, '.' )) != NULL)
len = (BYTE)(dotptr - filename);
else len = strlen( filename );
while(hModule)
{
NE_MODULE *pModule = MODULE_GetPtr( hModule );
if (!pModule) break;
modulepath = NE_MODULE_NAME(pModule);
if (!(modulename = strrchr( modulepath, '\\' )))
modulename = modulepath;
else modulename++;
if (!lstrcmpi( modulename, filename )) return hModule;
name_table = (BYTE *)pModule + pModule->name_table;
if ((*name_table == len) && !lstrncmpi(filename, name_table+1, len))
return hModule;
hModule = pModule->next;
}
return 0;
}
/**********************************************************************
* MODULE_FreeModule
*
* Remove a module from memory.
*/
static void MODULE_FreeModule( HMODULE hModule )
{
HMODULE *hPrevModule;
NE_MODULE *pModule;
SEGTABLEENTRY *pSegment;
HMODULE *pModRef;
int i;
if (!(pModule = MODULE_GetPtr( hModule ))) return;
if (pModule->flags & NE_FFLAGS_BUILTIN)
return; /* Can't free built-in module */
/* FIXME: should call the exit code for the library here */
/* Clear magic number just in case */
pModule->magic = pModule->self = 0;
/* Remove it from the linked list */
hPrevModule = &hFirstModule;
while (*hPrevModule && (*hPrevModule != hModule))
{
hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
}
if (*hPrevModule) *hPrevModule = pModule->next;
/* Free all the segments */
pSegment = NE_SEG_TABLE( pModule );
for (i = 1; i <= pModule->seg_count; i++, pSegment++)
{
GlobalFree( pSegment->selector );
}
/* Free the referenced modules */
pModRef = (HMODULE*)NE_MODULE_TABLE( pModule );
for (i = 0; i < pModule->modref_count; i++, pModRef++)
{
FreeModule( *pModRef );
}
/* Free the module storage */
if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
if (pModule->dlls_to_init) GlobalFree( pModule->dlls_to_init );
GlobalFree( hModule );
/* Remove module from cache */
if (hCachedModule == hModule) hCachedModule = 0;
}
/**********************************************************************
* LoadModule (KERNEL.45)
*/
HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
{
HMODULE hModule;
HANDLE hInstance, hPrevInstance;
NE_MODULE *pModule;
LOADPARAMS *params = (LOADPARAMS *)paramBlock;
#ifndef WINELIB
WORD *pModRef, *pDLLs;
HFILE hFile;
int i;
hModule = MODULE_FindModule( name );
if (!hModule) /* We have to load the module */
{
OFSTRUCT ofs;
/* Try to load the built-in first if not disabled */
if ((hModule = MODULE_LoadBuiltin( name, FALSE ))) return hModule;
if ((hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR)
{
/* Now try the built-in even if disabled */
if ((hModule = MODULE_LoadBuiltin( name, TRUE )))
{
fprintf( stderr, "Warning: could not load Windows DLL '%s', using built-in module.\n", name );
return hModule;
}
return 2; /* File not found */
}
/* Create the module structure */
hModule = MODULE_LoadExeHeader( hFile, &ofs );
if (hModule < 32)
{
/* FIXME: Hack because PE_LoadModule is recursive */
int fd = dup( FILE_GetUnixHandle(hFile) );
_lclose( hFile );
if (hModule == 21) hModule = PE_LoadModule( fd, &ofs, paramBlock );
close( fd );
if (hModule < 32)
fprintf( stderr, "LoadModule: can't load '%s', error=%d\n",
name, hModule );
return hModule;
}
_lclose( hFile );
pModule = MODULE_GetPtr( hModule );
/* Allocate the segments for this module */
MODULE_CreateSegments( hModule );
hPrevInstance = 0;
hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
/* Load the referenced DLLs */
pModRef = (WORD *)((char *)pModule + pModule->modref_table);
pDLLs = (WORD *)GlobalLock( pModule->dlls_to_init );
for (i = 0; i < pModule->modref_count; i++, pModRef++)
{
char buffer[256];
BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
memcpy( buffer, pstr + 1, *pstr );
strcpy( buffer + *pstr, ".dll" );
dprintf_module( stddeb, "Loading '%s'\n", buffer );
if (!(*pModRef = MODULE_FindModule( buffer )))
{
/* If the DLL is not loaded yet, load it and store */
/* its handle in the list of DLLs to initialize. */
HMODULE hDLL;
if ((hDLL = LoadModule( buffer, (LPVOID)-1 )) == 2) /* file not found */
{
char *p;
/* Try with prepending the path of the current module */
GetModuleFileName( hModule, buffer, 256 );
if (!(p = strrchr( buffer, '\\' ))) p = buffer;
memcpy( p + 1, pstr + 1, *pstr );
strcpy( p + 1 + *pstr, ".dll" );
hDLL = LoadModule( buffer, (LPVOID)-1 );
}
if (hDLL < 32)
{
fprintf( stderr, "Could not load '%s' required by '%s', error = %d\n",
buffer, name, hDLL );
return 2; /* file not found */
}
*pModRef = GetExePtr( hDLL );
*pDLLs++ = *pModRef;
}
else /* Increment the reference count of the DLL */
{
NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
if (pOldDLL) pOldDLL->count++;
}
}
/* Load the segments */
if (pModule->flags & NE_FFLAGS_SELFLOAD)
{
int fd;
/* Handle self loading modules */
SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
SELFLOADHEADER *selfloadheader;
HMODULE hselfload = GetModuleHandle("WINPROCS");
WORD oldss, oldsp, saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
fprintf (stderr, "Warning: %*.*s is a self-loading module\n"
"Support for self-loading modules is very experimental\n",
*((BYTE*)pModule + pModule->name_table),
*((BYTE*)pModule + pModule->name_table),
(char *)pModule + pModule->name_table + 1);
NE_LoadSegment( hModule, 1 );
selfloadheader = (SELFLOADHEADER *)
PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
selfloadheader->EntryAddrProc =
MODULE_GetEntryPoint(hselfload,27);
selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle("KERNEL"),403);
pModule->self_loading_sel = GlobalHandleToSel(
GLOBAL_Alloc (GMEM_ZEROINIT,
0xFF00, hModule, FALSE, FALSE, FALSE)
);
oldss = IF1632_Saved16_ss;
oldsp = IF1632_Saved16_sp;
IF1632_Saved16_ss = pModule->self_loading_sel;
IF1632_Saved16_sp = 0xFF00;
if (!IF1632_Stack32_base) {
STACK32FRAME* frame32;
char *stack32Top;
/* Setup an initial 32 bit stack frame */
hInitialStack32 = GLOBAL_Alloc( GMEM_FIXED, 0x10000,
hModule, FALSE, FALSE,
FALSE );
/* Create the 32-bit stack frame */
*(DWORD *)GlobalLock(hInitialStack32) = 0xDEADBEEF;
stack32Top = (char*)GlobalLock(hInitialStack32) +
0x10000;
frame32 = (STACK32FRAME *)stack32Top - 1;
frame32->saved_esp = (DWORD)stack32Top;
frame32->edi = 0;
frame32->esi = 0;
frame32->edx = 0;
frame32->ecx = 0;
frame32->ebx = 0;
frame32->ebp = 0;
frame32->retaddr = 0;
frame32->codeselector = WINE_CODE_SELECTOR;
/* pTask->esp = (DWORD)frame32; */
IF1632_Stack32_base = WIN16_GlobalLock(hInitialStack32);
}
/* FIXME: we probably need a DOS handle here */
fd = MODULE_OpenFile( hModule );
CallTo16_word_ww (selfloadheader->BootApp,
pModule->self_loading_sel, hModule, fd);
/* some BootApp procs overwrite the selector of dgroup */
pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
IF1632_Saved16_ss = oldss;
IF1632_Saved16_sp = oldsp;
for (i = 2; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
if (hInitialStack32){
GlobalUnlock (hInitialStack32);
GlobalFree (hInitialStack32);
IF1632_Stack32_base = hInitialStack32 = 0;
}
}
else
{
for (i = 1; i <= pModule->seg_count; i++)
NE_LoadSegment( hModule, i );
}
/* Fixup the functions prologs */
NE_FixupPrologs( pModule );
/* Make sure the usage count is 1 on the first loading of */
/* the module, even if it contains circular DLL references */
pModule->count = 1;
}
else
{
pModule = MODULE_GetPtr( hModule );
hPrevInstance = MODULE_GetInstance( hModule );
hInstance = MODULE_CreateInstance( hModule, params );
if (hInstance != hPrevInstance) /* not a library */
NE_LoadSegment( hModule, pModule->dgroup );
pModule->count++;
}
#else
hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE) );
pModule = (NE_MODULE *)GlobalLock( hModule );
pModule->count = 1;
pModule->magic = NE_SIGNATURE;
pModule->self = hModule;
hPrevInstance = 0;
hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
#endif /* WINELIB */
/* Create a task for this instance */
if (!(pModule->flags & NE_FFLAGS_LIBMODULE) && (paramBlock != (LPVOID)-1))
{
TASK_CreateTask( hModule, hInstance, hPrevInstance,
params->hEnvironment,
(LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
*((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) );
}
return hInstance;
}
/**********************************************************************
* FreeModule (KERNEL.46)
*/
BOOL FreeModule( HANDLE hModule )
{
NE_MODULE *pModule;
hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
dprintf_module( stddeb, "FreeModule: %s count %d\n",
MODULE_GetModuleName(hModule), pModule->count );
if (--pModule->count == 0) MODULE_FreeModule( hModule );
return TRUE;
}
/**********************************************************************
* GetModuleHandle (KERNEL.47)
*/
HMODULE WIN16_GetModuleHandle( SEGPTR name )
{
if (HIWORD(name) == 0) return GetExePtr( (HANDLE)name );
return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
}
HMODULE GetModuleHandle( LPCSTR name )
{
return MODULE_FindModule( name );
}
/**********************************************************************
* GetModuleUsage (KERNEL.48)
*/
int GetModuleUsage( HANDLE hModule )
{
NE_MODULE *pModule;
hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
hModule, pModule->count );
return pModule->count;
}
/**********************************************************************
* GetModuleFileName (KERNEL.49)
*/
int GetModuleFileName( HANDLE hModule, LPSTR lpFileName, short nSize )
{
NE_MODULE *pModule;
hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
lstrcpyn( lpFileName, NE_MODULE_NAME(pModule), nSize );
dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
return strlen(lpFileName);
}
/***********************************************************************
* LoadLibrary (KERNEL.95)
*/
HANDLE LoadLibrary( LPCSTR libname )
{
#ifdef WINELIB
dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
WINELIB_UNIMP("LoadLibrary()");
return (HANDLE)0;
#else
HANDLE handle;
dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
/* This does not increment the module reference count, and will
* therefore cause crashes on FreeLibrary calls.
if ((handle = MODULE_FindModule( libname )) != 0) return handle;
*/
handle = LoadModule( libname, (LPVOID)-1 );
if (handle == (HANDLE)2) /* file not found */
{
char buffer[256];
lstrcpyn( buffer, libname, 252 );
strcat( buffer, ".dll" );
handle = LoadModule( buffer, (LPVOID)-1 );
}
if (handle >= (HANDLE)32) NE_InitializeDLLs( GetExePtr(handle) );
return handle;
#endif
}
/***********************************************************************
* FreeLibrary (KERNEL.96)
*/
void FreeLibrary( HANDLE handle )
{
dprintf_module( stddeb,"FreeLibrary: %04x\n", handle );
FreeModule( handle );
}
/***********************************************************************
* WinExec (KERNEL.166)
*/
HANDLE WinExec( LPSTR lpCmdLine, WORD nCmdShow )
{
LOADPARAMS params;
HLOCAL cmdShowHandle, cmdLineHandle;
HANDLE handle;
WORD *cmdShowPtr;
char *p, *cmdline, filename[256];
static int use_load_module = 1;
if (!(cmdShowHandle = GlobalAlloc( 0, 2 * sizeof(WORD) ))) return 0;
if (!(cmdLineHandle = GlobalAlloc( 0, 256 ))) return 0;
/* Store nCmdShow */
cmdShowPtr = (WORD *)GlobalLock( cmdShowHandle );
cmdShowPtr[0] = 2;
cmdShowPtr[1] = nCmdShow;
/* Build the filename and command-line */
cmdline = (char *)GlobalLock( cmdLineHandle );
lstrcpyn( filename, lpCmdLine, sizeof(filename) - 4 /* for extension */ );
for (p = filename; *p && (*p != ' ') && (*p != '\t'); p++);
if (*p) lstrcpyn( cmdline, p + 1, 128 );
else cmdline[0] = '\0';
*p = '\0';
/* Now load the executable file */
if (use_load_module)
{
#ifdef WINELIB
/* WINELIB: Use LoadModule() only for the program itself */
use_load_module = 0;
params.hEnvironment = (HANDLE)GetDOSEnvironment();
#else
params.hEnvironment = (HANDLE)SELECTOROF( GetDOSEnvironment() );
#endif /* WINELIB */
params.cmdLine = (SEGPTR)WIN16_GlobalLock( cmdLineHandle );
params.showCmd = (SEGPTR)WIN16_GlobalLock( cmdShowHandle );
params.reserved = 0;
handle = LoadModule( filename, &params );
if (handle == 2) /* file not found */
{
/* Check that the original file name did not have a suffix */
p = strrchr(filename, '.');
if (!p || (strchr(p, '/') && strchr(p, '\\')))
{
p = filename + strlen(filename);
strcpy( p, ".exe" );
handle = LoadModule( filename, &params );
*p = '\0'; /* Remove extension */
}
}
}
else handle = 2;
if (handle < 32)
{
/* Try to start it as a unix program */
if (!fork())
{
/* Child process */
const char *unixfilename;
const char *argv[256], **argptr;
int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
nCmdShow == SW_SHOWMINNOACTIVE);
/* get unixfilename */
if (strchr(filename, '/') ||
strchr(filename, ':') ||
strchr(filename, '\\'))
unixfilename = DOSFS_GetUnixFileName(filename, 1);
else unixfilename = filename;
if (unixfilename)
{
/* build argv */
argptr = argv;
if (iconic) *argptr++ = "-iconic";
*argptr++ = unixfilename;
p = cmdline;
while (1)
{
while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
if (!*p) break;
*argptr++ = p;
while (*p && *p != ' ' && *p != '\t') p++;
}
*argptr++ = 0;
/* Execute */
execvp(argv[0], (char**)argv);
}
/* Failed ! */
#ifdef WINELIB
/* build argv */
argptr = argv;
*argptr++ = "wine";
if (iconic) *argptr++ = "-iconic";
*argptr++ = lpCmdLine;
*argptr++ = 0;
/* Execute */
execvp(argv[0] , (char**)argv);
/* Failed ! */
fprintf(stderr, "WinExec: can't exec 'wine %s'\n", lpCmdLine);
#endif
exit(1);
}
}
GlobalFree( cmdShowHandle );
GlobalFree( cmdLineHandle );
#if 0
if (handle < (HANDLE)32) /* Error? */
return handle;
/* FIXME: Yield never returns!
We may want to run more applications or start the debugger
before calling Yield. If we don't Yield will be called immdiately
after returning. Why is it needed for Word anyway? */
Yield(); /* program is executed immediately ....needed for word */
#endif
return handle;
}
/***********************************************************************
* GetProcAddress (KERNEL.50)
*/
FARPROC GetProcAddress( HANDLE hModule, SEGPTR name )
{
WORD ordinal;
SEGPTR ret;
if (!hModule) hModule = GetCurrentTask();
hModule = GetExePtr( hModule );
if (HIWORD(name) != 0)
{
ordinal = MODULE_GetOrdinal( hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
dprintf_module( stddeb, "GetProcAddress: %04x '%s'\n",
hModule, (LPSTR)PTR_SEG_TO_LIN(name) );
}
else
{
ordinal = LOWORD(name);
dprintf_module( stddeb, "GetProcAddress: %04x %04x\n",
hModule, ordinal );
}
if (!ordinal) return (FARPROC)0;
ret = MODULE_GetEntryPoint( hModule, ordinal );
dprintf_module( stddeb, "GetProcAddress: returning %08lx\n", (DWORD)ret );
return (FARPROC)ret;
}
/**********************************************************************
* GetExpWinVer (KERNEL.167)
*/
WORD GetExpWinVer( HMODULE hModule )
{
NE_MODULE *pModule = MODULE_GetPtr( hModule );
return pModule ? pModule->expected_version : 0;
}
/**********************************************************************
* ModuleFirst (TOOLHELP.59)
*/
BOOL ModuleFirst( MODULEENTRY *lpme )
{
lpme->wNext = hFirstModule;
return ModuleNext( lpme );
}
/**********************************************************************
* ModuleNext (TOOLHELP.60)
*/
BOOL ModuleNext( MODULEENTRY *lpme )
{
NE_MODULE *pModule;
if (!lpme->wNext) return FALSE;
if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
MAX_MODULE_NAME );
lpme->szModule[MAX_MODULE_NAME] = '\0';
lpme->hModule = lpme->wNext;
lpme->wcUsage = pModule->count;
strncpy( lpme->szExePath, NE_MODULE_NAME(pModule), MAX_PATH );
lpme->szExePath[MAX_PATH] = '\0';
lpme->wNext = pModule->next;
return TRUE;
}
/**********************************************************************
* ModuleFindName (TOOLHELP.61)
*/
BOOL ModuleFindName( MODULEENTRY *lpme, LPCSTR name )
{
lpme->wNext = GetModuleHandle( name );
return ModuleNext( lpme );
}
/**********************************************************************
* ModuleFindHandle (TOOLHELP.62)
*/
BOOL ModuleFindHandle( MODULEENTRY *lpme, HMODULE hModule )
{
hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
lpme->wNext = hModule;
return ModuleNext( lpme );
}