Release 950606
Tue Jun 6 12:11:41 1995 Alexandre Julliard (julliard@sunsite.unc.edu)
* [controls/menu.c]
Fixed bug with drawing multi-column menus with vertical separator.
* [debugger/debug.l]
Fixed NULL-pointer reference after readline().
* [if1632/winprocs.spec] [miscemu/int21.c] [miscemu/interrupts.c]
Added interrupt vector emulation. Allows to retrieve an interrupt
vector and jump to it without crashing.
* [loader/ldt.c]
Moved ldt.c to memory directory.
* [loader/task.c]
Implemented LockCurrentTask() and GetInstanceData().
* [objects/bitblt.c]
Fixed a bug that caused StretchBlt() to use wrong colors when
stretching a monochrome bitmap to a color display.
* [objects/bitmap.c]
Fixed a segmented pointer bug in CreateBitmapIndirect().
* [tools/build.c]
Added possibility to have arguments for register functions; used
by interrupt vectors to remove the flags from the stack.
Generate a new function CallTo32_LargeStack(), that allows calling
a 32-bit function using the original 32-bit stack, for functions
that need more that 64k of stack.
Tue May 30 10:29:56 1995 Martin von Loewis <martin@informatik.hu-berlin.de>
* [if1632/shell.spec] [misc/shell.c]
DoEnvironmentSubst: fixed prototype
* [if1632/gdi.spec] [objects/palette.c]
SetSystemPaletteUse: new function
* [if1632/kernel.spec] [loader/resource.c]
DirectResAlloc: new function
* [if1632/user.spec] [windows/keyboard.c]
SetKeyboardState: new function
Mon May 29 12:58:28 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* [tools/build.c]
Prevent interrupts from destroying the args for a 32 bit function
by loading the correct value into %esp directly after %ss.
* [loader/ne_image.c] [loader/module.c]
The new instance must be created earlier in LoadModule(), so that
fixups referencing it will be handled correctly.
Initialize the local heap for a DGROUP in NE_LoadSegment().
* [objects/dib.c]
Like RLE8 bitmaps, RLE4 bitmaps don't always end with a proper code.
This used to crash Wine. Fixed.
* [objects/text.c]
Fix possible null pointer dereference in debugging output.
* [misc/commdlg.c]
Handle user input in the edit control better. Some bugs fixed.
* [memory/local.c]
Started implementing moveable blocks. This is unfinished (!), but
at least it does not seem to break things.
Wed May 24 13:26:36 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* [loader/module.c]
LoadModule(): DLLs occasionally have a data segment, and they work
much better if it is loaded :-)
LoadLibrary(): pass HMODULE instead of HINSTANCE to NE_InitializeDLLs.
FindModule(): also strip off the last backslash of the pathnames
(Winhelp tried to load C:\WINDOWS\SYSTEM\COMMDLG.DLL).
GetModuleHandle(): just call MODULE_FindModule, it does the same job,
only better.
* [loader/ne_image.c]
LocalInit() the heap of a DLL in NE_InitDLL. (This is probably
not really correct, it seems that all programs and DLLs try to do
this themselves. But they pass weird parameters.)
NE_InitializeDLLs should also call NE_InitDLL for the passed hModule.
* [loader/task.c] [misc/user.c]
Finish global initializations in InitTask instead of InitApp, or
all the DLLs will be initialized in InitTask without any available
window classes!
diff --git a/loader/Imakefile b/loader/Imakefile
index 9c15c28..befe47a 100644
--- a/loader/Imakefile
+++ b/loader/Imakefile
@@ -4,7 +4,6 @@
SRCS = \
dump.c \
- ldt.c \
main.c \
module.c \
ne_image.c \
diff --git a/loader/ldt.c b/loader/ldt.c
deleted file mode 100644
index 73e1260..0000000
--- a/loader/ldt.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * LDT manipulation functions
- *
- * Copyright 1993 Robert J. Amstadt
- * Copyright 1995 Alexandre Julliard
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <errno.h>
-#include "ldt.h"
-#include "stddebug.h"
-#include "debug.h"
-
-#ifndef WINELIB
-
-#ifdef linux
-#include <linux/unistd.h>
-#include <linux/head.h>
-#include <linux/ldt.h>
-
-_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
-#endif /* linux */
-
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#include <machine/segments.h>
-
-extern int i386_get_ldt(int, union descriptor *, int);
-extern int i386_set_ldt(int, union descriptor *, int);
-#endif /* __NetBSD__ || __FreeBSD__ */
-
-#endif /* ifndef WINELIB */
-
-
-/***********************************************************************
- * LDT_BytesToEntry
- *
- * Convert the raw bytes of the descriptor to an ldt_entry structure.
- */
-static void LDT_BytesToEntry( unsigned long *buffer, ldt_entry *content )
-{
- content->base = (*buffer >> 16) & 0x0000ffff;
- content->limit = *buffer & 0x0000ffff;
- buffer++;
- content->base |= (*buffer & 0xff000000) | ((*buffer << 16) & 0x00ff0000);
- content->limit |= (*buffer & 0x000f0000);
- content->type = (*buffer >> 10) & 3;
- content->seg_32bit = (*buffer & 0x00400000) != 0;
- content->read_only = (*buffer & 0x00000200) == 0;
- content->limit_in_pages = (*buffer & 0x00800000) != 0;
-}
-
-
-/***********************************************************************
- * LDT_GetEntry
- *
- * Retrieve an LDT entry.
- */
-int LDT_GetEntry( int entry, ldt_entry *content )
-{
- int ret = 0;
-
-#ifdef WINELIB
- content->base = ldt_copy[entry].base;
- content->limit = ldt_copy[entry].limit;
- content->type = SEGMENT_DATA;
- content->seg_32bit = 0;
- content->read_only = 0;
- content->limit_in_pages = 0;
-#else /* WINELIB */
-
-#ifdef linux
- int size = (entry + 1) * 2 * sizeof(long);
- long *buffer = (long *) malloc( size );
- ret = modify_ldt( 0, buffer, size );
- LDT_BytesToEntry( &buffer[entry*2], content );
- free( buffer );
-#endif /* linux */
-
-#if defined(__NetBSD__) || defined(__FreeBSD__)
- long buffer[2];
- ret = i386_get_ldt( entry, (union descriptor *)buffer, 1 );
- LDT_BytesToEntry( buffer, content );
-#endif /* __NetBSD__ || __FreeBSD__ */
-
-#endif /* WINELIB */
-
- return ret;
-}
-
-
-/***********************************************************************
- * LDT_SetEntry
- *
- * Set an LDT entry.
- */
-int LDT_SetEntry( int entry, ldt_entry *content )
-{
- int ret = 0;
-
- dprintf_ldt(stddeb,
- "LDT_SetEntry: entry=%04x base=%08lx limit=%05lx %s %d-bit flags=%c%c%c\n",
- entry, content->base, content->limit,
- content->limit_in_pages ? "pages" : "bytes",
- content->seg_32bit ? 32 : 16,
- content->read_only && (content->type & SEGMENT_CODE) ? '-' : 'r',
- content->read_only || (content->type & SEGMENT_CODE) ? '-' : 'w',
- (content->type & SEGMENT_CODE) ? 'x' : '-' );
-
-#ifndef WINELIB
-#ifdef linux
- {
- struct modify_ldt_ldt_s ldt_info;
-
- memset( &ldt_info, 0, sizeof(ldt_info) );
- ldt_info.entry_number = entry;
- ldt_info.base_addr = content->base;
- ldt_info.limit = content->limit;
- ldt_info.seg_32bit = content->seg_32bit != 0;
- ldt_info.contents = content->type;
- ldt_info.read_exec_only = content->read_only != 0;
- ldt_info.limit_in_pages = content->limit_in_pages != 0;
- ret = modify_ldt(1, &ldt_info, sizeof(ldt_info));
- }
-#endif /* linux */
-
-#if defined(__NetBSD__) || defined(__FreeBSD__)
- {
- long d[2];
-
- d[0] = ((content->base & 0x0000ffff) << 16) |
- (content->limit & 0x0ffff);
- d[1] = (content->base & 0xff000000) |
- ((content->base & 0x00ff0000)>>16) |
- (content->limit & 0xf0000) |
- (content->type << 10) |
- ((content->read_only == 0) << 9) |
- ((content->seg_32bit != 0) << 22) |
- ((content->limit_in_pages != 0) << 23) |
- 0xf000;
- ret = i386_set_ldt(entry, (union descriptor *)d, 1);
- if (ret < 0)
- {
- perror("i386_set_ldt");
- fprintf(stderr,
- "Did you reconfigure the kernel with \"options USER_LDT\"?\n");
- exit(1);
- }
- }
-#endif /* __NetBSD__ || __FreeBSD__ */
-#endif /* ifndef WINELIB */
-
- if (ret < 0) return ret;
- ldt_copy[entry].base = content->base;
- if (!content->limit_in_pages) ldt_copy[entry].limit = content->limit;
- else ldt_copy[entry].limit = (content->limit << 12) | 0x0fff;
- return ret;
-}
-
-
-/***********************************************************************
- * LDT_Print
- *
- * Print the content of the LDT on stdout.
- */
-void LDT_Print()
-{
- int i;
-
-#ifdef WINELIB
- for (i = 0; i < LDT_SIZE; i++)
- {
- if (ldt_copy[i].base || ldt_copy[i].limit)
- {
- fprintf( stderr, "%04x: sel=%04x base=%08x limit=%05x\n",
- i, ENTRY_TO_SELECTOR(i),
- ldt_copy[i].base, ldt_copy[i].limit );
- }
- }
-#else /* WINELIB */
-
- long buffer[2*LDT_SIZE];
- ldt_entry content;
- int n;
-
-#ifdef linux
- n = modify_ldt( 0, buffer, sizeof(buffer) ) / 8;
-#endif /* linux */
-#if defined(__NetBSD__) || defined(__FreeBSD__)
- n = i386_get_ldt( 0, (union descriptor *)buffer, LDT_SIZE );
-#endif /* __NetBSD__ || __FreeBSD__ */
- for (i = 0; i < n; i++)
- {
- LDT_BytesToEntry( &buffer[2*i], &content );
- if (content.base || content.limit)
- {
- fprintf( stderr, "%04x: sel=%04x base=%08lx limit=%05lx %s type=%d\n",
- i, ENTRY_TO_SELECTOR(i),
- content.base, content.limit,
- content.limit_in_pages ? "(pages)" : "(bytes)",
- content.type );
- }
- }
-#endif /* WINELIB */
-}
diff --git a/loader/main.c b/loader/main.c
index 3ace9d3..e6ad03e 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -10,12 +10,12 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
-#include "neexe.h"
+#include "windows.h"
#include "dos_fs.h"
#include "dlls.h"
-#include "windows.h"
+#include "miscemu.h"
+#include "neexe.h"
#include "wineopts.h"
-#include "wine.h"
#include "task.h"
#include "options.h"
#include "pe_image.h"
@@ -46,6 +46,9 @@
/* Initialize tasks */
if (!TASK_Init()) return 0;
+ /* Initialize interrupt vectors */
+ if (!INT_Init()) return 0;
+
/* Initialize the DOS file system */
DOS_InitFS();
diff --git a/loader/module.c b/loader/module.c
index c4af5bf..aa397d8 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -292,7 +292,7 @@
/***********************************************************************
* MODULE_CreateSegments
*/
-BOOL MODULE_CreateSegments( HMODULE hModule )
+static BOOL MODULE_CreateSegments( HMODULE hModule )
{
SEGTABLEENTRY *pSegment;
NE_MODULE *pModule;
@@ -308,9 +308,8 @@
{
/* FIXME: this is needed because heap growing is not implemented */
pModule->heap_size = 0x10000 - minsize;
- /* For tasks, the DGROUP is allocated by MODULE_MakeNewInstance */
- minsize = 0x10000;
- if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) continue;
+ /* The DGROUP is allocated by MODULE_CreateInstance */
+ continue;
}
pSegment->selector = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
minsize, hModule,
@@ -327,6 +326,57 @@
/***********************************************************************
+ * MODULE_GetInstance
+ */
+static HINSTANCE MODULE_GetInstance( HMODULE hModule )
+{
+ SEGTABLEENTRY *pSegment;
+ NE_MODULE *pModule;
+
+ if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+ if (pModule->dgroup == 0) return hModule;
+
+ pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
+
+ return pSegment->selector;
+}
+
+
+/***********************************************************************
+ * MODULE_CreateInstance
+ */
+static HINSTANCE MODULE_CreateInstance( HMODULE hModule, LOADPARAMS *params )
+{
+ SEGTABLEENTRY *pSegment;
+ NE_MODULE *pModule;
+ int minsize;
+ HINSTANCE hNewInstance, hPrevInstance;
+
+ if (!(pModule = (NE_MODULE *)GlobalLock( 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( int fd, OFSTRUCT *ofs )
@@ -518,62 +568,6 @@
/***********************************************************************
- * MODULE_MakeNewInstance
- *
- * Create a new instance of the specified module.
- */
-HINSTANCE MODULE_MakeNewInstance( HMODULE hModule, LOADPARAMS *params )
-{
- NE_MODULE *pModule;
- SEGTABLEENTRY *pSegment;
- HINSTANCE hNewInstance, hPrevInstance;
- int minsize;
-
- if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
- if (!pModule->dgroup) return hModule; /* No DGROUP -> return the module */
-
- pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
- hPrevInstance = pSegment->selector;
-
- /* Don't create a new instance if it's a library */
-
- if (pModule->flags & NE_FFLAGS_LIBMODULE) return hPrevInstance;
- if (params == (LOADPARAMS*)-1) return hPrevInstance;
-
- /* Allocate the new data segment */
-
- 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;
- NE_LoadSegment( hModule, pModule->dgroup );
-
- /* Create a new task for this instance */
- if (!TASK_CreateTask( hModule, hNewInstance, hPrevInstance,
- params->hEnvironment,
- (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ),
- *((WORD *)PTR_SEG_TO_LIN(params->showCmd)+1) ))
- {
- GlobalFree( hNewInstance );
- return 0;
- }
-
- /* Initialize the local heap */
-
- if (pModule->heap_size)
- {
- WORD heapstart = pSegment->minsize;
- if (pModule->ss == pModule->dgroup) heapstart += pModule->stack_size;
- LocalInit( hNewInstance, heapstart, heapstart + pModule->heap_size );
- }
- return hNewInstance;
-}
-
-
-/***********************************************************************
* MODULE_GetOrdinal
*
* Lookup the ordinal for a given name.
@@ -800,6 +794,7 @@
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 );
@@ -811,6 +806,7 @@
modulepath = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
if (!(modulename = strrchr( modulepath, '\\' )))
modulename = modulepath;
+ else modulename++;
if (!strcasecmp( modulename, filename )) return hModule;
name_table = (BYTE *)pModule + pModule->name_table;
@@ -878,8 +874,9 @@
HINSTANCE LoadModule( LPCSTR name, LPVOID paramBlock )
{
HMODULE hModule;
- HANDLE hInstance;
+ HANDLE hInstance, hPrevInstance;
NE_MODULE *pModule;
+ LOADPARAMS *params = (LOADPARAMS *)paramBlock;
WORD *pModRef, *pDLLs;
int i, fd;
@@ -906,6 +903,9 @@
MODULE_CreateSegments( hModule );
+ hPrevInstance = 0;
+ hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
+
/* Load the referenced DLLs */
pModRef = (WORD *)((char *)pModule + pModule->modref_table);
@@ -950,14 +950,9 @@
}
}
- /* Load the segments (except the DGROUP) */
+ /* Load the segments */
- for (i = 1; i <= pModule->seg_count; i++)
- if (i != pModule->dgroup) NE_LoadSegment( hModule, i );
-
- /* Create an instance for this module */
-
- hInstance = MODULE_MakeNewInstance( hModule, (LOADPARAMS*)paramBlock );
+ for (i = 1; i <= pModule->seg_count; i++) NE_LoadSegment( hModule, i );
/* Fixup the functions prologs */
@@ -971,10 +966,23 @@
else
{
pModule = (NE_MODULE *)GlobalLock( hModule );
- hInstance = MODULE_MakeNewInstance( hModule, (LOADPARAMS*)paramBlock );
+ hPrevInstance = MODULE_GetInstance( hModule );
+ hInstance = MODULE_CreateInstance( hModule, params );
+ if (hInstance != hPrevInstance) /* not a library */
+ NE_LoadSegment( hModule, pModule->dgroup );
pModule->count++;
}
+ /* 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;
}
@@ -999,20 +1007,7 @@
*/
HMODULE GetModuleHandle( LPCSTR name )
{
- BYTE len = strlen(name);
- HMODULE hModule = hFirstModule;
-
- while( hModule )
- {
- NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
- char *pname = (char *)pModule + pModule->name_table;
- if (((BYTE)*pname == len) && !strncasecmp( pname+1, name, len ))
- break;
- hModule = pModule->next;
- }
- dprintf_module( stddeb, "GetModuleHandle('%s'): returning %04x\n",
- name, hModule );
- return hModule;
+ return MODULE_FindModule( name );
}
@@ -1044,6 +1039,7 @@
name = ((LOADEDFILEINFO*)((char*)pModule + pModule->fileinfo))->filename;
strncpy( lpFileName, name, nSize );
lpFileName[nSize-1] = '\0';
+ dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
return strlen(lpFileName);
}
@@ -1056,6 +1052,8 @@
HANDLE handle;
dprintf_module( stddeb, "LoadLibrary: (%08x) %s\n", (int)libname, libname);
+ if ((handle = MODULE_FindModule( libname )) != 0) return handle;
+
handle = LoadModule( libname, (LPVOID)-1 );
if (handle == 2) /* file not found */
{
@@ -1064,7 +1062,7 @@
strcat( buffer, ".dll" );
handle = LoadModule( buffer, (LPVOID)-1 );
}
- if (handle >= 32) NE_InitializeDLLs( handle );
+ if (handle >= 32) NE_InitializeDLLs( GetExePtr(handle) );
return handle;
}
diff --git a/loader/ne_image.c b/loader/ne_image.c
index 1a14ef2..4529f62 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -56,6 +56,14 @@
lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
read( fd, GlobalLock( pSeg->selector ), pSeg->size ? pSeg->size : 0x10000);
+ if ( pModule->heap_size && pModule->dgroup == segnum )
+ {
+ /* Initialize the local heap */
+ WORD heapstart = pSeg->minsize;
+ if (pModule->ss == pModule->dgroup) heapstart += pModule->stack_size;
+ LocalInit( pSeg->selector, heapstart, heapstart + pModule->heap_size );
+ }
+
if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
return TRUE; /* No relocation data, we are done */
@@ -413,12 +421,15 @@
WORD *pDLL;
pModule = (NE_MODULE *)GlobalLock( hModule );
- if (!pModule->dlls_to_init) return;
- for (pDLL = (WORD *)GlobalLock( pModule->dlls_to_init ); *pDLL; pDLL++)
+ if (pModule->dlls_to_init)
{
- NE_InitDLL( *pDLL );
- NE_InitializeDLLs( *pDLL );
+ for (pDLL = (WORD *)GlobalLock( pModule->dlls_to_init ); *pDLL; pDLL++)
+ {
+ NE_InitDLL( *pDLL );
+ NE_InitializeDLLs( *pDLL );
+ }
+ GlobalFree( pModule->dlls_to_init );
+ pModule->dlls_to_init = 0;
}
- GlobalFree( pModule->dlls_to_init );
- pModule->dlls_to_init = 0;
+ NE_InitDLL( hModule );
}
diff --git a/loader/resource.c b/loader/resource.c
index adbfc80..0970786 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -16,6 +16,7 @@
#include "windows.h"
#include "gdi.h"
#include "bitmap.h"
+#include "global.h"
#include "neexe.h"
#include "icon.h"
#include "accel.h"
@@ -221,6 +222,23 @@
}
}
+/**********************************************************************
+ * DirectResAlloc (KERNEL.168)
+ * Check Schulman, p. 232 for details
+ */
+HANDLE DirectResAlloc(HANDLE hInstance, WORD wType, WORD wSize)
+{
+ HANDLE hModule;
+ dprintf_resource(stddeb,"DirectResAlloc(%x,%x,%x)\n",hInstance,wType,wSize);
+ hModule = GetExePtr(hInstance);
+ if(!hModule)return 0;
+ if(wType != 0x10) /* 0x10 is the only observed value, passed from
+ CreateCursorIndirect. */
+ fprintf(stderr, "DirectResAlloc: wType = %x\n", wType);
+ /* This hopefully does per-module allocation rather than per-instance */
+ return GLOBAL_Alloc(GMEM_FIXED, wSize, hModule, FALSE, FALSE, FALSE);
+}
+
/**********************************************************************
* ConvertCoreBitmap
diff --git a/loader/signal.c b/loader/signal.c
index b395d41..6ac04ad 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -18,6 +18,7 @@
#include "dos_fs.h"
#include "prototypes.h"
#include "miscemu.h"
+#include "registers.h"
#include "win.h"
#if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
@@ -44,57 +45,59 @@
}
#endif
-int do_int(int intnum, struct sigcontext_struct *scp)
+int do_int(int intnum, struct sigcontext_struct *context)
{
switch(intnum)
{
- case 0x10: return do_int10(scp);
+ case 0x10: return do_int10(context);
case 0x11:
- scp->sc_eax = (scp->sc_eax & 0xffff0000L) | DOS_GetEquipment();
+ AX = DOS_GetEquipment();
return 1;
case 0x12:
- scp->sc_eax = (scp->sc_eax & 0xffff0000L) | 640L;
+ AX = 640;
return 1; /* get base mem size */
- case 0x13: return do_int13(scp);
- case 0x15: return do_int15(scp);
- case 0x16: return do_int16(scp);
- case 0x1a: return do_int1a(scp);
- case 0x21: return do_int21(scp);
+ case 0x13: return do_int13(context);
+ case 0x15: return do_int15(context);
+ case 0x16: return do_int16(context);
+ case 0x1a: return do_int1a(context);
+ case 0x21: return do_int21(context);
case 0x22:
- scp->sc_eax = 0x1234;
- scp->sc_ebx = 0x5678;
- scp->sc_ecx = 0x9abc;
- scp->sc_edx = 0xdef0;
+ AX = 0x1234;
+ BX = 0x5678;
+ CX = 0x9abc;
+ DX = 0xdef0;
return 1;
- case 0x25: return do_int25(scp);
- case 0x26: return do_int26(scp);
- case 0x2a: return do_int2a(scp);
- case 0x2f: return do_int2f(scp);
- case 0x31: return do_int31(scp);
+ case 0x25: return do_int25(context);
+ case 0x26: return do_int26(context);
+ case 0x2a: return do_int2a(context);
+ case 0x2f: return do_int2f(context);
+ case 0x31: return do_int31(context);
+ case 0x5c: return do_int5c(context);
default:
- printf("int%02x: Unimplemented!\n", intnum);
+ fprintf(stderr,"int%02x: Unimplemented!\n", intnum);
break;
}
return 0;
}
#ifdef linux
-static void win_fault(int signal, struct sigcontext_struct context)
+static void win_fault(int signal, struct sigcontext_struct context_struct)
{
- struct sigcontext_struct *scp = &context;
+ struct sigcontext_struct *context = &context_struct;
#else
-static void win_fault(int signal, int code, struct sigcontext *scp)
+static void win_fault(int signal, int code, struct sigcontext *context)
{
#endif
unsigned char * instr;
+ WORD *stack;
#if !(defined (linux) || defined (__NetBSD__))
- int i, *dump;
+ int i, *dump;
#endif
/* First take care of a few preliminaries */
@@ -112,7 +115,7 @@
/* And back up over the int3 instruction. */
if(signal == SIGTRAP) {
- scp->sc_eip--;
+ EIP--;
goto oops;
}
#endif
@@ -126,76 +129,83 @@
if(signal != SIGBUS && signal != SIGSEGV && signal != SIGTRAP)
exit(1);
#endif
- if (scp->sc_cs == WINE_CODE_SELECTOR)
+ if (CS == WINE_CODE_SELECTOR)
{
fprintf(stderr,
"Segmentation fault in Wine program (%x:%lx)."
- " Please debug\n",
- scp->sc_cs, scp->sc_eip);
+ " Please debug\n", CS, EIP );
goto oops;
}
/* Now take a look at the actual instruction where the program
bombed */
- instr = (unsigned char *) PTR_SEG_OFF_TO_LIN(scp->sc_cs, scp->sc_eip);
+ instr = (unsigned char *) PTR_SEG_OFF_TO_LIN( CS, EIP );
switch(*instr)
{
case 0xcd: /* int <XX> */
instr++;
- if (!do_int(*instr, scp)) {
+ if (!do_int(*instr, context)) {
fprintf(stderr,"Unexpected Windows interrupt %x\n", *instr);
goto oops;
}
- scp->sc_eip += 2; /* Bypass the int instruction */
+ EIP += 2; /* Bypass the int instruction */
break;
-
+
+ case 0xcf: /* iret */
+ stack = (WORD *)PTR_SEG_OFF_TO_LIN( SS, SP );
+ EIP = *stack++;
+ CS = *stack++;
+ EFL = *stack;
+ SP += 6; /* Pop the return address and flags */
+ break;
+
case 0xe4: /* inb al,XX */
- inportb_abs(scp);
- scp->sc_eip += 2;
+ inportb_abs(context);
+ EIP += 2;
break;
case 0xe5: /* in ax,XX */
- inport_abs(scp);
- scp->sc_eip += 2;
+ inport_abs(context);
+ EIP += 2;
break;
case 0xe6: /* outb XX,al */
- outportb_abs(scp);
- scp->sc_eip += 2;
+ outportb_abs(context);
+ EIP += 2;
break;
case 0xe7: /* out XX,ax */
- outport_abs(scp);
- scp->sc_eip += 2;
+ outport_abs(context);
+ EIP += 2;
break;
case 0xec: /* inb al,dx */
- inportb(scp);
- scp->sc_eip++;
+ inportb(context);
+ EIP++;
break;
case 0xed: /* in ax,dx */
- inport(scp);
- scp->sc_eip++;
+ inport(context);
+ EIP++;
break;
case 0xee: /* outb dx,al */
- outportb(scp);
- scp->sc_eip++;
+ outportb(context);
+ EIP++;
break;
case 0xef: /* out dx,ax */
- outport(scp);
- scp->sc_eip++;
+ outport(context);
+ EIP++;
break;
case 0xfa: /* cli, ignored */
- scp->sc_eip++;
+ EIP++;
break;
case 0xfb: /* sti, ignored */
- scp->sc_eip++;
+ EIP++;
break;
default:
@@ -210,14 +220,14 @@
oops:
XUngrabPointer(display, CurrentTime);
- XUngrabServer(display);
- XFlush(display);
- fprintf(stderr,"In win_fault %x:%lx\n", scp->sc_cs, scp->sc_eip);
+ XUngrabServer(display);
+ XFlush(display);
+ fprintf(stderr,"In win_fault %x:%lx\n", CS, EIP );
#if defined(linux) || defined(__NetBSD__) || defined(__FreeBSD__)
- wine_debug(signal, (int *)scp); /* Enter our debugger */
+ wine_debug(signal, (int *)context); /* Enter our debugger */
#else
- fprintf(stderr,"Stack: %x:%x\n", scp->sc_ss, scp->sc_esp);
- dump = (int*) scp;
+ fprintf(stderr,"Stack: %x:%x\n", SS, ESP );
+ dump = (int*) context;
for(i=0; i<22; i++)
{
fprintf(stderr," %8.8x", *dump++);
diff --git a/loader/task.c b/loader/task.c
index 33d53de..5663419 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -12,6 +12,7 @@
#include "callback.h"
#include "global.h"
#include "instance.h"
+#include "miscemu.h"
#include "module.h"
#include "neexe.h"
#include "selectors.h"
@@ -31,6 +32,7 @@
static HTASK hFirstTask = 0;
static HTASK hCurrentTask = 0;
static HTASK hTaskToKill = 0;
+static HTASK hLockedTask = 0;
static WORD nTaskCount = 0;
/* TASK_Reschedule() 16-bit entry point */
@@ -281,12 +283,11 @@
/* Fill the PDB */
pTask->pdb.int20 = 0x20cd;
- pTask->pdb.dispatcher[0] = 0x9a;
+ pTask->pdb.dispatcher[0] = 0x9a; /* ljmp */
*(DWORD *)&pTask->pdb.dispatcher[1] = MODULE_GetEntryPoint( GetModuleHandle("KERNEL"), 102 ); /* KERNEL.102 is DOS3Call() */
- pTask->pdb.savedint22 = MODULE_GetEntryPoint( GetModuleHandle("KERNEL"),
- 137 ); /* KERNEL.137 is FatalAppExit() */
- pTask->pdb.savedint23 = pTask->pdb.savedint22;
- pTask->pdb.savedint24 = pTask->pdb.savedint22;
+ pTask->pdb.savedint22 = INT_GetHandler( 0x22 );
+ pTask->pdb.savedint23 = INT_GetHandler( 0x23 );
+ pTask->pdb.savedint24 = INT_GetHandler( 0x24 );
pTask->pdb.environment = hEnvironment;
strncpy( pTask->pdb.cmdLine + 1, cmdLine, 126 );
pTask->pdb.cmdLine[127] = '\0';
@@ -347,8 +348,8 @@
frame16->saved_sp = pTask->sp;
frame16->ds = pTask->hInstance;
frame16->entry_point = 0;
- frame16->ordinal_number = 1;
- frame16->dll_id = 1;
+ frame16->ordinal_number = 24; /* WINPROCS.24 is TASK_Reschedule */
+ frame16->dll_id = 24; /* WINPROCS */
frame16->bp = 0;
frame16->ip = LOWORD( CALL16_RetAddr_word );
frame16->cs = HIWORD( CALL16_RetAddr_word );
@@ -431,6 +432,7 @@
TASK_UnlinkTask( hCurrentTask );
hTaskToKill = hCurrentTask;
+ hLockedTask = 0;
Yield();
/* We never return from Yield() */
}
@@ -454,6 +456,10 @@
if (hTaskToKill && (hTaskToKill != hCurrentTask))
TASK_DeleteTask( hTaskToKill );
+ /* If current task is locked, simply return */
+
+ if (hLockedTask) return;
+
/* Find a task to yield to */
pOldTask = (TDB *)GlobalLock( hCurrentTask );
@@ -496,6 +502,7 @@
pOldTask->sp = IF1632_Saved16_sp;
pOldTask->esp = IF1632_Saved32_esp;
}
+ else IF1632_Original32_esp = IF1632_Saved32_esp;
/* Make the task the last in the linked list (round-robin scheduling) */
@@ -519,6 +526,7 @@
*/
void InitTask( struct sigcontext_struct context )
{
+ static int firstTask = 1;
TDB *pTask;
NE_MODULE *pModule;
@@ -526,6 +534,22 @@
if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return;
if (!(pModule = (NE_MODULE *)GlobalLock( pTask->hModule ))) return;
+ if (firstTask)
+ {
+ extern BOOL WIDGETS_Init(void);
+ extern BOOL WIN_CreateDesktopWindow(void);
+
+ /* Perform global initialisations that need a task context */
+
+ /* Initialize built-in window classes */
+ if (!WIDGETS_Init()) return;
+
+ /* Create desktop window */
+ if (!WIN_CreateDesktopWindow()) return;
+
+ firstTask = 0;
+ }
+
NE_InitializeDLLs( pTask->hModule );
/* Registers on return are:
@@ -602,6 +626,26 @@
/***********************************************************************
+ * LockCurrentTask (KERNEL.33)
+ */
+HTASK LockCurrentTask( BOOL bLock )
+{
+ if (bLock) hLockedTask = hCurrentTask;
+ else hLockedTask = 0;
+ return hLockedTask;
+}
+
+
+/***********************************************************************
+ * IsTaskLocked (KERNEL.122)
+ */
+WORD IsTaskLocked(void)
+{
+ return hLockedTask;
+}
+
+
+/***********************************************************************
* OldYield (KERNEL.117)
*/
void OldYield(void)
@@ -747,6 +791,19 @@
/***********************************************************************
+ * GetInstanceData (KERNEL.54)
+ */
+int GetInstanceData( HANDLE instance, WORD buffer, int len )
+{
+ char *ptr = (char *)GlobalLock( instance );
+ if (!ptr || !len) return 0;
+ if ((int)buffer + len >= 0x10000) len = 0x10000 - buffer;
+ memcpy( ptr + buffer, (char *)GlobalLock( CURRENT_DS ) + buffer, len );
+ return len;
+}
+
+
+/***********************************************************************
* GetNumTasks (KERNEL.152)
*/
WORD GetNumTasks(void)