408 lines
9.3 KiB
C
408 lines
9.3 KiB
C
static char RCSId[] = "$Id: wine.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
|
||
static char Copyright[] = "Copyright Robert J. Amstadt, 1993";
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
#include <fcntl.h>
|
||
#include <unistd.h>
|
||
#include <string.h>
|
||
#include <errno.h>
|
||
#ifdef linux
|
||
#include <linux/unistd.h>
|
||
#include <linux/head.h>
|
||
#include <linux/ldt.h>
|
||
#include <linux/segment.h>
|
||
#endif
|
||
#include "neexe.h"
|
||
#include "segmem.h"
|
||
#include "prototypes.h"
|
||
#include "dlls.h"
|
||
#include "wine.h"
|
||
#include "windows.h"
|
||
#include "wineopts.h"
|
||
#include "arch.h"
|
||
#include "options.h"
|
||
|
||
/* #define DEBUG_FIXUP */
|
||
|
||
extern HANDLE CreateNewTask(HINSTANCE hInst);
|
||
extern int CallToInit16(unsigned long csip, unsigned long sssp,
|
||
unsigned short ds);
|
||
extern void CallTo32();
|
||
|
||
char *GetDosFileName(char *unixfilename);
|
||
char *GetModuleName(struct w_files * wpnt, int index, char *buffer);
|
||
extern unsigned char ran_out;
|
||
extern char WindowsPath[256];
|
||
char *WIN_ProgramName;
|
||
|
||
unsigned short WIN_StackSize;
|
||
unsigned short WIN_HeapSize;
|
||
|
||
struct w_files * wine_files = NULL;
|
||
|
||
char **Argv;
|
||
int Argc;
|
||
HINSTANCE hSysRes;
|
||
|
||
static char *DLL_Extensions[] = { "dll", NULL };
|
||
static char *EXE_Extensions[] = { "exe", NULL };
|
||
|
||
/**********************************************************************
|
||
* myerror
|
||
*/
|
||
void
|
||
myerror(const char *s)
|
||
{
|
||
if (s == NULL)
|
||
perror("wine");
|
||
else
|
||
fprintf(stderr, "wine: %s\n", s);
|
||
|
||
exit(1);
|
||
}
|
||
|
||
/**********************************************************************
|
||
* GetFilenameFromInstance
|
||
*/
|
||
char *
|
||
GetFilenameFromInstance(unsigned short instance)
|
||
{
|
||
register struct w_files *w = wine_files;
|
||
|
||
while (w && w->hinstance != instance)
|
||
w = w->next;
|
||
|
||
if (w)
|
||
return w->filename;
|
||
else
|
||
return NULL;
|
||
}
|
||
|
||
struct w_files *
|
||
GetFileInfo(unsigned short instance)
|
||
{
|
||
register struct w_files *w = wine_files;
|
||
|
||
while (w && w->hinstance != instance)
|
||
w = w->next;
|
||
|
||
return w;
|
||
}
|
||
|
||
#ifndef WINELIB
|
||
/**********************************************************************
|
||
*
|
||
* Load MZ Header
|
||
*/
|
||
void load_mz_header(int fd, struct mz_header_s *mz_header)
|
||
{
|
||
if (read(fd, mz_header, sizeof(struct mz_header_s)) !=
|
||
sizeof(struct mz_header_s))
|
||
{
|
||
myerror("Unable to read MZ header from file");
|
||
}
|
||
}
|
||
#endif
|
||
|
||
int IsDLLLoaded(char *name)
|
||
{
|
||
struct w_files *wpnt;
|
||
|
||
if(FindDLLTable(name))
|
||
return 1;
|
||
|
||
for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
|
||
if(strcmp(wpnt->name, name) == 0)
|
||
return 1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**********************************************************************
|
||
* LoadImage
|
||
* Load one executable into memory
|
||
*/
|
||
HINSTANCE LoadImage(char *module, int filetype, int change_dir)
|
||
{
|
||
unsigned int read_size;
|
||
int i;
|
||
struct w_files * wpnt, *wpnt1;
|
||
unsigned int status;
|
||
char buffer[256], header[2], modulename[64], *fullname;
|
||
|
||
ExtractDLLName(module, modulename);
|
||
printf("%sLoadImage \n", module);
|
||
/* built-in one ? */
|
||
if (FindDLLTable(modulename)) {
|
||
return GetModuleHandle(modulename);
|
||
}
|
||
|
||
/* already loaded ? */
|
||
for (wpnt = wine_files ; wpnt ; wpnt = wpnt->next)
|
||
if (strcasecmp(wpnt->name, modulename) == 0)
|
||
return wpnt->hinstance;
|
||
|
||
/*
|
||
* search file
|
||
*/
|
||
fullname = FindFile(buffer, sizeof(buffer), module,
|
||
(filetype == EXE ? EXE_Extensions : DLL_Extensions),
|
||
WindowsPath);
|
||
if (fullname == NULL)
|
||
{
|
||
fprintf(stderr, "LoadImage: I can't find %s.dll | %s.exe !\n",
|
||
module, module);
|
||
return 2;
|
||
}
|
||
|
||
fullname = GetDosFileName(fullname);
|
||
WIN_ProgramName = strdup(fullname);
|
||
|
||
fprintf(stderr,"LoadImage: loading %s (%s)\n [%s]\n",
|
||
module, buffer, WIN_ProgramName);
|
||
|
||
if (change_dir && fullname)
|
||
{
|
||
char dirname[256];
|
||
char *p;
|
||
|
||
strcpy(dirname, fullname);
|
||
p = strrchr(dirname, '\\');
|
||
*p = '\0';
|
||
|
||
DOS_SetDefaultDrive(dirname[0] - 'A');
|
||
DOS_ChangeDir(dirname[0] - 'A', dirname + 2);
|
||
}
|
||
|
||
/* First allocate a spot to store the info we collect, and add it to
|
||
* our linked list.
|
||
*/
|
||
|
||
wpnt = (struct w_files *) malloc(sizeof(struct w_files));
|
||
if(wine_files == NULL)
|
||
wine_files = wpnt;
|
||
else {
|
||
wpnt1 = wine_files;
|
||
while(wpnt1->next) wpnt1 = wpnt1->next;
|
||
wpnt1->next = wpnt;
|
||
};
|
||
wpnt->next = NULL;
|
||
wpnt->resnamtab = (RESNAMTAB *) -1;
|
||
|
||
/*
|
||
* Open file for reading.
|
||
*/
|
||
wpnt->fd = open(buffer, O_RDONLY);
|
||
if (wpnt->fd < 0)
|
||
return 2;
|
||
|
||
/*
|
||
* Establish header pointers.
|
||
*/
|
||
wpnt->filename = strdup(buffer);
|
||
wpnt->name = strdup(modulename);
|
||
|
||
/* if(module) {
|
||
wpnt->name = strdup(module);
|
||
ToDos(wpnt->name);
|
||
}*/
|
||
|
||
/* read mz header */
|
||
wpnt->mz_header = (struct mz_header_s *) malloc(sizeof(struct mz_header_s));;
|
||
status = lseek(wpnt->fd, 0, SEEK_SET);
|
||
load_mz_header (wpnt->fd, wpnt->mz_header);
|
||
if (wpnt->mz_header->must_be_0x40 != 0x40 &&
|
||
wpnt->mz_header->must_be_0x40 != 0x1e)
|
||
myerror("This is not a Windows program");
|
||
|
||
/* read first two bytes to determine filetype */
|
||
status = lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
|
||
read(wpnt->fd, &header, sizeof(header));
|
||
|
||
if (header[0] == 'N' && header[1] == 'E')
|
||
return (LoadNEImage(wpnt));
|
||
|
||
if (header[0] == 'P' && header[1] == 'E') {
|
||
printf("win32 applications are not supported");
|
||
return 14;
|
||
}
|
||
|
||
fprintf(stderr, "wine: (%s) unknown fileformat !\n", wpnt->filename);
|
||
|
||
return 14;
|
||
}
|
||
|
||
#ifndef WINELIB
|
||
/**********************************************************************
|
||
* main
|
||
*/
|
||
int _WinMain(int argc, char **argv)
|
||
{
|
||
int segment;
|
||
char *p;
|
||
char *sysresname;
|
||
char filename[256];
|
||
HANDLE hTaskMain;
|
||
HINSTANCE hInstMain;
|
||
#ifdef WINESTAT
|
||
char * cp;
|
||
#endif
|
||
struct w_files * wpnt;
|
||
int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
|
||
int rv;
|
||
|
||
Argc = argc - 1;
|
||
Argv = argv + 1;
|
||
|
||
if (strchr(Argv[0], '\\') || strchr(Argv[0],'/')) {
|
||
for (p = Argv[0] + strlen(Argv[0]); *p != '\\' && *p !='/'; p--)
|
||
/* NOTHING */;
|
||
|
||
strncpy(filename, Argv[0], p - Argv[0]);
|
||
filename[p - Argv[0]] = '\0';
|
||
strcat(WindowsPath, ";");
|
||
if (strchr(filename, '/'))
|
||
strcat(WindowsPath, GetDosFileName(filename));
|
||
else
|
||
strcat(WindowsPath, filename);
|
||
}
|
||
|
||
if ((hInstMain = LoadImage(Argv[0], EXE, 1)) < 32) {
|
||
fprintf(stderr, "wine: can't load %s!.\n", Argv[0]);
|
||
exit(1);
|
||
}
|
||
hTaskMain = CreateNewTask(hInstMain);
|
||
printf("_WinMain // hTaskMain=%04X hInstMain=%04X !\n", hTaskMain, hInstMain);
|
||
|
||
GetPrivateProfileString("wine", "SystemResources", "sysres.dll",
|
||
filename, sizeof(filename), WINE_INI);
|
||
|
||
hSysRes = LoadImage(filename, DLL, 0);
|
||
if (hSysRes < 32) {
|
||
fprintf(stderr, "wine: can't load %s!.\n", filename);
|
||
exit(1);
|
||
} else
|
||
printf("System Resources Loaded // hSysRes='%04X'\n", hSysRes);
|
||
|
||
/*
|
||
* Fixup references.
|
||
*/
|
||
/* wpnt = wine_files;
|
||
for(wpnt = wine_files; wpnt; wpnt = wpnt->next)
|
||
for (segment = 0; segment < wpnt->ne_header->n_segment_tab; segment++)
|
||
if (FixupSegment(wpnt, segment) < 0)
|
||
myerror("fixup failed.");
|
||
*/
|
||
|
||
#ifdef WINESTAT
|
||
cp = strrchr(argv[0], '/');
|
||
if(!cp) cp = argv[0];
|
||
else cp++;
|
||
if(strcmp(cp,"winestat") == 0) {
|
||
winestat();
|
||
exit(0);
|
||
};
|
||
#endif
|
||
|
||
/*
|
||
* Initialize signal handling.
|
||
*/
|
||
init_wine_signals();
|
||
|
||
/*
|
||
* Fixup stack and jump to start.
|
||
*/
|
||
WIN_StackSize = wine_files->ne_header->stack_length;
|
||
WIN_HeapSize = wine_files->ne_header->local_heap_length;
|
||
|
||
ds_reg = (wine_files->
|
||
selector_table[wine_files->ne_header->auto_data_seg-1].selector);
|
||
cs_reg = wine_files->selector_table[wine_files->ne_header->cs-1].selector;
|
||
ip_reg = wine_files->ne_header->ip;
|
||
ss_reg = wine_files->selector_table[wine_files->ne_header->ss-1].selector;
|
||
sp_reg = wine_files->ne_header->sp;
|
||
|
||
if (Options.debug) wine_debug(0, NULL);
|
||
|
||
rv = CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
|
||
printf ("rv = %x\n", rv);
|
||
}
|
||
|
||
void InitDLL(struct w_files *wpnt)
|
||
{
|
||
int cs_reg, ds_reg, ip_reg, rv;
|
||
/*
|
||
* Is this a library?
|
||
*/
|
||
if (wpnt->ne_header->format_flags & 0x8000)
|
||
{
|
||
if (!(wpnt->ne_header->format_flags & 0x0001))
|
||
{
|
||
/* Not SINGLEDATA */
|
||
fprintf(stderr, "Library is not marked SINGLEDATA\n");
|
||
exit(1);
|
||
}
|
||
|
||
ds_reg = wpnt->selector_table[wpnt->
|
||
ne_header->auto_data_seg-1].selector;
|
||
cs_reg = wpnt->selector_table[wpnt->ne_header->cs-1].selector;
|
||
ip_reg = wpnt->ne_header->ip;
|
||
|
||
if (cs_reg) {
|
||
fprintf(stderr, "Initializing %s, cs:ip %04x:%04x, ds %04x\n",
|
||
wpnt->name, cs_reg, ip_reg, ds_reg);
|
||
|
||
rv = CallTo16(cs_reg << 16 | ip_reg, ds_reg);
|
||
printf ("rv = %x\n", rv);
|
||
} else
|
||
printf("%s skipped\n", wpnt->name);
|
||
}
|
||
}
|
||
|
||
void InitializeLoadedDLLs(struct w_files *wpnt)
|
||
{
|
||
static flagReadyToRun = 0;
|
||
struct w_files *final_wpnt;
|
||
|
||
printf("InitializeLoadedDLLs %08X\n", wpnt);
|
||
|
||
if (wpnt == NULL)
|
||
{
|
||
flagReadyToRun = 1;
|
||
fprintf(stderr, "Initializing DLLs\n");
|
||
}
|
||
|
||
if (!flagReadyToRun)
|
||
return;
|
||
|
||
#if 1
|
||
if (wpnt != NULL)
|
||
fprintf(stderr, "Initializing %s\n", wpnt->name);
|
||
#endif
|
||
|
||
/*
|
||
* Initialize libraries
|
||
*/
|
||
if (!wpnt)
|
||
{
|
||
wpnt = wine_files;
|
||
final_wpnt = NULL;
|
||
}
|
||
else
|
||
{
|
||
final_wpnt = wpnt->next;
|
||
}
|
||
|
||
for( ; wpnt != final_wpnt; wpnt = wpnt->next)
|
||
InitDLL(wpnt);
|
||
}
|
||
#else /* #ifndef WINELIB */
|
||
void InitDLL(struct w_files *wpnt)
|
||
{
|
||
}
|
||
|
||
#endif /* #ifndef WINELIB */
|