Release 960712

Fri Jul 12 17:43:05 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/scroll.c]
	Use Win32 heap functions to allocate scroll-bar info structure.

	* [debugger/dbg.y] [debugger/registers.c]
	Added support for FS and GS segment registers.
	Check that segment registers value are OK before returning from
	the signal handler.

	* [tools/build.c] [if1632/relay.c] [loader/builtin.c]
	Changed relay debugging for Win32 function: the relay code now
	passes the entry point address instead of the function name.

	* [tools/build.c] [miscemu/*.c]
	Added support for data entry points in Win32 DLLs.
	Added 'cdecl' function type for Win32.
	For 'register' function, the relay code now passes a pointer to
	the SIGCONTEXT structure.
	
	* [include/registers.h] [include/wine.h]
	Moved SIGCONTEXT structure definition in registers.h.

	* [loader/pe_image.c]
	Don't die at once if some Win32 entry points cannot be found, but
	set them to NULL, just like we do for Win16. This allows some
	programs to go further before crashing.

	* [loader/task.c] [loader/main.c]
	Moved global initializations from InitTask() to MAIN_Init(), as
	they no longer need a task context with the new SEGPTR heap functions.

	* [memory/string.c]
	Added lstrcpynAtoW and lstrcpynWtoA; not real API functions, but
 	very convenient.

	* [windows/graphics.c]
	Partially implemented DrawEdge().

	* [windows/timer.c] [windows/caret.c]
	Implemented Win32 timer handling. Updated caret management to use
	Win32 timers (avoids having to use a Win16 callback).

	* [windows/win.c]
	Prevent programs from setting some style bits with
	SetWindowLong(). This should fix some BadMatch crashes.
	Link new windows at the end of the linked list.

	* [windows/winpos.c]
	Don't try to activate a child window in ShowWindow().

	* [windows/winproc.c]
	Added a 32->32 thunk to support Ansi-Unicode translation.

Wed Jul 10 22:11:12 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [files/directory.c]
	Additional (undocumented) return value for GetTempDrive() added.

	* [files/dos_fs.c] [files/file.c] [include/windows.h]
	GetTempFileName32* added.
	GetShortPathName* added.

	* [memory/string.c]
	Win16 lstrcpy() can get NULL ptrs as argument and survive.

	* [misc/lzexpand.c]
	LZOpenFile(): also try opening with compressed filename if normal
 	open fails.

	* [misc/ole2nls.c] [misc/lstr.c] [include/windows.h]
	Char* added.
	CompareString* added.

Sun Jul  7 01:22:14 1996  Jukka Iivonen <iivonen@cc.helsinki.fi>

	* [objects/font.c] [if1632/gdi32.spec]
	CreateFontIndirect32A and CreateFontIndirect32W added.

	* [misc/ole2nls.c]
	GetUserDefaultLCID return values updated for new languages.
	Finnish support added for GetLocaleInfoA.

	* [object/palette] [gdi32.spec]
	RealizePalette32 and SelectPalette32 added.
	
Sat Jul  6 17:27:30 1996  Ronan Waide  <root@waider.ie>

	* [misc/shell.c]
	Fixup for SHELL_FindExecutable so that File->Run from progman
	works once more. Still needs some more fixups - grep for FIXME in
	this file.
diff --git a/debugger/break.c b/debugger/break.c
index be92e1f..1e48763 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -37,31 +37,25 @@
  */
 static void DEBUG_SetOpcode( const DBG_ADDR *addr, BYTE op )
 {
-    if (addr->seg)
+    BYTE *ptr;
+
+    if (addr->seg) ptr = (BYTE *)PTR_SEG_OFF_TO_LIN( addr->seg, addr->off );
+    else ptr = (BYTE *)addr->off;
+
+    /* There are a couple of problems with this. On Linux prior to
+       1.1.62, this call fails (ENOACCESS) due to a bug in fs/exec.c.
+       This code is currently not tested at all on BSD.
+       How do I get the old protection in order to restore it later on?
+       */
+    if (mprotect((caddr_t)((int)ptr & (~4095)), 4096,
+                 PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
     {
-        *(BYTE *)PTR_SEG_OFF_TO_LIN( addr->seg, addr->off ) = op;
+        perror( "Can't set break point" );
+        return;
     }
-    else  /* 32-bit code, so we have to change the protection first */
-    {
-        /* There are a couple of problems with this. On Linux prior to
-           1.1.62, this call fails (ENOACCESS) due to a bug in fs/exec.c.
-           This code is currently not tested at all on BSD.
-           How do I determine the page size in a more symbolic manner?
-           And why does mprotect need that start address of the page
-           in the first place?
-           Not that portability matters, this code is i386 only anyways...
-           How do I get the old protection in order to restore it later on?
-        */
-        if (mprotect((caddr_t)(addr->off & (~4095)), 4096,
-                     PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
-        {
-            perror( "Can't set break point" );
-            return;
-	}
-        *(BYTE *)addr->off = op;
-	mprotect((caddr_t)(addr->off & ~4095), 4096,
-                  PROT_READ | PROT_EXEC );
-    }
+    *ptr = op;
+    /* mprotect((caddr_t)(addr->off & ~4095), 4096,
+       PROT_READ | PROT_EXEC ); */
 }
 
 
diff --git a/debugger/dbg.y b/debugger/dbg.y
index 45e806b..9a006a2 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -234,6 +234,7 @@
     static int loaded_symbols = 0;
     char SymbolTableFile[256];
     int instr_len = 0, newmode;
+    BOOL32 ret_ok;
 #ifdef YYDEBUG
     yydebug = 0;
 #endif
@@ -295,6 +296,7 @@
             instr_len = addr.off - EIP_reg(DEBUG_context);
         }
 
+        ret_ok = 0;
         do
         {
             issue_prompt();
@@ -303,7 +305,9 @@
             addr.seg = CS_reg(DEBUG_context);
             addr.off = EIP_reg(DEBUG_context);
             DBG_FIX_ADDR_SEG( &addr, 0 );
-        } while (!DBG_CHECK_READ_PTR( &addr, 1 ));
+            ret_ok = DEBUG_ValidateRegisters();
+            if (ret_ok) ret_ok = DBG_CHECK_READ_PTR( &addr, 1 );
+        } while (!ret_ok);
     }
 
     DEBUG_RestartExecution( regs, dbg_exec_mode, instr_len );
diff --git a/debugger/debug.l b/debugger/debug.l
index 709c23a..abd10bf 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -80,6 +80,8 @@
 $ds     { yylval.reg = REG_DS;  return tREG; }
 $cs     { yylval.reg = REG_CS;  return tREG; }
 $ss     { yylval.reg = REG_SS;  return tREG; }
+$fs     { yylval.reg = REG_FS;  return tREG; }
+$gs     { yylval.reg = REG_GS;  return tREG; }
 
 info|inf|in			{ return tINFO; }
 show|sho|sh			{ return tINFO; }
@@ -169,7 +171,11 @@
     {
         flush_symbols();
         line = readline ("Wine-dbg>");
-        if (!line) exit(0);
+        if (!line)
+        {
+            fprintf( stderr, "\n" );
+            exit(0);
+        }
 
         /* Remove leading and trailing whitespace from the line */
 
diff --git a/debugger/hash.c b/debugger/hash.c
index 39dbdab..459878d 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -212,7 +212,7 @@
     DBG_ADDR addr;
     char buffer[256];
     unsigned char *cpnt, *name;
-    unsigned int address;
+    FARPROC16 address;
     BOOL ok;
 
     for (ok = ModuleFirst(&entry); ok; ok = ModuleNext(&entry))
diff --git a/debugger/memory.c b/debugger/memory.c
index cfe16a2..62d33060 100644
--- a/debugger/memory.c
+++ b/debugger/memory.c
@@ -7,6 +7,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include "windows.h"
 #include "debugger.h"
 
 
diff --git a/debugger/registers.c b/debugger/registers.c
index 57aaf96..66b38f3 100644
--- a/debugger/registers.c
+++ b/debugger/registers.c
@@ -7,11 +7,8 @@
 #include <stdio.h>
 #include "debugger.h"
 
-
 SIGCONTEXT *DEBUG_context;
 
-
-
 /***********************************************************************
  *           DEBUG_SetRegister
  *
@@ -45,6 +42,20 @@
         case REG_DS:  DS_reg(DEBUG_context)  = val; break;
         case REG_ES:  ES_reg(DEBUG_context)  = val; break;
         case REG_SS:  SS_reg(DEBUG_context)  = val; break;
+#ifdef FS_reg
+        case REG_FS:  FS_reg(DEBUG_context)  = val; break;
+#else
+        case REG_FS:
+            fprintf( stderr, "Register %fs not supported on this system\n ");
+            break;
+#endif
+#ifdef GS_reg
+        case REG_GS:  GS_reg(DEBUG_context)  = val; break;
+#else
+        case REG_GS:
+            fprintf( stderr, "Register %gs not supported on this system\n ");
+            break;
+#endif
     }
 }
 
@@ -82,6 +93,20 @@
         case REG_DS:  return DS_reg(DEBUG_context);
         case REG_ES:  return ES_reg(DEBUG_context);
         case REG_SS:  return SS_reg(DEBUG_context);
+#ifdef FS_reg
+        case REG_FS:  return FS_reg(DEBUG_context);
+#else
+        case REG_FS:
+            fprintf( stderr, "Register %fs not supported on this system\n ");
+            return 0;
+#endif
+#ifdef GS_reg
+        case REG_GS:  return GS_reg(DEBUG_context);
+#else
+        case REG_GS:
+            fprintf( stderr, "Register %gs not supported on this system\n ");
+            return 0;
+#endif
     }
     return 0;  /* should not happen */
 }
@@ -98,13 +123,18 @@
     fprintf(stderr,"Register dump:\n");
 
     /* First get the segment registers out of the way */
-    fprintf( stderr," CS:%04x SS:%04x DS:%04x ES:%04x\n",
+    fprintf( stderr," CS:%04x SS:%04x DS:%04x ES:%04x",
              CS_reg(DEBUG_context), SS_reg(DEBUG_context),
              DS_reg(DEBUG_context), ES_reg(DEBUG_context) );
-
+#ifdef FS_reg
+    fprintf( stderr, " FS:%04x", FS_reg(DEBUG_context) );
+#endif
+#ifdef GS_reg
+    fprintf( stderr, " GS:%04x", GS_reg(DEBUG_context) );
+#endif
     if (dbg_mode == 16)
     {
-        fprintf( stderr," IP:%04x SP:%04x BP:%04x FLAGS:%04x\n",
+        fprintf( stderr,"\n IP:%04x SP:%04x BP:%04x FLAGS:%04x\n",
                  IP_reg(DEBUG_context), SP_reg(DEBUG_context),
                  BP_reg(DEBUG_context), FL_reg(DEBUG_context) );
 	fprintf( stderr," AX:%04x BX:%04x CX:%04x DX:%04x SI:%04x DI:%04x\n",
@@ -114,7 +144,7 @@
     }
     else  /* 32-bit mode */
     {
-        fprintf( stderr, " EIP:%08lx ESP:%08lx EBP:%08lx EFLAGS:%08lx\n", 
+        fprintf( stderr, "\n EIP:%08lx ESP:%08lx EBP:%08lx EFLAGS:%08lx\n", 
                  EIP_reg(DEBUG_context), ESP_reg(DEBUG_context),
                  EBP_reg(DEBUG_context), EFL_reg(DEBUG_context) );
 	fprintf( stderr, " EAX:%08lx EBX:%08lx ECX:%08lx EDX:%08lx\n", 
@@ -125,3 +155,52 @@
     }
 }
 
+
+/***********************************************************************
+ *           DEBUG_ValidateRegisters
+ *
+ * Make sure all registers have a correct value for returning from
+ * the signal handler.
+ */
+BOOL32 DEBUG_ValidateRegisters(void)
+{
+/* Check that a selector is a valid ring-3 LDT selector, or a NULL selector */
+#define CHECK_SEG(seg,name) \
+    if (((seg) & ~3) && \
+        ((((seg) & 7) != 7) || IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(seg)))) \
+    { \
+        fprintf( stderr, "*** Invalid value for %s register: %04x\n", \
+                 (name), (seg) ); \
+        return FALSE; \
+    }
+
+    if (CS_reg(DEBUG_context) != WINE_CODE_SELECTOR)
+        CHECK_SEG( CS_reg(DEBUG_context), "CS" );
+    if (SS_reg(DEBUG_context) != WINE_DATA_SELECTOR)
+        CHECK_SEG( SS_reg(DEBUG_context), "SS" );
+    if (DS_reg(DEBUG_context) != WINE_DATA_SELECTOR)
+        CHECK_SEG( DS_reg(DEBUG_context), "DS" );
+    if (ES_reg(DEBUG_context) != WINE_DATA_SELECTOR)
+        CHECK_SEG( ES_reg(DEBUG_context), "ES" );
+    if (FS_reg(DEBUG_context) != WINE_DATA_SELECTOR)
+        CHECK_SEG( FS_reg(DEBUG_context), "FS" );
+    if (GS_reg(DEBUG_context) != WINE_DATA_SELECTOR)
+        CHECK_SEG( GS_reg(DEBUG_context), "GS" );
+
+    /* Check that CS and SS are not NULL */
+
+    if (!(CS_reg(DEBUG_context) & ~3))
+    {
+        fprintf( stderr, "*** Invalid value for CS register: %04x\n",
+                 CS_reg(DEBUG_context) );
+        return FALSE;
+    }
+    if (!(SS_reg(DEBUG_context) & ~3))
+    {
+        fprintf( stderr, "*** Invalid value for SS register: %04x\n",
+                 SS_reg(DEBUG_context) );
+        return FALSE;
+    }
+    return TRUE;
+#undef CHECK_SEG
+}