More complete implementation of the SetCtrlHandler() function (and the
related console functions).

diff --git a/relay32/kernel32.spec b/relay32/kernel32.spec
index c5e80a8..279ea63 100644
--- a/relay32/kernel32.spec
+++ b/relay32/kernel32.spec
@@ -290,7 +290,7 @@
 271 stdcall FreeLibrary(long) FreeLibrary32
 273 stdcall FreeResource(long) FreeResource32
 274 stdcall FreeSLCallback(long) FreeSLCallback
-275 stub GenerateConsoleCtrlEvent
+275 stdcall GenerateConsoleCtrlEvent(long long) GenerateConsoleCtrlEvent
 276 stdcall GetACP() GetACP
 277 stdcall GetAtomNameA(long ptr long) GetAtomName32A
 278 stdcall GetAtomNameW(long ptr long) GetAtomName32W
@@ -392,7 +392,7 @@
 374 stdcall GetProcessFlags(long) GetProcessFlags
 375 stdcall GetProcessHeap() GetProcessHeap
 376 stdcall GetProcessHeaps(long ptr) GetProcessHeaps
-377 stub GetProcessShutdownParameters
+377 stdcall GetProcessShutdownParameters(ptr ptr) GetProcessShutdownParameters
 378 stdcall GetProcessTimes(long ptr ptr ptr ptr) GetProcessTimes
 379 stdcall GetProcessVersion(long) GetProcessVersion
 380 stdcall GetProcessWorkingSetSize(long ptr ptr) GetProcessWorkingSetSize
diff --git a/scheduler/process.c b/scheduler/process.c
index ca6d794..19d7503 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -717,13 +717,43 @@
 
 /***********************************************************************
  *           SetProcessShutdownParameters    (KERNEL32)
+ *
+ * CHANGED - James Sutherland (JamesSutherland@gmx.de)
+ * Now tracks changes made (but does not act on these changes)
+ * NOTE: the definition for SHUTDOWN_NORETRY was done on guesswork.
+ * It really shouldn't be here, but I'll move it when it's been checked!
  */
+#define SHUTDOWN_NORETRY 1
+extern unsigned int shutdown_noretry = 0;
+extern unsigned int shutdown_priority = 0x280L;
 BOOL32 WINAPI SetProcessShutdownParameters(DWORD level,DWORD flags)
 {
-    FIXME(process,"(%ld,0x%08lx): stub\n",level,flags);
+    if (flags & SHUTDOWN_NORETRY)
+      shutdown_noretry = 1;
+    else
+      shutdown_noretry = 0;
+    if (level > 0x100L && level < 0x3FFL)
+      shutdown_priority = level;
+    else
+      {
+	ERR(process,"invalid priority level 0x%08lx\n", level);
+	return FALSE;
+      }
     return TRUE;
 }
 
+
+/***********************************************************************
+ * GetProcessShutdownParameters                 (KERNEL32)
+ *
+ */
+BOOL32 WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel,
+					    LPDWORD lpdwFlags )
+{
+  (*lpdwLevel) = shutdown_priority;
+  (*lpdwFlags) = (shutdown_noretry * SHUTDOWN_NORETRY);
+  return TRUE;
+}
 /***********************************************************************
  *           SetProcessPriorityBoost    (KERNEL32)
  */
diff --git a/win32/console.c b/win32/console.c
index 593cbe5..03d66f5 100644
--- a/win32/console.c
+++ b/win32/console.c
@@ -177,11 +177,85 @@
  * RETURNS
  *    Success: TRUE
  *    Failure: FALSE
+ *
+ * CHANGED
+ * James Sutherland (JamesSutherland@gmx.de)
+ * Added global variables console_ignore_ctrl_c and handlers[]
+ * Does not yet do any error checking, or set LastError if failed.
+ * This doesn't yet matter, since these handlers are not yet called...!
  */
+static unsigned int console_ignore_ctrl_c = 0;
+static HANDLER_ROUTINE *handlers[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 BOOL32 WINAPI SetConsoleCtrlHandler( HANDLER_ROUTINE *func, BOOL32 add )
 {
-    FIXME(console, "(%p,%i): stub\n",func,add);
-    return TRUE;
+  unsigned int alloc_loop = sizeof(handlers)/sizeof(HANDLER_ROUTINE *);
+  unsigned int done = 0;
+  FIXME(console, "(%p,%i) - no error checking or testing yet\n", func, add);
+  if (!func)
+    {
+      console_ignore_ctrl_c = add;
+      return TRUE;
+    }
+  if (add)
+      {
+	for (;alloc_loop--;)
+	  if (!handlers[alloc_loop] && !done)
+	    {
+	      handlers[alloc_loop] = func;
+	      done++;
+	    }
+	if (!done)
+	   FIXME(console, "Out of space on CtrlHandler table\n");
+	return(done);
+      }
+    else
+      {
+	for (;alloc_loop--;)
+	  if (handlers[alloc_loop] == func && !done)
+	    {
+	      handlers[alloc_loop] = 0;
+	      done++;
+	    }
+	if (!done)
+	   WARN(console, "Attempt to remove non-installed CtrlHandler %p\n");
+	return (done);
+      }
+    return (done);
+}
+
+
+/******************************************************************************
+ * GenerateConsoleCtrlEvent [KERNEL32.275] Simulate a CTRL-C or CTRL-BREAK
+ *
+ * PARAMS
+ *    dwCtrlEvent        [I] Type of event
+ *    dwProcessGroupID   [I] Process group ID to send event to
+ *
+ * NOTES
+ *    Doesn't yet work...!
+ *
+ * RETURNS
+ *    Success: True
+ *    Failure: False (and *should* [but doesn't] set LastError)
+ */
+BOOL32 WINAPI GenerateConsoleCtrlEvent( DWORD dwCtrlEvent,
+					DWORD dwProcessGroupID )
+{
+  if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
+    {
+      ERR( console, "invalid event %d for PGID %d\n", 
+	   (unsigned short)dwCtrlEvent, dwProcessGroupID );
+      return FALSE;
+    }
+  if (dwProcessGroupID == GetCurrentProcessId() )
+    {
+      FIXME( console, "Attempt to send event %d to self - stub\n",
+	     (unsigned short)dwCtrlEvent );
+      return FALSE;
+    }
+  FIXME( console,"event %d to external PGID %d - not implemented yet\n",
+	 (unsigned short)dwCtrlEvent, dwProcessGroupID );
+  return FALSE;
 }