From 62a8b433012644ca5a491e7df480f91d5496618b Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Tue, 19 Jan 1999 17:48:23 +0000
Subject: [PATCH] Hacked server-side device support Added user APCs support.
 Many changes to the xterm console to make use of the server (not finished
 yet). Moved some other small stuff to the server.

---
 files/change.c           |  51 +----
 files/dos_fs.c           |  31 ++-
 files/file.c             | 191 ++++++++++---------
 include/device.h         |   3 +-
 include/file.h           |  13 +-
 include/process.h        |   3 +-
 include/server.h         | 169 ++++++++++++++++-
 include/server/object.h  |  21 ++-
 include/server/request.h |  48 ++++-
 include/server/thread.h  |  11 ++
 include/thread.h         |   5 +-
 include/winbase.h        |   5 +-
 include/windows.h        |   1 +
 include/wintypes.h       |   2 +
 memory/virtual.c         |  63 +++----
 msdos/int21.c            |  26 ++-
 msdos/vxd.c              |   7 +-
 relay32/kernel32.spec    |   2 +-
 scheduler/client.c       |  26 +--
 scheduler/handle.c       |  28 ---
 scheduler/k32obj.c       |   9 +-
 scheduler/process.c      | 130 +++++++------
 scheduler/synchro.c      |  84 +++++----
 scheduler/thread.c       | 182 ++++++++----------
 server/console.c         | 368 ++++++++++++++++++++++++++++--------
 server/file.c            |  14 ++
 server/process.c         |  72 ++++++-
 server/request.c         | 189 +++++++++++++++++--
 server/thread.c          | 163 +++++++++++++---
 server/trace.c           | 203 +++++++++++++++++++-
 win32/console.c          | 396 ++++++++++++++++++++++-----------------
 win32/device.c           | 115 +++++-------
 win32/process.c          |  39 ----
 33 files changed, 1760 insertions(+), 910 deletions(-)

diff --git a/files/change.c b/files/change.c
index 3dde14cdd0b..6e81b4e7f33 100644
--- a/files/change.c
+++ b/files/change.c
@@ -18,40 +18,12 @@
 #include "server.h"
 #include "debug.h"
 
-static void CHANGE_Destroy( K32OBJ *obj );
-
-const K32OBJ_OPS CHANGE_Ops =
-{
-    CHANGE_Destroy      /* destroy */
-};
-
 /* The change notification object */
 typedef struct
 {
     K32OBJ       header;
-    LPSTR        lpPathName;
-    BOOL32       bWatchSubtree;
-    DWORD        dwNotifyFilter;
-    BOOL32       notify;
 } CHANGE_OBJECT;
 
-/****************************************************************************
- *		CHANGE_Destroy
- */
-static void CHANGE_Destroy( K32OBJ *obj )
-{
-    CHANGE_OBJECT *change = (CHANGE_OBJECT *)obj;
-    assert( obj->type == K32OBJ_CHANGE );
-
-    if ( change->lpPathName )
-    {
-        HeapFree( SystemHeap, 0, change->lpPathName );
-        change->lpPathName = NULL;
-    }
-
-    obj->type = K32OBJ_UNKNOWN;
-    HeapFree( SystemHeap, 0, change );
-}
 
 /****************************************************************************
  *		FindFirstChangeNotification32A (KERNEL32.248)
@@ -76,15 +48,8 @@ HANDLE32 WINAPI FindFirstChangeNotification32A( LPCSTR lpPathName,
         CLIENT_CloseHandle( reply.handle );
         return INVALID_HANDLE_VALUE32;
     }
-
     change->header.type = K32OBJ_CHANGE;
     change->header.refcount = 1;
-
-    change->lpPathName = HEAP_strdupA( SystemHeap, 0, lpPathName );
-    change->bWatchSubtree = bWatchSubtree;
-    change->dwNotifyFilter = dwNotifyFilter;
-    change->notify = FALSE;
-
     return HANDLE_Alloc( PROCESS_Current(), &change->header, 
                          STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE /*FIXME*/,
                          FALSE, reply.handle );
@@ -109,20 +74,10 @@ HANDLE32 WINAPI FindFirstChangeNotification32W( LPCWSTR lpPathName,
  */
 BOOL32 WINAPI FindNextChangeNotification( HANDLE32 handle ) 
 {
-    CHANGE_OBJECT *change;
-
-    SYSTEM_LOCK();
-    if (!(change = (CHANGE_OBJECT *)HANDLE_GetObjPtr( PROCESS_Current(),
-                                                      handle, K32OBJ_CHANGE, 
-                                                      0 /*FIXME*/, NULL )) )
-    {
-        SYSTEM_UNLOCK();
+    if (HANDLE_GetServerHandle( PROCESS_Current(), handle,
+                                K32OBJ_FILE, 0 ) == -1)
         return FALSE;
-    }
-
-    change->notify = FALSE;
-    K32OBJ_DecCount( &change->header );
-    SYSTEM_UNLOCK();
+    /* FIXME: do something */
     return TRUE;
 }
 
diff --git a/files/dos_fs.c b/files/dos_fs.c
index 2bc9be3811a..47d86e26555 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -26,6 +26,8 @@
 #include "heap.h"
 #include "msdos.h"
 #include "syslevel.h"
+#include "server.h"
+#include "process.h"
 #include "debug.h"
 
 /* Define the VFAT ioctl to get both short and long file names */
@@ -602,6 +604,30 @@ const DOS_DEVICE *DOSFS_GetDevice( const char *name )
     return NULL;
 }
 
+
+/***********************************************************************
+ *           DOSFS_GetDeviceByHandle
+ */
+const DOS_DEVICE *DOSFS_GetDeviceByHandle( HFILE32 hFile )
+{
+    struct get_file_info_request req;
+    struct get_file_info_reply reply;
+
+    if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
+                                              K32OBJ_FILE, 0 )) == -1)
+        return NULL;
+    CLIENT_SendRequest( REQ_GET_FILE_INFO, -1, 1, &req, sizeof(req) );
+    if (!CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) &&
+        (reply.type == FILE_TYPE_UNKNOWN))
+    {
+        if ((reply.attr >= 0) &&
+            (reply.attr < sizeof(DOSFS_Devices)/sizeof(DOSFS_Devices[0])))
+            return &DOSFS_Devices[reply.attr];
+    }
+    return NULL;
+}
+
+
 /***********************************************************************
  *           DOSFS_OpenDevice
  *
@@ -651,10 +677,7 @@ HFILE32 DOSFS_OpenDevice( const char *name, DWORD access )
 		if (!strcmp(DOSFS_Devices[i].name,"SCSIMGR$") ||
                     !strcmp(DOSFS_Devices[i].name,"HPSCAN"))
                 {
-                    /* FIXME: should keep the name somewhere */
-                    return FILE_CreateFile( "/dev/null", access,
-                                            FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
-                                            OPEN_EXISTING, 0, -1 );
+                    return FILE_CreateDevice( i, access, NULL );
 		}
 		FIXME(dosfs,"device open %s not supported (yet)\n",DOSFS_Devices[i].name);
     		return HFILE_ERROR32;
diff --git a/files/file.c b/files/file.c
index 2cfe9e2657e..6b61a6047be 100644
--- a/files/file.c
+++ b/files/file.c
@@ -46,74 +46,17 @@
 #define MAP_ANON MAP_ANONYMOUS
 #endif
 
-static void FILE_Destroy( K32OBJ *obj );
-
-const K32OBJ_OPS FILE_Ops =
+/* The file object */
+typedef struct
 {
-    FILE_Destroy       /* destroy */
-};
-
-struct DOS_FILE_LOCK {
-  struct DOS_FILE_LOCK *	next;
-  DWORD				base;
-  DWORD				len;
-  DWORD				processId;
-  FILE_OBJECT *			dos_file;
-  char *			unix_name;
-};
+    K32OBJ    header;
+} FILE_OBJECT;
 
-typedef struct DOS_FILE_LOCK DOS_FILE_LOCK;
-
-static DOS_FILE_LOCK *locks = NULL;
-static void DOS_RemoveFileLocks(FILE_OBJECT *file);
 
 /* Size of per-process table of DOS handles */
 #define DOS_TABLE_SIZE 256
 
 
-/***********************************************************************
- *           FILE_Destroy
- *
- * Destroy a DOS file.
- */
-static void FILE_Destroy( K32OBJ *ptr )
-{
-    FILE_OBJECT *file = (FILE_OBJECT *)ptr;
-    assert( ptr->type == K32OBJ_FILE );
-
-    DOS_RemoveFileLocks(file);
-
-    if (file->unix_name) HeapFree( SystemHeap, 0, file->unix_name );
-    ptr->type = K32OBJ_UNKNOWN;
-    HeapFree( SystemHeap, 0, file );
-}
-
-
-/***********************************************************************
- *           FILE_GetFile
- *
- * Return the DOS file associated to a task file handle. FILE_ReleaseFile must
- * be called to release the file.
- */
-FILE_OBJECT *FILE_GetFile( HFILE32 handle, DWORD access, int *server_handle )
-{
-    return (FILE_OBJECT *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
-                                            K32OBJ_FILE, access,
-                                            server_handle );
-}
-
-
-/***********************************************************************
- *           FILE_ReleaseFile
- *
- * Release a DOS file obtained with FILE_GetFile.
- */
-void FILE_ReleaseFile( FILE_OBJECT *file )
-{
-    K32OBJ_DecCount( &file->header );
-}
-
-
 /***********************************************************************
  *              FILE_ConvertOFMode
  *
@@ -391,7 +334,6 @@ HFILE32 FILE_DupUnixHandle( int fd, DWORD access )
     }
     file->header.type = K32OBJ_FILE;
     file->header.refcount = 0;
-    file->unix_name = NULL;
     return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access,
                          req.inherit, reply.handle );
 }
@@ -448,7 +390,39 @@ HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
     }
     file->header.type = K32OBJ_FILE;
     file->header.refcount = 0;
-    file->unix_name = HEAP_strdupA( SystemHeap, 0, filename );
+    return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access,
+                         req.inherit, reply.handle );
+}
+
+
+/***********************************************************************
+ *           FILE_CreateDevice
+ *
+ * Same as FILE_CreateFile but for a device
+ */
+HFILE32 FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa )
+{
+    FILE_OBJECT *file;
+    struct create_device_request req;
+    struct create_device_reply reply;
+
+    req.access  = access;
+    req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+    req.id      = client_id;
+    CLIENT_SendRequest( REQ_CREATE_DEVICE, -1, 1, &req, sizeof(req) );
+    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
+    if (reply.handle == -1) return INVALID_HANDLE_VALUE32;
+
+    /* Now build the FILE_OBJECT */
+
+    if (!(file = HeapAlloc( SystemHeap, 0, sizeof(FILE_OBJECT) )))
+    {
+        SetLastError( ERROR_OUTOFMEMORY );
+        CLIENT_CloseHandle( reply.handle );
+        return (HFILE32)INVALID_HANDLE_VALUE32;
+    }
+    file->header.type = K32OBJ_FILE;
+    file->header.refcount = 0;
     return HANDLE_Alloc( PROCESS_Current(), &file->header, req.access,
                          req.inherit, reply.handle );
 }
@@ -487,7 +461,6 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing,
                               DWORD attributes, HANDLE32 template )
 {
     DOS_FULL_NAME full_name;
-    HANDLE32 to_dup = HFILE_ERROR32;
 
     if (!filename)
     {
@@ -507,7 +480,8 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing,
 	}
     }
 
-    if (!strncmp(filename, "\\\\.\\", 4)) return DEVICE_Open( filename+4 );
+    if (!strncmp(filename, "\\\\.\\", 4))
+        return DEVICE_Open( filename+4, access, sa );
 
     /* If the name still starts with '\\', it's a UNC name. */
     if (!strncmp(filename, "\\\\", 2))
@@ -517,23 +491,9 @@ HFILE32 WINAPI CreateFile32A( LPCSTR filename, DWORD access, DWORD sharing,
         return HFILE_ERROR32;
     }
 
-    /* If the name is either CONIN$ or CONOUT$, give them duplicated stdin
-     * or stdout, respectively. The lower case version is also allowed. Most likely
-     * this should be a case ignore string compare.
-     */
-    if(!strcasecmp(filename, "CONIN$"))
-	to_dup = GetStdHandle( STD_INPUT_HANDLE );
-    else if(!strcasecmp(filename, "CONOUT$"))
-	to_dup = GetStdHandle( STD_OUTPUT_HANDLE );
-
-    if(to_dup != HFILE_ERROR32)
-    {
-	HFILE32 handle;
-	if (!DuplicateHandle( GetCurrentProcess(), to_dup, GetCurrentProcess(),
-			      &handle, access, FALSE, 0 ))
-	    handle = HFILE_ERROR32;
-	return handle;
-    }
+    /* Open a console for CONIN$ or CONOUT$ */
+    if (!lstrcmpi32A(filename, "CONIN$")) return CONSOLE_OpenHandle( FALSE, access, sa );
+    if (!lstrcmpi32A(filename, "CONOUT$")) return CONSOLE_OpenHandle( TRUE, access, sa );
 
     if (DOSFS_GetDevice( filename ))
     {
@@ -1979,6 +1939,64 @@ BOOL32 WINAPI SetFileTime( HFILE32 hFile,
     return !CLIENT_WaitReply( NULL, NULL, 0 );
 }
 
+
+/**************************************************************************
+ *           LockFile   (KERNEL32.511)
+ */
+BOOL32 WINAPI LockFile( HFILE32 hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
+                        DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh )
+{
+    struct lock_file_request req;
+
+    if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
+                                              K32OBJ_FILE, 0 )) == -1)
+        return FALSE;
+    req.offset_low  = dwFileOffsetLow;
+    req.offset_high = dwFileOffsetHigh;
+    req.count_low   = nNumberOfBytesToLockLow;
+    req.count_high  = nNumberOfBytesToLockHigh;
+    CLIENT_SendRequest( REQ_LOCK_FILE, -1, 1, &req, sizeof(req) );
+    return !CLIENT_WaitReply( NULL, NULL, 0 );
+}
+
+
+/**************************************************************************
+ *           UnlockFile   (KERNEL32.703)
+ */
+BOOL32 WINAPI UnlockFile( HFILE32 hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
+                          DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh )
+{
+    struct unlock_file_request req;
+
+    if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hFile,
+                                              K32OBJ_FILE, 0 )) == -1)
+        return FALSE;
+    req.offset_low  = dwFileOffsetLow;
+    req.offset_high = dwFileOffsetHigh;
+    req.count_low   = nNumberOfBytesToUnlockLow;
+    req.count_high  = nNumberOfBytesToUnlockHigh;
+    CLIENT_SendRequest( REQ_UNLOCK_FILE, -1, 1, &req, sizeof(req) );
+    return !CLIENT_WaitReply( NULL, NULL, 0 );
+}
+
+
+#if 0
+
+struct DOS_FILE_LOCK {
+  struct DOS_FILE_LOCK *	next;
+  DWORD				base;
+  DWORD				len;
+  DWORD				processId;
+  FILE_OBJECT *			dos_file;
+/*  char *			unix_name;*/
+};
+
+typedef struct DOS_FILE_LOCK DOS_FILE_LOCK;
+
+static DOS_FILE_LOCK *locks = NULL;
+static void DOS_RemoveFileLocks(FILE_OBJECT *file);
+
+
 /* Locks need to be mirrored because unix file locking is based
  * on the pid. Inside of wine there can be multiple WINE processes
  * that share the same unix pid.
@@ -1994,6 +2012,7 @@ static BOOL32 DOS_AddLock(FILE_OBJECT *file, struct flock *f)
   processId = GetCurrentProcessId();
 
   /* check if lock overlaps a current lock for the same file */
+#if 0
   for (curr = locks; curr; curr = curr->next) {
     if (strcmp(curr->unix_name, file->unix_name) == 0) {
       if ((f->l_start == curr->base) && (f->l_len == curr->len))
@@ -2005,12 +2024,13 @@ static BOOL32 DOS_AddLock(FILE_OBJECT *file, struct flock *f)
       }
     }
   }
+#endif
 
   curr = HeapAlloc( SystemHeap, 0, sizeof(DOS_FILE_LOCK) );
   curr->processId = GetCurrentProcessId();
   curr->base = f->l_start;
   curr->len = f->l_len;
-  curr->unix_name = HEAP_strdupA( SystemHeap, 0, file->unix_name);
+/*  curr->unix_name = HEAP_strdupA( SystemHeap, 0, file->unix_name);*/
   curr->next = locks;
   curr->dos_file = file;
   locks = curr;
@@ -2029,7 +2049,7 @@ static void DOS_RemoveFileLocks(FILE_OBJECT *file)
     if ((*curr)->dos_file == file) {
       rem = *curr;
       *curr = (*curr)->next;
-      HeapFree( SystemHeap, 0, rem->unix_name );
+/*      HeapFree( SystemHeap, 0, rem->unix_name );*/
       HeapFree( SystemHeap, 0, rem );
     }
     else
@@ -2052,7 +2072,7 @@ static BOOL32 DOS_RemoveLock(FILE_OBJECT *file, struct flock *f)
       /* this is the same lock */
       rem = *curr;
       *curr = (*curr)->next;
-      HeapFree( SystemHeap, 0, rem->unix_name );
+/*      HeapFree( SystemHeap, 0, rem->unix_name );*/
       HeapFree( SystemHeap, 0, rem );
       return TRUE;
     }
@@ -2151,6 +2171,7 @@ BOOL32 WINAPI UnlockFile(
 #endif
   return TRUE;
 }
+#endif
 
 /**************************************************************************
  * GetFileAttributesEx32A [KERNEL32.874]
diff --git a/include/device.h b/include/device.h
index 58834e762cd..456ef22da30 100644
--- a/include/device.h
+++ b/include/device.h
@@ -1,4 +1,5 @@
 #ifndef __WINE_DEVICE_H
 #define __WINE_DEVICE_H
-extern HANDLE32 DEVICE_Open( LPCSTR name);
+extern HANDLE32 DEVICE_Open( LPCSTR filename, DWORD access,
+                             LPSECURITY_ATTRIBUTES sa );
 #endif
diff --git a/include/file.h b/include/file.h
index e6192b5d6fd..6af604ac4f3 100644
--- a/include/file.h
+++ b/include/file.h
@@ -13,13 +13,6 @@
 
 #define MAX_PATHNAME_LEN   1024
 
-/* The file object */
-typedef struct
-{
-    K32OBJ    header;
-    char     *unix_name;
-} FILE_OBJECT;
-
 /* Definition of a full DOS file name */
 typedef struct
 {
@@ -39,9 +32,6 @@ typedef struct
 
 
 /* files/file.c */
-extern FILE_OBJECT *FILE_GetFile( HFILE32 handle, DWORD access,
-                                  int *server_handle );
-extern void FILE_ReleaseFile( FILE_OBJECT *file );
 extern void FILE_SetDosError(void);
 extern HFILE32 FILE_DupUnixHandle( int fd, DWORD access );
 extern BOOL32 FILE_Stat( LPCSTR unixName, BY_HANDLE_FILE_INFORMATION *info );
@@ -49,6 +39,8 @@ extern HFILE16 FILE_Dup2( HFILE16 hFile1, HFILE16 hFile2 );
 extern HFILE32 FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
                                 LPSECURITY_ATTRIBUTES sa, DWORD creation,
                                 DWORD attributes, HANDLE32 template );
+extern HFILE32 FILE_CreateDevice( int client_id, DWORD access,
+                                  LPSECURITY_ATTRIBUTES sa );
 extern LPVOID FILE_dommap( int unix_handle, LPVOID start,
                            DWORD size_high, DWORD size_low,
                            DWORD offset_high, DWORD offset_low,
@@ -71,6 +63,7 @@ extern void DOSFS_UnixTimeToFileTime( time_t unixtime, LPFILETIME ft,
 extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft, DWORD *remainder );
 extern BOOL32 DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer );
 extern const DOS_DEVICE *DOSFS_GetDevice( const char *name );
+extern const DOS_DEVICE *DOSFS_GetDeviceByHandle( HFILE32 hFile );
 extern HFILE32 DOSFS_OpenDevice( const char *name, DWORD access );
 extern BOOL32 DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
                                   INT32 long_len, LPSTR short_buf,
diff --git a/include/process.h b/include/process.h
index e5969a612bc..7454fae4583 100644
--- a/include/process.h
+++ b/include/process.h
@@ -139,8 +139,6 @@ extern K32OBJ *HANDLE_GetObjPtr( PDB32 *pdb, HANDLE32 handle,
                                  int *server_handle );
 extern int HANDLE_GetServerHandle( PDB32 *pdb, HANDLE32 handle,
                                    K32OBJ_TYPE type, DWORD access );
-extern BOOL32 HANDLE_SetObjPtr( PDB32 *pdb, HANDLE32 handle,
-                                K32OBJ *ptr, DWORD access );
 extern void HANDLE_CloseAll( PDB32 *pdb, K32OBJ *ptr );
 
 /* Global handle macros */
@@ -153,6 +151,7 @@ extern void HANDLE_CloseAll( PDB32 *pdb, K32OBJ *ptr );
 /* scheduler/process.c */
 extern BOOL32 PROCESS_Init( void );
 extern PDB32 *PROCESS_Current(void);
+extern BOOL32 PROCESS_IsCurrent( HANDLE32 handle );
 extern PDB32 *PROCESS_Initial(void);
 extern PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle );
 extern PDB32 *PROCESS_IdToPDB( DWORD id );
diff --git a/include/server.h b/include/server.h
index 2f386f2f33c..ea5df051065 100644
--- a/include/server.h
+++ b/include/server.h
@@ -92,9 +92,24 @@ struct get_process_info_request
 };
 struct get_process_info_reply
 {
-    void*        pid;          /* server process id */
-    int          exit_code;    /* process exit code */
+    void*        pid;              /* server process id */
+    int          exit_code;        /* process exit code */
+    int          priority;         /* priority class */
+    int          process_affinity; /* process affinity mask */
+    int          system_affinity;  /* system affinity mask */
+};
+
+
+/* Set a process informations */
+struct set_process_info_request
+{
+    int          handle;       /* process handle */
+    int          mask;         /* setting mask (see below) */
+    int          priority;     /* priority class */
+    int          affinity;     /* affinity mask */
 };
+#define SET_PROCESS_INFO_PRIORITY 0x01
+#define SET_PROCESS_INFO_AFFINITY 0x02
 
 
 /* Retrieve information about a thread */
@@ -106,6 +121,50 @@ struct get_thread_info_reply
 {
     void*        pid;          /* server thread id */
     int          exit_code;    /* thread exit code */
+    int          priority;     /* thread priority level */
+};
+
+
+/* Set a thread informations */
+struct set_thread_info_request
+{
+    int          handle;       /* thread handle */
+    int          mask;         /* setting mask (see below) */
+    int          priority;     /* priority class */
+    int          affinity;     /* affinity mask */
+};
+#define SET_THREAD_INFO_PRIORITY 0x01
+#define SET_THREAD_INFO_AFFINITY 0x02
+
+
+/* Suspend a thread */
+struct suspend_thread_request
+{
+    int          handle;       /* thread handle */
+};
+struct suspend_thread_reply
+{
+    int          count;        /* new suspend count */
+};
+
+
+/* Resume a thread */
+struct resume_thread_request
+{
+    int          handle;       /* thread handle */
+};
+struct resume_thread_reply
+{
+    int          count;        /* new suspend count */
+};
+
+
+/* Queue an APC for a thread */
+struct queue_apc_request
+{
+    int          handle;       /* thread handle */
+    void*        func;         /* function to call */
+    void*        param;        /* param for function to call */
 };
 
 
@@ -160,6 +219,7 @@ struct select_request
 struct select_reply
 {
     int          signaled;     /* signaled handle */
+/*  void*        apcs[]; */    /* async procedures to call */
 };
 #define SELECT_ALL       1
 #define SELECT_ALERTABLE 2
@@ -338,6 +398,28 @@ struct get_file_info_reply
 };
 
 
+/* Lock a region of a file */
+struct lock_file_request
+{
+    int          handle;        /* handle to the file */
+    unsigned int offset_low;    /* offset of start of lock */
+    unsigned int offset_high;   /* offset of start of lock */
+    unsigned int count_low;     /* count of bytes to lock */
+    unsigned int count_high;    /* count of bytes to lock */
+};
+
+
+/* Unlock a region of a file */
+struct unlock_file_request
+{
+    int          handle;        /* handle to the file */
+    unsigned int offset_low;    /* offset of start of unlock */
+    unsigned int offset_high;   /* offset of start of unlock */
+    unsigned int count_low;     /* count of bytes to unlock */
+    unsigned int count_high;    /* count of bytes to unlock */
+};
+
+
 /* Create an anonymous pipe */
 struct create_pipe_request
 {
@@ -350,23 +432,82 @@ struct create_pipe_reply
 };
 
 
-/* Create a console */
-struct create_console_request
+/* Allocate a console for the current process */
+struct alloc_console_request
 {
+};
+
+
+/* Free the console of the current process */
+struct free_console_request
+{
+};
+
+
+/* Open a handle to the process console */
+struct open_console_request
+{
+    int          output;        /* input or output? */
+    unsigned int access;        /* wanted access rights */
     int          inherit;       /* inherit flag */
 };
-struct create_console_reply
+struct open_console_reply
 {
-    int          handle_read;   /* handle to read from the console */
-    int          handle_write;  /* handle to write to the console */
+    int          handle;        /* handle to the console */
 };
 
 
 /* Set a console file descriptor */
 struct set_console_fd_request
+{
+    int          handle;        /* handle to the console */
+    int          pid;           /* pid of xterm (hack) */
+};
+
+
+/* Get a console mode (input or output) */
+struct get_console_mode_request
+{
+    int          handle;        /* handle to the console */
+};
+struct get_console_mode_reply
+{
+    int          mode;          /* console mode */
+};
+
+
+/* Set a console mode (input or output) */
+struct set_console_mode_request
+{
+    int          handle;        /* handle to the console */
+    int          mode;          /* console mode */
+};
+
+
+/* Set info about a console (output only) */
+struct set_console_info_request
+{
+    int          handle;        /* handle to the console */
+    int          mask;          /* setting mask (see below) */
+    int          cursor_size;   /* size of cursor (percentage filled) */
+    int          cursor_visible;/* cursor visibility flag */
+    char         title[0];      /* console title */
+};
+#define SET_CONSOLE_INFO_CURSOR 0x01
+#define SET_CONSOLE_INFO_TITLE  0x02
+
+/* Get info about a console (output only) */
+struct get_console_info_request
 {
     int          handle;        /* handle to the console */
 };
+struct get_console_info_reply
+{
+    int          cursor_size;   /* size of cursor (percentage filled) */
+    int          cursor_visible;/* cursor visibility flag */
+    int          pid;           /* pid of xterm (hack) */
+/*  char         title[0]; */   /* console title */
+};
 
 
 /* Create a change notification */
@@ -417,6 +558,19 @@ struct get_mapping_info_reply
 };
 
 
+/* Create a device */
+struct create_device_request
+{
+    unsigned int access;        /* wanted access rights */
+    int          inherit;       /* inherit flag */
+    int          id;            /* client private id */
+};
+struct create_device_reply
+{
+    int          handle;        /* handle to the device */
+};
+
+
 /* client-side functions */
 
 #ifndef __WINE_SERVER__
@@ -438,7 +592,6 @@ extern int CLIENT_CloseHandle( int handle );
 extern int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process,
                                    int dst_handle, DWORD access, BOOL32 inherit, DWORD options );
 extern int CLIENT_OpenProcess( void *pid, DWORD access, BOOL32 inherit );
-extern int CLIENT_Select( int count, int *handles, int flags, int timeout );
 #endif  /* __WINE_SERVER__ */
 
 #endif  /* __WINE_SERVER_H */
diff --git a/include/server/object.h b/include/server/object.h
index b10682f6659..a48a7a9d882 100644
--- a/include/server/object.h
+++ b/include/server/object.h
@@ -133,6 +133,11 @@ extern void remove_process_thread( struct process *process,
 extern void kill_process( struct process *process, int exit_code );
 extern void get_process_info( struct process *process,
                               struct get_process_info_reply *reply );
+extern void set_process_info( struct process *process,
+                              struct set_process_info_request *req );
+extern int alloc_console( struct process *process );
+extern int free_console( struct process *process );
+extern struct object *get_console( struct process *process, int output );
 
 /* handle functions */
 
@@ -184,6 +189,10 @@ extern int file_get_mmap_fd( struct file *file );
 extern int set_file_pointer( int handle, int *low, int *high, int whence );
 extern int truncate_file( int handle );
 extern int set_file_time( int handle, time_t access_time, time_t write_time );
+extern int file_lock( struct file *file, int offset_high, int offset_low,
+                      int count_high, int count_low );
+extern int file_unlock( struct file *file, int offset_high, int offset_low,
+                        int count_high, int count_low );
 extern void file_set_error(void);
 
 
@@ -195,7 +204,13 @@ extern int create_pipe( struct object *obj[2] );
 /* console functions */
 
 extern int create_console( int fd, struct object *obj[2] );
-extern int set_console_fd( int handle, int fd );
+extern int set_console_fd( int handle, int fd, int pid );
+extern int get_console_mode( int handle, int *mode );
+extern int set_console_mode( int handle, int mode );
+extern int set_console_info( int handle, struct set_console_info_request *req,
+                             const char *title );
+extern int get_console_info( int handle, struct get_console_info_reply *reply,
+                             const char **title );
 
 
 /* change notification functions */
@@ -210,6 +225,10 @@ extern int open_mapping( unsigned int access, int inherit, const char *name );
 extern int get_mapping_info( int handle, struct get_mapping_info_reply *reply );
 
 
+/* device functions */
+extern struct object *create_device( int id );
+
+
 extern int debug_level;
 
 #endif  /* __WINE_SERVER_OBJECT_H */
diff --git a/include/server/request.h b/include/server/request.h
index 30b25b5cc1e..f8c105141e0 100644
--- a/include/server/request.h
+++ b/include/server/request.h
@@ -11,7 +11,12 @@ enum request
     REQ_TERMINATE_PROCESS,
     REQ_TERMINATE_THREAD,
     REQ_GET_PROCESS_INFO,
+    REQ_SET_PROCESS_INFO,
     REQ_GET_THREAD_INFO,
+    REQ_SET_THREAD_INFO,
+    REQ_SUSPEND_THREAD,
+    REQ_RESUME_THREAD,
+    REQ_QUEUE_APC,
     REQ_CLOSE_HANDLE,
     REQ_DUP_HANDLE,
     REQ_OPEN_PROCESS,
@@ -31,12 +36,21 @@ enum request
     REQ_SET_FILE_TIME,
     REQ_FLUSH_FILE,
     REQ_GET_FILE_INFO,
+    REQ_LOCK_FILE,
+    REQ_UNLOCK_FILE,
     REQ_CREATE_PIPE,
-    REQ_CREATE_CONSOLE,
+    REQ_ALLOC_CONSOLE,
+    REQ_FREE_CONSOLE,
+    REQ_OPEN_CONSOLE,
     REQ_SET_CONSOLE_FD,
+    REQ_GET_CONSOLE_MODE,
+    REQ_SET_CONSOLE_MODE,
+    REQ_SET_CONSOLE_INFO,
+    REQ_GET_CONSOLE_INFO,
     REQ_CREATE_CHANGE_NOTIFICATION,
     REQ_CREATE_MAPPING,
     REQ_GET_MAPPING_INFO,
+    REQ_CREATE_DEVICE,
     REQ_NB_REQUESTS
 };
 
@@ -51,7 +65,12 @@ DECL_HANDLER(init_thread);
 DECL_HANDLER(terminate_process);
 DECL_HANDLER(terminate_thread);
 DECL_HANDLER(get_process_info);
+DECL_HANDLER(set_process_info);
 DECL_HANDLER(get_thread_info);
+DECL_HANDLER(set_thread_info);
+DECL_HANDLER(suspend_thread);
+DECL_HANDLER(resume_thread);
+DECL_HANDLER(queue_apc);
 DECL_HANDLER(close_handle);
 DECL_HANDLER(dup_handle);
 DECL_HANDLER(open_process);
@@ -71,12 +90,21 @@ DECL_HANDLER(truncate_file);
 DECL_HANDLER(set_file_time);
 DECL_HANDLER(flush_file);
 DECL_HANDLER(get_file_info);
+DECL_HANDLER(lock_file);
+DECL_HANDLER(unlock_file);
 DECL_HANDLER(create_pipe);
-DECL_HANDLER(create_console);
+DECL_HANDLER(alloc_console);
+DECL_HANDLER(free_console);
+DECL_HANDLER(open_console);
 DECL_HANDLER(set_console_fd);
+DECL_HANDLER(get_console_mode);
+DECL_HANDLER(set_console_mode);
+DECL_HANDLER(set_console_info);
+DECL_HANDLER(get_console_info);
 DECL_HANDLER(create_change_notification);
 DECL_HANDLER(create_mapping);
 DECL_HANDLER(get_mapping_info);
+DECL_HANDLER(create_device);
 
 static const struct handler {
     void       (*handler)();
@@ -88,7 +116,12 @@ static const struct handler {
     { (void(*)())req_terminate_process, sizeof(struct terminate_process_request) },
     { (void(*)())req_terminate_thread, sizeof(struct terminate_thread_request) },
     { (void(*)())req_get_process_info, sizeof(struct get_process_info_request) },
+    { (void(*)())req_set_process_info, sizeof(struct set_process_info_request) },
     { (void(*)())req_get_thread_info, sizeof(struct get_thread_info_request) },
+    { (void(*)())req_set_thread_info, sizeof(struct set_thread_info_request) },
+    { (void(*)())req_suspend_thread, sizeof(struct suspend_thread_request) },
+    { (void(*)())req_resume_thread, sizeof(struct resume_thread_request) },
+    { (void(*)())req_queue_apc, sizeof(struct queue_apc_request) },
     { (void(*)())req_close_handle, sizeof(struct close_handle_request) },
     { (void(*)())req_dup_handle, sizeof(struct dup_handle_request) },
     { (void(*)())req_open_process, sizeof(struct open_process_request) },
@@ -108,12 +141,21 @@ static const struct handler {
     { (void(*)())req_set_file_time, sizeof(struct set_file_time_request) },
     { (void(*)())req_flush_file, sizeof(struct flush_file_request) },
     { (void(*)())req_get_file_info, sizeof(struct get_file_info_request) },
+    { (void(*)())req_lock_file, sizeof(struct lock_file_request) },
+    { (void(*)())req_unlock_file, sizeof(struct unlock_file_request) },
     { (void(*)())req_create_pipe, sizeof(struct create_pipe_request) },
-    { (void(*)())req_create_console, sizeof(struct create_console_request) },
+    { (void(*)())req_alloc_console, sizeof(struct alloc_console_request) },
+    { (void(*)())req_free_console, sizeof(struct free_console_request) },
+    { (void(*)())req_open_console, sizeof(struct open_console_request) },
     { (void(*)())req_set_console_fd, sizeof(struct set_console_fd_request) },
+    { (void(*)())req_get_console_mode, sizeof(struct get_console_mode_request) },
+    { (void(*)())req_set_console_mode, sizeof(struct set_console_mode_request) },
+    { (void(*)())req_set_console_info, sizeof(struct set_console_info_request) },
+    { (void(*)())req_get_console_info, sizeof(struct get_console_info_request) },
     { (void(*)())req_create_change_notification, sizeof(struct create_change_notification_request) },
     { (void(*)())req_create_mapping, sizeof(struct create_mapping_request) },
     { (void(*)())req_get_mapping_info, sizeof(struct get_mapping_info_request) },
+    { (void(*)())req_create_device, sizeof(struct create_device_request) },
 };
 #endif  /* WANT_REQUEST_HANDLERS */
 
diff --git a/include/server/thread.h b/include/server/thread.h
index 1977152ff84..d5f8f00859b 100644
--- a/include/server/thread.h
+++ b/include/server/thread.h
@@ -17,6 +17,7 @@
 
 struct process;
 struct thread_wait;
+struct thread_apc;
 struct mutex;
 
 enum run_state { STARTING, RUNNING, TERMINATED };
@@ -31,11 +32,16 @@ struct thread
     struct process     *process;
     struct mutex       *mutex;     /* list of currently owned mutexes */
     struct thread_wait *wait;      /* current wait condition if sleeping */
+    struct thread_apc  *apc;       /* list of async procedure calls */
+    int                 apc_count; /* number of outstanding APCs */
     int                 error;     /* current error code */
     enum run_state      state;     /* running state */
     int                 exit_code; /* thread exit code */
     int                 client_fd; /* client fd for socket communications */
     int                 unix_pid;  /* Unix pid of client */
+    int                 priority;  /* priority level */
+    int                 affinity;  /* affinity mask */
+    int                 suspend;   /* suspend count */
     enum request        last_req;  /* last request received (for debugging) */
     char               *name;
 };
@@ -50,10 +56,15 @@ extern struct thread *get_thread_from_id( void *id );
 extern struct thread *get_thread_from_handle( int handle, unsigned int access );
 extern void get_thread_info( struct thread *thread,
                              struct get_thread_info_reply *reply );
+extern void set_thread_info( struct thread *thread,
+                             struct set_thread_info_request *req );
+extern int suspend_thread( struct thread *thread );
+extern int resume_thread( struct thread *thread );
 extern int send_reply( struct thread *thread, int pass_fd,
                        int n, ... /* arg_1, len_1, ..., arg_n, len_n */ );
 extern int add_queue( struct object *obj, struct wait_queue_entry *entry );
 extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );
+extern int thread_queue_apc( struct thread *thread, void *func, void *param );
 extern void kill_thread( struct thread *thread, int exit_code );
 extern void thread_killed( struct thread *thread, int exit_code );
 extern void thread_timeout(void);
diff --git a/include/thread.h b/include/thread.h
index 4854b63cfd1..123866411be 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -61,7 +61,6 @@ typedef struct _TEB
 typedef struct
 {
     DWORD         count;     /* Count of valid objects */
-    DWORD         signaled;  /* Index of signaled object (or WAIT_FAILED)*/
     BOOL32        wait_all;  /* Wait for all objects flag */
     K32OBJ       *objs[MAXIMUM_WAIT_OBJECTS];  /* Object pointers */
     int           server[MAXIMUM_WAIT_OBJECTS];  /* Server handles */
@@ -110,8 +109,7 @@ typedef struct _THDB
     CRITICAL_SECTION *sys_mutex[4];/* 1e8 Syslevel mutex pointers */
     DWORD          unknown6[2];    /* 1f8 Unknown */
     /* The following are Wine-specific fields */
-    CONTEXT        context;        /* 200 Thread context */
-    WAIT_STRUCT    wait_struct;    /*     Event wait structure */
+    WAIT_STRUCT    wait_struct;    /* 200 Event wait structure */
     int            socket;         /*     Socket for server communication */
     unsigned int   seq;            /*     Server sequence number */
     void          *server_tid;     /*     Server id for this thread */
@@ -155,7 +153,6 @@ extern THDB *THREAD_Current(void);
 extern BOOL32 THREAD_IsWin16( THDB *thdb );
 extern THDB *THREAD_IdToTHDB( DWORD id );
 extern void THREAD_Start( THDB *thdb );
-extern THDB *THREAD_GetPtr( HANDLE32 handle, DWORD access, int *server_handle );
 extern void THREAD_AddQueue( THREAD_QUEUE *queue, THDB *thread );
 extern void THREAD_RemoveQueue( THREAD_QUEUE *queue, THDB *thread );
 extern DWORD THREAD_TlsAlloc( THDB *thread );
diff --git a/include/winbase.h b/include/winbase.h
index 8df2d66229e..2254b4102e3 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -273,6 +273,8 @@ typedef struct tagCOMMTIMEOUTS {
   
 #pragma pack(4)
 
+typedef VOID (CALLBACK *PAPCFUNC)(ULONG_PTR);
+
 BOOL32      WINAPI ClearCommError(INT32,LPDWORD,LPCOMSTAT);
 BOOL32      WINAPI BuildCommDCB32A(LPCSTR,LPDCB32);
 BOOL32      WINAPI BuildCommDCB32W(LPCWSTR,LPDCB32);
@@ -305,8 +307,9 @@ void      WINAPI LeaveCriticalSection(CRITICAL_SECTION *lpCrit);
 void      WINAPI MakeCriticalSectionGlobal(CRITICAL_SECTION *lpCrit);
 HANDLE32  WINAPI OpenProcess(DWORD access, BOOL32 inherit, DWORD id);
 BOOL32    WINAPI GetProcessWorkingSetSize(HANDLE32,LPDWORD,LPDWORD);
-BOOL32    WINAPI SetProcessWorkingSetSize(HANDLE32,DWORD,DWORD);
+DWORD     WINAPI QueueUserAPC(PAPCFUNC,HANDLE32,ULONG_PTR);
 void      WINAPI RaiseException(DWORD,DWORD,DWORD,const LPDWORD);
+BOOL32    WINAPI SetProcessWorkingSetSize(HANDLE32,DWORD,DWORD);
 BOOL32    WINAPI TerminateProcess(HANDLE32,DWORD);
 BOOL32    WINAPI TerminateThread(HANDLE32,DWORD);
 
diff --git a/include/windows.h b/include/windows.h
index e3885f81311..4431430fd7f 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -4186,6 +4186,7 @@ BOOL32      WINAPI SetPriorityClass(HANDLE32,DWORD);
 BOOL32      WINAPI SetStdHandle(DWORD,HANDLE32);
 BOOL32      WINAPI SetSystemPowerState(BOOL32,BOOL32);
 BOOL32      WINAPI SetSystemTime(const SYSTEMTIME*);
+DWORD       WINAPI SetThreadAffinityMask(HANDLE32,DWORD);
 BOOL32      WINAPI SetThreadPriority(HANDLE32,INT32);
 BOOL32      WINAPI SetTimeZoneInformation(const LPTIME_ZONE_INFORMATION);
 VOID        WINAPI Sleep(DWORD);
diff --git a/include/wintypes.h b/include/wintypes.h
index e64868cb7c8..e456dadd512 100644
--- a/include/wintypes.h
+++ b/include/wintypes.h
@@ -89,6 +89,8 @@ typedef unsigned short  WCHAR;
 typedef unsigned short  BOOL16;
 typedef int             BOOL32;
 typedef double          DATE;
+typedef long            LONG_PTR;
+typedef unsigned long   ULONG_PTR;
 #ifdef __i386__
 typedef double          LONGLONG;
 typedef double          ULONGLONG;
diff --git a/memory/virtual.c b/memory/virtual.c
index a387b9b9137..9bd0c9afe76 100644
--- a/memory/virtual.c
+++ b/memory/virtual.c
@@ -31,7 +31,7 @@
 typedef struct
 {
     K32OBJ        header;
-    FILE_OBJECT  *file;
+    K32OBJ       *file;
 } FILE_MAPPING;
 
 /* File view */
@@ -810,20 +810,12 @@ BOOL32 WINAPI VirtualProtectEx(
               LPVOID addr,     /* [in]  Address of region of committed pages */
               DWORD size,      /* [in]  Size of region */
               DWORD new_prot,  /* [in]  Desired access protection */
-              LPDWORD old_prot /* [out] Address of variable to get old protection */
-) {
-    BOOL32 ret = FALSE;
-
-    PDB32 *pdb = PROCESS_GetPtr( handle, PROCESS_VM_OPERATION, NULL );
-    if (pdb)
-    {
-        if (pdb == PROCESS_Current())
-            ret = VirtualProtect( addr, size, new_prot, old_prot );
-        else
-            ERR(virtual,"Unsupported on other process\n");
-        K32OBJ_DecCount( &pdb->header );
-    }
-    return ret;
+              LPDWORD old_prot /* [out] Address of variable to get old protection */ )
+{
+    if (PROCESS_IsCurrent( handle ))
+        return VirtualProtect( addr, size, new_prot, old_prot );
+    ERR(virtual,"Unsupported on other process\n");
+    return FALSE;
 }
 
 
@@ -907,20 +899,12 @@ DWORD WINAPI VirtualQueryEx(
              HANDLE32 handle,                 /* [in] Handle of process */
              LPCVOID addr,                    /* [in] Address of region */
              LPMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */
-             DWORD len                        /* [in] Size of buffer */
-) {
-    DWORD ret = len;
-
-    PDB32 *pdb = PROCESS_GetPtr( handle, PROCESS_QUERY_INFORMATION, NULL );
-    if (pdb)
-    {
-        if (pdb == PROCESS_Current())
-            ret = VirtualQuery( addr, info, len );
-        else
-            ERR(virtual,"Unsupported on other process\n");
-        K32OBJ_DecCount( &pdb->header );
-    }
-    return ret;
+             DWORD len                        /* [in] Size of buffer */ )
+{
+    if (PROCESS_IsCurrent( handle ))
+        return VirtualQuery( addr, info, len );
+    ERR(virtual,"Unsupported on other process\n");
+    return 0;
 }
 
 
@@ -1079,7 +1063,7 @@ HANDLE32 WINAPI CreateFileMapping32A(
                 LPCSTR name      /* [in] Name of file-mapping object */ )
 {
     FILE_MAPPING *mapping = NULL;
-    FILE_OBJECT *file;
+    K32OBJ *file;
     struct create_mapping_request req;
     struct create_mapping_reply reply = { -1 };
     HANDLE32 handle;
@@ -1172,7 +1156,9 @@ HANDLE32 WINAPI CreateFileMapping32A(
             ((protect & 0xff) == PAGE_EXECUTE_READWRITE) ||
             ((protect & 0xff) == PAGE_EXECUTE_WRITECOPY))
                 access |= GENERIC_WRITE;
-        if (!(file = FILE_GetFile( hFile, access, &req.handle ))) goto error;
+
+        if (!(file = HANDLE_GetObjPtr( PROCESS_Current(), hFile, K32OBJ_FILE,
+                                       access, &req.handle ))) goto error;
         if (!GetFileInformationByHandle( hFile, &info )) goto error;
         if (!size_high && !size_low)
         {
@@ -1218,7 +1204,7 @@ HANDLE32 WINAPI CreateFileMapping32A(
 
 error:
     if (reply.handle != -1) CLIENT_CloseHandle( reply.handle );
-    if (file) K32OBJ_DecCount( &file->header );
+    if (file) K32OBJ_DecCount( file );
     if (mapping) HeapFree( SystemHeap, 0, mapping );
     return 0;
 }
@@ -1305,7 +1291,7 @@ static void VIRTUAL_DestroyMapping( K32OBJ *ptr )
     FILE_MAPPING *mapping = (FILE_MAPPING *)ptr;
     assert( ptr->type == K32OBJ_MEM_MAPPED_FILE );
 
-    if (mapping->file) K32OBJ_DecCount( &mapping->file->header );
+    if (mapping->file) K32OBJ_DecCount( mapping->file );
     ptr->type = K32OBJ_UNKNOWN;
     HeapFree( SystemHeap, 0, mapping );
 }
@@ -1347,7 +1333,6 @@ LPVOID WINAPI MapViewOfFileEx(
               DWORD count,       /* [in] Number of bytes to map */
               LPVOID addr        /* [in] Suggested starting address for mapped view */
 ) {
-    FILE_MAPPING *mapping;
     FILE_VIEW *view;
     UINT32 ptr = (UINT32)-1, size = 0;
     int flags = MAP_PRIVATE;
@@ -1364,12 +1349,8 @@ LPVOID WINAPI MapViewOfFileEx(
         return NULL;
     }
 
-    if (!(mapping = (FILE_MAPPING *)HANDLE_GetObjPtr( PROCESS_Current(),
-                                                      handle,
-                                                      K32OBJ_MEM_MAPPED_FILE,
-                                                      0  /* FIXME */, &req.handle )))
-        return NULL;
-
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
+                                         K32OBJ_MEM_MAPPED_FILE, 0 /* FIXME */ );
     CLIENT_SendRequest( REQ_GET_MAPPING_INFO, -1, 1, &req, sizeof(req) );
     if (CLIENT_WaitSimpleReply( &info, sizeof(info), &unix_handle ))
         goto error;
@@ -1438,13 +1419,11 @@ LPVOID WINAPI MapViewOfFileEx(
         goto error;
     }
     if (unix_handle != -1) close( unix_handle );
-    K32OBJ_DecCount( &mapping->header );
     return (LPVOID)ptr;
 
 error:
     if (unix_handle != -1) close( unix_handle );
     if (ptr != (UINT32)-1) FILE_munmap( (void *)ptr, 0, size );
-    K32OBJ_DecCount( &mapping->header );
     return NULL;
 }
 
diff --git a/msdos/int21.c b/msdos/int21.c
index 2b011691a68..809d71073b5 100644
--- a/msdos/int21.c
+++ b/msdos/int21.c
@@ -218,22 +218,17 @@ static void GetDrivePB( CONTEXT *context, int drive )
 static void ioctlGetDeviceInfo( CONTEXT *context )
 {
     int curr_drive;
-    FILE_OBJECT *file;
+    const DOS_DEVICE *dev;
 
     TRACE(int21, "(%d)\n", BX_reg(context));
     
     RESET_CFLAG(context);
 
     /* DOS device ? */
-    if ((file = FILE_GetFile( FILE_GetHandle32(BX_reg(context)), 0, NULL )))
+    if ((dev = DOSFS_GetDeviceByHandle( FILE_GetHandle32(BX_reg(context)) )))
     {
-        const DOS_DEVICE *dev = DOSFS_GetDevice( file->unix_name );
-        FILE_ReleaseFile( file );
-        if (dev)
-        {
-	    DX_reg(context) = dev->flags;
-	    return;
-        }
+        DX_reg(context) = dev->flags;
+        return;
     }
 
     /* it seems to be a file */
@@ -1559,12 +1554,13 @@ void WINAPI DOS3Call( CONTEXT *context )
         case 0x01:
             break;
         case 0x02:{
-           FILE_OBJECT *file;
-           file = FILE_GetFile(FILE_GetHandle32(BX_reg(context)),0,NULL);
-           if (!strcasecmp(file->unix_name, "SCSIMGR$"))
-                        ASPI_DOS_HandleInt(context);
-           FILE_ReleaseFile( file );
-           break;
+            const DOS_DEVICE *dev;
+            if ((dev = DOSFS_GetDeviceByHandle( FILE_GetHandle32(BX_reg(context)) )) &&
+                !strcasecmp( dev->name, "SCSIMGR$" ))
+            {
+                ASPI_DOS_HandleInt(context);
+            }
+            break;
        }
 	case 0x05:{	/* IOCTL - WRITE TO BLOCK DEVICE CONTROL CHANNEL */
 	    /*BYTE *dataptr = CTX_SEG_OFF_TO_LIN(context, DS_reg(context),EDX_reg(context));*/
diff --git a/msdos/vxd.c b/msdos/vxd.c
index 420bb50773e..8022a548941 100644
--- a/msdos/vxd.c
+++ b/msdos/vxd.c
@@ -1123,12 +1123,13 @@ void VXD_Win32s( CONTEXT *context )
     {
         DWORD *stack    = (DWORD *)W32S_APP2WINE(EDX_reg(context), W32S_OFFSET);
         HANDLE32 handle = stack[0];
+        HANDLE32 new_handle;
 
         TRACE(vxd, "NtDupSection(%lx)\n", (DWORD)handle);
  
-        /* Handle is 'duplicated' by incrementing RefCount */
-        HANDLE_GetObjPtr(PROCESS_Current(), handle, K32OBJ_MEM_MAPPED_FILE, 0,NULL);
-
+        DuplicateHandle( GetCurrentProcess(), handle,
+                         GetCurrentProcess(), &new_handle,
+                         0, FALSE, DUPLICATE_SAME_ACCESS );
         EAX_reg(context) = STATUS_SUCCESS;
     }
     break;
diff --git a/relay32/kernel32.spec b/relay32/kernel32.spec
index b82cb2032ab..c4d1dedaa4a 100644
--- a/relay32/kernel32.spec
+++ b/relay32/kernel32.spec
@@ -581,7 +581,7 @@ init	MAIN_KernelInit
 563 stub QueryOldestEventLogRecord
 564 stdcall QueryPerformanceCounter(ptr) QueryPerformanceCounter
 565 stdcall QueryPerformanceFrequency(ptr) QueryPerformanceFrequency
-566 stub QueueUserAPC
+566 stdcall QueueUserAPC(ptr long long) QueueUserAPC
 567 register RaiseException() RaiseException
 568 stdcall ReadConsoleA(long ptr long ptr ptr) ReadConsole32A
 569 stdcall ReadConsoleInputA(long ptr long ptr) ReadConsoleInput32A
diff --git a/scheduler/client.c b/scheduler/client.c
index 24fdfa4ebce..2c27f7a9412 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -6,6 +6,7 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
@@ -267,7 +268,7 @@ int CLIENT_NewThread( THDB *thdb, int *thandle, int *phandle )
         case 0:  /* child */
             close( tmpfd[0] );
             sprintf( buffer, "%d", tmpfd[1] );
-/*#define EXEC_SERVER*/
+#define EXEC_SERVER
 #ifdef EXEC_SERVER
             execlp( "wineserver", "wineserver", buffer, NULL );
             execl( "/usr/local/bin/wineserver", "wineserver", buffer, NULL );
@@ -299,6 +300,7 @@ int CLIENT_NewThread( THDB *thdb, int *thandle, int *phandle )
     if (thdb->socket != -1) close( thdb->socket );
     thdb->socket = fd[0];
     thdb->seq = 0;  /* reset the sequence number for the new fd */
+    fcntl( fd[0], F_SETFD, 1 ); /* set close on exec flag */
 
     if (thandle) *thandle = reply.thandle;
     else if (reply.thandle != -1) CLIENT_CloseHandle( reply.thandle );
@@ -365,7 +367,6 @@ int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process, in
 {
     struct dup_handle_request req;
     struct dup_handle_reply reply;
-    int len;
 
     req.src_process = src_process;
     req.src_handle  = src_handle;
@@ -399,24 +400,3 @@ int CLIENT_OpenProcess( void *pid, DWORD access, BOOL32 inherit )
     CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
     return reply.handle;
 }
-
-
-/***********************************************************************
- *           CLIENT_Select
- */
-int CLIENT_Select( int count, int *handles, int flags, int timeout )
-{
-    struct select_request req;
-    struct select_reply reply;
-    int len;
-
-    req.count   = count;
-    req.flags   = flags;
-    req.timeout = timeout;
-
-    CLIENT_SendRequest( REQ_SELECT, -1, 2,
-                        &req, sizeof(req),
-                        handles, count * sizeof(int) );
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-    return reply.signaled;
-}
diff --git a/scheduler/handle.c b/scheduler/handle.c
index 80257ccbf88..7e58820958f 100644
--- a/scheduler/handle.c
+++ b/scheduler/handle.c
@@ -212,34 +212,6 @@ int HANDLE_GetServerHandle( PDB32 *pdb, HANDLE32 handle,
 }
 
 
-/***********************************************************************
- *           HANDLE_SetObjPtr
- *
- * Change the object pointer of a handle, and increment the refcount.
- * Use with caution!
- */
-BOOL32 HANDLE_SetObjPtr( PDB32 *pdb, HANDLE32 handle, K32OBJ *ptr,
-                         DWORD access )
-{
-    BOOL32 ret = FALSE;
-
-    SYSTEM_LOCK();
-    if ((handle > 0) && (handle < pdb->handle_table->count))
-    {
-        HANDLE_ENTRY *entry = &pdb->handle_table->entries[handle];
-        K32OBJ *old_ptr = entry->ptr;
-        K32OBJ_IncCount( ptr );
-        entry->access = access;
-        entry->ptr    = ptr;
-        if (old_ptr) K32OBJ_DecCount( old_ptr );
-        ret = TRUE;
-    }
-    SYSTEM_UNLOCK();
-    if (!ret) SetLastError( ERROR_INVALID_HANDLE );
-    return ret;
-}
-
-
 /*********************************************************************
  *           HANDLE_GetAccess
  */
diff --git a/scheduler/k32obj.c b/scheduler/k32obj.c
index 35f5be39d7d..e64cb89344d 100644
--- a/scheduler/k32obj.c
+++ b/scheduler/k32obj.c
@@ -15,10 +15,7 @@
 /* The declarations are here to avoid including a lot of unnecessary files */
 extern const K32OBJ_OPS PROCESS_Ops;
 extern const K32OBJ_OPS THREAD_Ops;
-extern const K32OBJ_OPS FILE_Ops;
-extern const K32OBJ_OPS CHANGE_Ops;
 extern const K32OBJ_OPS MEM_MAPPED_FILE_Ops;
-extern const K32OBJ_OPS DEVICE_Ops;
 extern const K32OBJ_OPS CONSOLE_Ops;
 extern const K32OBJ_OPS SNAPSHOT_Ops;
 
@@ -44,13 +41,13 @@ const K32OBJ_OPS * const K32OBJ_Ops[K32OBJ_NBOBJECTS] =
     &K32OBJ_NullOps,        /* K32OBJ_CRITICAL_SECTION */
     &PROCESS_Ops,           /* K32OBJ_PROCESS */
     &THREAD_Ops,            /* K32OBJ_THREAD */
-    &FILE_Ops,              /* K32OBJ_FILE */
-    &CHANGE_Ops,            /* K32OBJ_CHANGE */
+    &K32OBJ_DefaultOps,     /* K32OBJ_FILE */
+    &K32OBJ_DefaultOps,     /* K32OBJ_CHANGE */
     &CONSOLE_Ops,           /* K32OBJ_CONSOLE */
     &K32OBJ_NullOps,        /* K32OBJ_SCREEN_BUFFER */
     &MEM_MAPPED_FILE_Ops,   /* K32OBJ_MEM_MAPPED_FILE */
     &K32OBJ_NullOps,        /* K32OBJ_SERIAL */
-    &DEVICE_Ops,            /* K32OBJ_DEVICE_IOCTL */
+    &K32OBJ_NullOps,        /* K32OBJ_DEVICE_IOCTL */
     &K32OBJ_DefaultOps,     /* K32OBJ_PIPE */
     &K32OBJ_NullOps,        /* K32OBJ_MAILSLOT */
     &K32OBJ_NullOps,        /* K32OBJ_TOOLHELP_SNAPSHOT */
diff --git a/scheduler/process.c b/scheduler/process.c
index b49c00a00ef..41736ddecd9 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -66,6 +66,33 @@ PDB32 *PROCESS_GetPtr( HANDLE32 handle, DWORD access, int *server_handle )
                                      K32OBJ_PROCESS, access, server_handle );
 }
 
+/***********************************************************************
+ *           PROCESS_QueryInfo
+ *
+ * Retrieve information about a process
+ */
+static BOOL32 PROCESS_QueryInfo( HANDLE32 handle,
+                                 struct get_process_info_reply *reply )
+{
+    struct get_process_info_request req;
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
+                                         K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
+    CLIENT_SendRequest( REQ_GET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
+    return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
+}
+
+/***********************************************************************
+ *           PROCESS_IsCurrent
+ *
+ * Check if a handle is to the current process
+ */
+BOOL32 PROCESS_IsCurrent( HANDLE32 handle )
+{
+    struct get_process_info_reply reply;
+    return (PROCESS_QueryInfo( handle, &reply ) &&
+            (reply.pid == PROCESS_Current()->server_pid));
+}
+
 
 /***********************************************************************
  *           PROCESS_IdToPDB
@@ -599,28 +626,14 @@ LCID WINAPI GetThreadLocale(void)
  */
 BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
 {
-    PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_SET_INFORMATION, NULL );
-    if (!pdb) return FALSE;
-    switch (priorityclass)
-    {
-    case NORMAL_PRIORITY_CLASS:
-    	pdb->priority = 0x00000008;
-	break;
-    case IDLE_PRIORITY_CLASS:
-    	pdb->priority = 0x00000004;
-	break;
-    case HIGH_PRIORITY_CLASS:
-    	pdb->priority = 0x0000000d;
-	break;
-    case REALTIME_PRIORITY_CLASS:
-    	pdb->priority = 0x00000018;
-    	break;
-    default:
-    	WARN(process,"Unknown priority class %ld\n",priorityclass);
-	break;
-    }
-    K32OBJ_DecCount( &pdb->header );
-    return TRUE;
+    struct set_process_info_request req;
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hprocess,
+                                         K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
+    if (req.handle == -1) return FALSE;
+    req.priority = priorityclass;
+    req.mask     = SET_PROCESS_INFO_PRIORITY;
+    CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
+    return !CLIENT_WaitReply( NULL, NULL, 0 );
 }
 
 
@@ -629,30 +642,39 @@ BOOL32 WINAPI SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
  */
 DWORD WINAPI GetPriorityClass(HANDLE32 hprocess)
 {
-    PDB32 *pdb = PROCESS_GetPtr( hprocess, PROCESS_QUERY_INFORMATION, NULL );
-    DWORD ret = 0;
-    if (pdb)
-    {
-    	switch (pdb->priority)
-        {
-	case 0x00000008:
-	    ret = NORMAL_PRIORITY_CLASS;
-	    break;
-	case 0x00000004:
-	    ret = IDLE_PRIORITY_CLASS;
-	    break;
-	case 0x0000000d:
-	    ret = HIGH_PRIORITY_CLASS;
-	    break;
-	case 0x00000018:
-	    ret = REALTIME_PRIORITY_CLASS;
-	    break;
-	default:
-	    WARN(process,"Unknown priority %ld\n",pdb->priority);
-	}
-	K32OBJ_DecCount( &pdb->header );
-    }
-    return ret;
+    struct get_process_info_reply reply;
+    if (!PROCESS_QueryInfo( hprocess, &reply )) return 0;
+    return reply.priority;
+}
+
+
+/***********************************************************************
+ *          SetProcessAffinityMask   (KERNEL32.662)
+ */
+BOOL32 WINAPI SetProcessAffinityMask( HANDLE32 hProcess, DWORD affmask )
+{
+    struct set_process_info_request req;
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
+                                         K32OBJ_PROCESS, PROCESS_SET_INFORMATION );
+    if (req.handle == -1) return FALSE;
+    req.affinity = affmask;
+    req.mask     = SET_PROCESS_INFO_AFFINITY;
+    CLIENT_SendRequest( REQ_SET_PROCESS_INFO, -1, 1, &req, sizeof(req) );
+    return !CLIENT_WaitReply( NULL, NULL, 0 );
+}
+
+/**********************************************************************
+ *          GetProcessAffinityMask    (KERNEL32.373)
+ */
+BOOL32 WINAPI GetProcessAffinityMask( HANDLE32 hProcess,
+                                      LPDWORD lpProcessAffinityMask,
+                                      LPDWORD lpSystemAffinityMask )
+{
+    struct get_process_info_reply reply;
+    if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
+    if (lpProcessAffinityMask) *lpProcessAffinityMask = reply.process_affinity;
+    if (lpSystemAffinityMask) *lpSystemAffinityMask = reply.system_affinity;
+    return TRUE;
 }
 
 
@@ -720,15 +742,6 @@ DWORD WINAPI GetProcessFlags( DWORD processid )
     return pdb->flags;
 }
 
-/***********************************************************************
- *		SetProcessAffinityMask	[KERNEL32.662]
- */
-BOOL32 WINAPI SetProcessAffinityMask(HANDLE32 hProcess,DWORD affmask)
-{
-    FIXME(process,"(0x%08x,%ld), stub - harmless\n",hProcess,affmask);
-    return TRUE;
-}
-
 /***********************************************************************
  *		SetProcessWorkingSetSize	[KERNEL32.662]
  * Sets the min/max working set sizes for a specified process.
@@ -867,15 +880,12 @@ BOOL32 WINAPI GetExitCodeProcess(
     LPDWORD lpExitCode) /* [O] address to receive termination status */
 {
     struct get_process_info_reply reply;
-    int handle = HANDLE_GetServerHandle( PROCESS_Current(), hProcess,
-                                         K32OBJ_PROCESS, PROCESS_QUERY_INFORMATION );
-
-    CLIENT_SendRequest( REQ_GET_PROCESS_INFO, -1, 1, &handle, sizeof(handle) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
+    if (!PROCESS_QueryInfo( hProcess, &reply )) return FALSE;
     if (lpExitCode) *lpExitCode = reply.exit_code;
     return TRUE;
 }
 
+
 /***********************************************************************
  * GetProcessHeaps [KERNEL32.376]
  */
diff --git a/scheduler/synchro.c b/scheduler/synchro.c
index 9f0dbce3e22..eb262d6b234 100644
--- a/scheduler/synchro.c
+++ b/scheduler/synchro.c
@@ -28,7 +28,6 @@ static BOOL32 SYNC_BuildWaitStruct( DWORD count, const HANDLE32 *handles,
 
     SYSTEM_LOCK();
     wait->count    = count;
-    wait->signaled = WAIT_FAILED;
     wait->wait_all = wait_all;
     for (i = 0, ptr = wait->objs; i < count; i++, ptr++)
     {
@@ -67,44 +66,12 @@ static void SYNC_FreeWaitStruct( WAIT_STRUCT *wait )
     SYSTEM_UNLOCK();
 }
 
-
-/***********************************************************************
- *           SYNC_DoWait
- */
-static DWORD SYNC_DoWait( DWORD count, const HANDLE32 *handles,
-                          BOOL32 wait_all, DWORD timeout, BOOL32 alertable )
-{
-    WAIT_STRUCT *wait = &THREAD_Current()->wait_struct;
-
-    if (count > MAXIMUM_WAIT_OBJECTS)
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return WAIT_FAILED;
-    }
-
-    if (alertable)
-        FIXME(win32, "alertable not implemented\n" );
-
-    if (!SYNC_BuildWaitStruct( count, handles, wait_all, wait ))
-        wait->signaled = WAIT_FAILED;
-    else
-    {
-        int flags = 0;
-        if (wait_all) flags |= SELECT_ALL;
-        if (alertable) flags |= SELECT_ALERTABLE;
-        if (timeout != INFINITE32) flags |= SELECT_TIMEOUT;
-        wait->signaled = CLIENT_Select( count, wait->server, flags, timeout );
-        SYNC_FreeWaitStruct( wait );
-    }
-    return wait->signaled;
-}
-
 /***********************************************************************
  *              Sleep  (KERNEL32.679)
  */
 VOID WINAPI Sleep( DWORD timeout )
 {
-    SYNC_DoWait( 0, NULL, FALSE, timeout, FALSE );
+    WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, FALSE );
 }
 
 /******************************************************************************
@@ -112,7 +79,7 @@ VOID WINAPI Sleep( DWORD timeout )
  */
 DWORD WINAPI SleepEx( DWORD timeout, BOOL32 alertable )
 {
-    DWORD ret = SYNC_DoWait( 0, NULL, FALSE, timeout, alertable );
+    DWORD ret = WaitForMultipleObjectsEx( 0, NULL, FALSE, timeout, alertable );
     if (ret != WAIT_IO_COMPLETION) ret = 0;
     return ret;
 }
@@ -123,7 +90,7 @@ DWORD WINAPI SleepEx( DWORD timeout, BOOL32 alertable )
  */
 DWORD WINAPI WaitForSingleObject( HANDLE32 handle, DWORD timeout )
 {
-    return SYNC_DoWait( 1, &handle, FALSE, timeout, FALSE );
+    return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, FALSE );
 }
 
 
@@ -133,7 +100,7 @@ DWORD WINAPI WaitForSingleObject( HANDLE32 handle, DWORD timeout )
 DWORD WINAPI WaitForSingleObjectEx( HANDLE32 handle, DWORD timeout,
                                     BOOL32 alertable )
 {
-    return SYNC_DoWait( 1, &handle, FALSE, timeout, alertable );
+    return WaitForMultipleObjectsEx( 1, &handle, FALSE, timeout, alertable );
 }
 
 
@@ -143,7 +110,7 @@ DWORD WINAPI WaitForSingleObjectEx( HANDLE32 handle, DWORD timeout,
 DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE32 *handles,
                                      BOOL32 wait_all, DWORD timeout )
 {
-    return SYNC_DoWait( count, handles, wait_all, timeout, FALSE );
+    return WaitForMultipleObjectsEx( count, handles, wait_all, timeout, FALSE );
 }
 
 
@@ -154,7 +121,46 @@ DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE32 *handles,
                                        BOOL32 wait_all, DWORD timeout,
                                        BOOL32 alertable )
 {
-    return SYNC_DoWait( count, handles, wait_all, timeout, alertable );
+    WAIT_STRUCT *wait = &THREAD_Current()->wait_struct;
+    struct select_request req;
+    struct select_reply reply;
+    void *apc[32];
+    int len;
+
+    if (count > MAXIMUM_WAIT_OBJECTS)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return WAIT_FAILED;
+    }
+
+    if (!SYNC_BuildWaitStruct( count, handles, wait_all, wait ))
+        return WAIT_FAILED;
+
+    req.count   = count;
+    req.flags   = 0;
+    req.timeout = timeout;
+
+    if (wait_all) req.flags |= SELECT_ALL;
+    if (alertable) req.flags |= SELECT_ALERTABLE;
+    if (timeout != INFINITE32) req.flags |= SELECT_TIMEOUT;
+
+    CLIENT_SendRequest( REQ_SELECT, -1, 2,
+                        &req, sizeof(req),
+                        wait->server, count * sizeof(int) );
+    CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply),
+                      apc, sizeof(apc) );
+    if ((reply.signaled == STATUS_USER_APC) && (len > sizeof(reply)))
+    {
+        int i;
+        len -= sizeof(reply);
+        for (i = 0; i < len / sizeof(void*); i += 2)
+        {
+            PAPCFUNC func = (PAPCFUNC)apc[i];
+            func( (ULONG_PTR)apc[i+1] );
+        }
+    }
+    SYNC_FreeWaitStruct( wait );
+    return reply.signaled;
 }
 
 
diff --git a/scheduler/thread.c b/scheduler/thread.c
index d89b77f4aa7..2241747f290 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -35,18 +35,6 @@ const K32OBJ_OPS THREAD_Ops =
 /* Is threading code initialized? */
 BOOL32 THREAD_InitDone = FALSE;
 
-/**********************************************************************
- *           THREAD_GetPtr
- *
- * Return a pointer to a thread object. The object count must be decremented
- * when no longer used.
- */
-THDB *THREAD_GetPtr( HANDLE32 handle, DWORD access, int *server_handle )
-{
-    return (THDB *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
-                                    K32OBJ_THREAD, access, server_handle );
-}
-
 
 /***********************************************************************
  *           THREAD_Current
@@ -161,7 +149,6 @@ THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size, BOOL32 alloc_stack16,
                      LPTHREAD_START_ROUTINE start_addr, LPVOID param )
 {
     DWORD old_prot;
-    WORD cs, ds;
 
     THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) );
     if (!thdb) return NULL;
@@ -236,19 +223,6 @@ THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size, BOOL32 alloc_stack16,
     if (!(thdb->event = CreateEvent32A( NULL, FALSE, FALSE, NULL ))) goto error;
     thdb->event = ConvertToGlobalHandle( thdb->event );
 
-    /* Initialize the thread context */
-
-    GET_CS(cs);
-    GET_DS(ds);
-    thdb->pcontext        = &thdb->context;
-    thdb->context.SegCs   = cs;
-    thdb->context.SegDs   = ds;
-    thdb->context.SegEs   = ds;
-    thdb->context.SegGs   = ds;
-    thdb->context.SegSs   = ds;
-    thdb->context.SegFs   = thdb->teb_sel;
-    thdb->context.Eip     = (DWORD)start_addr;
-    thdb->context.Esp     = (DWORD)thdb->teb.stack_top;
     PE_InitTls( thdb );
     return thdb;
 
@@ -588,10 +562,7 @@ BOOL32 WINAPI SetThreadContext(
     HANDLE32 handle,  /* [in]  Handle to thread with context */
     CONTEXT *context) /* [out] Address of context structure */
 {
-    THDB *thread = THREAD_GetPtr( handle, THREAD_GET_CONTEXT, NULL );
-    if (!thread) return FALSE;
-    *context = thread->context;
-    K32OBJ_DecCount( &thread->header );
+    FIXME( thread, "not implemented\n" );
     return TRUE;
 }
 
@@ -606,10 +577,19 @@ BOOL32 WINAPI GetThreadContext(
     HANDLE32 handle,  /* [in]  Handle to thread with context */
     CONTEXT *context) /* [out] Address of context structure */
 {
-    THDB *thread = THREAD_GetPtr( handle, THREAD_GET_CONTEXT, NULL );
-    if (!thread) return FALSE;
-    *context = thread->context;
-    K32OBJ_DecCount( &thread->header );
+    WORD cs, ds;
+
+    FIXME( thread, "returning dummy info\n" );
+
+    /* make up some plausible values for segment registers */
+    GET_CS(cs);
+    GET_DS(ds);
+    context->SegCs   = cs;
+    context->SegDs   = ds;
+    context->SegEs   = ds;
+    context->SegGs   = ds;
+    context->SegSs   = ds;
+    context->SegFs   = ds;
     return TRUE;
 }
 
@@ -624,14 +604,14 @@ BOOL32 WINAPI GetThreadContext(
 INT32 WINAPI GetThreadPriority(
     HANDLE32 hthread) /* [in] Handle to thread */
 {
-    THDB *thread;
-    INT32 ret;
-    
-    if (!(thread = THREAD_GetPtr( hthread, THREAD_QUERY_INFORMATION, NULL )))
+    struct get_thread_info_request req;
+    struct get_thread_info_reply reply;
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
+                                         K32OBJ_THREAD, THREAD_QUERY_INFORMATION );
+    CLIENT_SendRequest( REQ_GET_THREAD_INFO, -1, 1, &req, sizeof(req) );
+    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ))
         return THREAD_PRIORITY_ERROR_RETURN;
-    ret = thread->delta_priority;
-    K32OBJ_DecCount( &thread->header );
-    return ret;
+    return reply.priority;
 }
 
 
@@ -646,13 +626,31 @@ BOOL32 WINAPI SetThreadPriority(
     HANDLE32 hthread, /* [in] Handle to thread */
     INT32 priority)   /* [in] Thread priority level */
 {
-    THDB *thread;
-    
-    if (!(thread = THREAD_GetPtr( hthread, THREAD_SET_INFORMATION, NULL )))
-        return FALSE;
-    thread->delta_priority = priority;
-    K32OBJ_DecCount( &thread->header );
-    return TRUE;
+    struct set_thread_info_request req;
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
+                                         K32OBJ_THREAD, THREAD_SET_INFORMATION );
+    if (req.handle == -1) return FALSE;
+    req.priority = priority;
+    req.mask     = SET_THREAD_INFO_PRIORITY;
+    CLIENT_SendRequest( REQ_SET_THREAD_INFO, -1, 1, &req, sizeof(req) );
+    return !CLIENT_WaitReply( NULL, NULL, 0 );
+}
+
+
+/**********************************************************************
+ *           SetThreadAffinityMask   (KERNEL32.669)
+ */
+DWORD WINAPI SetThreadAffinityMask( HANDLE32 hThread, DWORD dwThreadAffinityMask )
+{
+    struct set_thread_info_request req;
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hThread,
+                                         K32OBJ_THREAD, THREAD_SET_INFORMATION );
+    if (req.handle == -1) return FALSE;
+    req.affinity = dwThreadAffinityMask;
+    req.mask     = SET_THREAD_INFO_AFFINITY;
+    CLIENT_SendRequest( REQ_SET_THREAD_INFO, -1, 1, &req, sizeof(req) );
+    if (CLIENT_WaitReply( NULL, NULL, 0 )) return 0;
+    return 1;  /* FIXME: should return previous value */
 }
 
 
@@ -688,10 +686,11 @@ BOOL32 WINAPI GetExitCodeThread(
     HANDLE32 hthread, /* [in]  Handle to thread */
     LPDWORD exitcode) /* [out] Address to receive termination status */
 {
+    struct get_thread_info_request req;
     struct get_thread_info_reply reply;
-    int handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
                                          K32OBJ_THREAD, THREAD_QUERY_INFORMATION );
-    CLIENT_SendRequest( REQ_GET_THREAD_INFO, -1, 1, &handle, sizeof(handle) );
+    CLIENT_SendRequest( REQ_GET_THREAD_INFO, -1, 1, &req, sizeof(req) );
     if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
     if (exitcode) *exitcode = reply.exit_code;
     return TRUE;
@@ -710,33 +709,15 @@ BOOL32 WINAPI GetExitCodeThread(
  *    Already running: 0
  */
 DWORD WINAPI ResumeThread(
-    HANDLE32 hthread) /* [in] Indentifies thread to restart */
+    HANDLE32 hthread) /* [in] Identifies thread to restart */
 {
-    THDB *thread;
-    DWORD oldcount;
-
-    SYSTEM_LOCK();
-    if (!(thread = THREAD_GetPtr( hthread, THREAD_QUERY_INFORMATION, NULL )))
-    {
-        SYSTEM_UNLOCK();
-        WARN(thread, "Invalid thread handle\n");
-	return 0xFFFFFFFF;
-    }
-    if ((oldcount = thread->suspend_count) != 0)
-    {
-        if (!--thread->suspend_count)
-        {
-            if (kill(thread->unix_pid, SIGCONT))
-            {
-                WARN(thread, "Unable to CONTinue pid: %04x\n",
-                     thread->unix_pid);
-                oldcount = 0xFFFFFFFF;
-            }
-        }
-    }
-    K32OBJ_DecCount(&thread->header);
-    SYSTEM_UNLOCK();
-    return oldcount;
+    struct resume_thread_request req;
+    struct resume_thread_reply reply;
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
+                                         K32OBJ_THREAD, THREAD_SUSPEND_RESUME );
+    CLIENT_SendRequest( REQ_RESUME_THREAD, -1, 1, &req, sizeof(req) );
+    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0xffffffff;
+    return reply.count;
 }
 
 
@@ -750,37 +731,28 @@ DWORD WINAPI ResumeThread(
 DWORD WINAPI SuspendThread(
     HANDLE32 hthread) /* [in] Handle to the thread */
 {
-    THDB *thread;
-    DWORD oldcount;
+    struct suspend_thread_request req;
+    struct suspend_thread_reply reply;
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
+                                         K32OBJ_THREAD, THREAD_SUSPEND_RESUME );
+    CLIENT_SendRequest( REQ_SUSPEND_THREAD, -1, 1, &req, sizeof(req) );
+    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0xffffffff;
+    return reply.count;
+}
 
-    SYSTEM_LOCK();
-    if (!(thread = THREAD_GetPtr( hthread, THREAD_QUERY_INFORMATION, NULL )))
-    {
-        SYSTEM_UNLOCK();
-        WARN(thread, "Invalid thread handle\n");
-	return 0xFFFFFFFF;
-    }
-    
-    if (!(oldcount = thread->suspend_count))
-    {
-        if (thread->unix_pid == getpid())
-            WARN(thread, "Attempting to suspend myself\n" );
-        else
-        {
-            if (kill(thread->unix_pid, SIGSTOP))
-            {
-                WARN(thread, "Unable to STOP pid: %04x\n", 
-                     thread->unix_pid);
-                oldcount = 0xFFFFFFFF;
-            }
-            else thread->suspend_count++;
-        }
-    }
-    else thread->suspend_count++;
-    K32OBJ_DecCount( &thread->header );
-    SYSTEM_UNLOCK();
-    return oldcount;
 
+/***********************************************************************
+ *              QueueUserAPC  (KERNEL32.566)
+ */
+DWORD WINAPI QueueUserAPC( PAPCFUNC func, HANDLE32 hthread, ULONG_PTR data )
+{
+    struct queue_apc_request req;
+    req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hthread,
+                                         K32OBJ_THREAD, THREAD_SET_CONTEXT );
+    req.func  = func;
+    req.param = (void *)data;
+    CLIENT_SendRequest( REQ_QUEUE_APC, -1, 1, &req, sizeof(req) );
+    return !CLIENT_WaitReply( NULL, NULL, 0 );
 }
 
 
diff --git a/server/console.c b/server/console.c
index d9cfae33eba..e9edaef0f9a 100644
--- a/server/console.c
+++ b/server/console.c
@@ -9,6 +9,7 @@
 
 #include <assert.h>
 #include <fcntl.h>
+#include <signal.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -21,36 +22,75 @@
 
 #include "winerror.h"
 #include "winnt.h"
+#include "wincon.h"
 #include "server/thread.h"
 
-struct console
+struct screen_buffer;
+
+struct console_input
+{
+    struct object         obj;           /* object header */
+    int                   fd;            /* Unix file descriptor */
+    int                   mode;          /* input mode */
+    struct screen_buffer *output;        /* associated screen buffer */
+};
+
+struct screen_buffer
 {
-    struct object  obj;             /* object header */
-    int            fd;              /* Unix file descriptor */
-    int            is_read;         /* is this the read or write part? */
+    struct object         obj;           /* object header */
+    int                   fd;            /* Unix file descriptor */
+    int                   mode;          /* output mode */
+    struct console_input *input;         /* associated console input */
+    int                   cursor_size;   /* size of cursor (percentage filled) */
+    int                   cursor_visible;/* cursor visibility flag */
+    int                   pid;           /* xterm pid (hack) */
+    char                 *title;         /* console title */
 };
 
-static void console_dump( struct object *obj, int verbose );
-static int console_add_queue( struct object *obj, struct wait_queue_entry *entry );
-static void console_remove_queue( struct object *obj, struct wait_queue_entry *entry );
-static int console_signaled( struct object *obj, struct thread *thread );
-static int console_get_read_fd( struct object *obj );
-static int console_get_write_fd( struct object *obj );
+
+static void console_input_dump( struct object *obj, int verbose );
+static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry );
+static void console_input_remove_queue( struct object *obj, struct wait_queue_entry *entry );
+static int console_input_signaled( struct object *obj, struct thread *thread );
+static int console_input_get_read_fd( struct object *obj );
+static void console_input_destroy( struct object *obj );
+
+static void screen_buffer_dump( struct object *obj, int verbose );
+static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry *entry );
+static void screen_buffer_remove_queue( struct object *obj, struct wait_queue_entry *entry );
+static int screen_buffer_signaled( struct object *obj, struct thread *thread );
+static int screen_buffer_get_write_fd( struct object *obj );
+static void screen_buffer_destroy( struct object *obj );
+
+/* common routine */
 static int console_get_info( struct object *obj, struct get_file_info_reply *reply );
-static void console_destroy( struct object *obj );
 
-static const struct object_ops console_ops =
+static const struct object_ops console_input_ops =
 {
-    console_dump,
-    console_add_queue,
-    console_remove_queue,
-    console_signaled,
+    console_input_dump,
+    console_input_add_queue,
+    console_input_remove_queue,
+    console_input_signaled,
     no_satisfied,
-    console_get_read_fd,
-    console_get_write_fd,
+    console_input_get_read_fd,
+    no_write_fd,
     no_flush,
     console_get_info,
-    console_destroy
+    console_input_destroy
+};
+
+static const struct object_ops screen_buffer_ops =
+{
+    screen_buffer_dump,
+    screen_buffer_add_queue,
+    screen_buffer_remove_queue,
+    screen_buffer_signaled,
+    no_satisfied,
+    no_read_fd,
+    screen_buffer_get_write_fd,
+    no_flush,
+    console_get_info,
+    screen_buffer_destroy
 };
 
 static const struct select_ops select_ops =
@@ -61,7 +101,8 @@ static const struct select_ops select_ops =
 
 int create_console( int fd, struct object *obj[2] )
 {
-    struct console *console_read, *console_write;
+    struct console_input *console_input;
+    struct screen_buffer *screen_buffer;
     int read_fd, write_fd;
 
     if ((read_fd = (fd != -1) ? dup(fd) : dup(0)) == -1)
@@ -75,67 +116,185 @@ int create_console( int fd, struct object *obj[2] )
         close( read_fd );
         return 0;
     }
-    if (!(console_read = mem_alloc( sizeof(struct console) )))
+    if (!(console_input = mem_alloc( sizeof(struct console_input) )))
     {
         close( read_fd );
         close( write_fd );
         return 0;
     }
-    if (!(console_write = mem_alloc( sizeof(struct console) )))
+    if (!(screen_buffer = mem_alloc( sizeof(struct screen_buffer) )))
     {
         close( read_fd );
         close( write_fd );
-        free( console_read );
+        free( console_input );
         return 0;
     }
-    init_object( &console_read->obj, &console_ops, NULL );
-    init_object( &console_write->obj, &console_ops, NULL );
-    console_read->fd       = read_fd;
-    console_read->is_read  = 1;
-    console_write->fd      = write_fd;
-    console_write->is_read = 0;
+    init_object( &console_input->obj, &console_input_ops, NULL );
+    init_object( &screen_buffer->obj, &screen_buffer_ops, NULL );
+    console_input->fd             = read_fd;
+    console_input->mode           = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
+                                    ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
+    console_input->output         = screen_buffer;
+    screen_buffer->fd             = write_fd;
+    screen_buffer->mode           = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
+    screen_buffer->input          = console_input;
+    screen_buffer->cursor_size    = 100;
+    screen_buffer->cursor_visible = 1;
+    screen_buffer->pid            = 0;
+    screen_buffer->title          = strdup( "Wine console" );
     CLEAR_ERROR();
-    obj[0] = &console_read->obj;
-    obj[1] = &console_write->obj;
+    obj[0] = &console_input->obj;
+    obj[1] = &screen_buffer->obj;
     return 1;
 }
 
-int set_console_fd( int handle, int fd )
+int set_console_fd( int handle, int fd, int pid )
 {
-    struct console *console;
+    struct console_input *input;
+    struct screen_buffer *output;
+    struct object *obj;
+    int fd_in, fd_out;
+
+    if (!(obj = get_handle_obj( current->process, handle, 0, NULL )))
+        return 0;
+    if (obj->ops == &console_input_ops)
+    {
+        input = (struct console_input *)obj;
+        output = input->output;
+        grab_object( output );
+    }
+    else if (obj->ops == &screen_buffer_ops)
+    {
+        output = (struct screen_buffer *)obj;
+        input = output->input;
+        grab_object( input );
+    }
+    else
+    {
+        SET_ERROR( ERROR_INVALID_HANDLE );
+        release_object( obj );
+        return 0;
+    }
 
-    if (!(console = (struct console *)get_handle_obj( current->process, handle,
-                                                      0, &console_ops )))
+    if ((fd_in = dup(fd)) == -1)
+    {
+        file_set_error();
+        release_object( input );
+        release_object( output );
         return 0;
-    if ((fd = dup(fd)) == -1)
+    }
+    if ((fd_out = dup(fd)) == -1)
     {
         file_set_error();
-        release_object( console );
+        close( fd_in );
+        release_object( input );
+        release_object( output );
         return 0;
     }
-    close( console->fd );
-    console->fd = fd;
+    close( input->fd );
+    close( output->fd );
+    input->fd = fd_in;
+    output->fd = fd_out;
+    output->pid = pid;
+    release_object( input );
+    release_object( output );
+    return 1;
+}
+
+int get_console_mode( int handle, int *mode )
+{
+    struct object *obj;
+    int ret = 0;
+
+    if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL )))
+        return 0;
+    if (obj->ops == &console_input_ops)
+    {
+        *mode = ((struct console_input *)obj)->mode;
+        ret = 1;
+    }
+    else if (obj->ops == &screen_buffer_ops)
+    {
+        *mode = ((struct screen_buffer *)obj)->mode;
+        ret = 1;
+    }
+    else SET_ERROR( ERROR_INVALID_HANDLE );
+    release_object( obj );
+    return ret;
+}
+
+int set_console_mode( int handle, int mode )
+{
+    struct object *obj;
+    int ret = 0;
+
+    if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL )))
+        return 0;
+    if (obj->ops == &console_input_ops)
+    {
+        ((struct console_input *)obj)->mode = mode;
+        ret = 1;
+    }
+    else if (obj->ops == &screen_buffer_ops)
+    {
+        ((struct screen_buffer *)obj)->mode = mode;
+        ret = 1;
+    }
+    else SET_ERROR( ERROR_INVALID_HANDLE );
+    release_object( obj );
+    return ret;
+}
+
+/* set misc console information (output handle only) */
+int set_console_info( int handle, struct set_console_info_request *req, const char *title )
+{
+    struct screen_buffer *console;
+    if (!(console = (struct screen_buffer *)get_handle_obj( current->process, handle,
+                                                            GENERIC_WRITE, &screen_buffer_ops )))
+        return 0;
+    if (req->mask & SET_CONSOLE_INFO_CURSOR)
+    {
+        console->cursor_size    = req->cursor_size;
+        console->cursor_visible = req->cursor_visible;
+    }
+    if (req->mask & SET_CONSOLE_INFO_TITLE)
+    {
+        if (console->title) free( console->title );
+        console->title = strdup( title );
+    }
+    release_object( console );
+    return 1;
+}
+
+/* get misc console information (output handle only) */
+int get_console_info( int handle, struct get_console_info_reply *reply, const char **title )
+{
+    struct screen_buffer *console;
+    if (!(console = (struct screen_buffer *)get_handle_obj( current->process, handle,
+                                                            GENERIC_READ, &screen_buffer_ops )))
+        return 0;
+    reply->cursor_size    = console->cursor_size;
+    reply->cursor_visible = console->cursor_visible;
+    reply->pid            = console->pid;
+    *title                = console->title;
     release_object( console );
     return 1;
 }
 
-static void console_dump( struct object *obj, int verbose )
+static void console_input_dump( struct object *obj, int verbose )
 {
-    struct console *console = (struct console *)obj;
-    assert( obj->ops == &console_ops );
-    fprintf( stderr, "Console %s fd=%d\n",
-             console->is_read ? "input" : "output", console->fd );
+    struct console_input *console = (struct console_input *)obj;
+    assert( obj->ops == &console_input_ops );
+    fprintf( stderr, "Console input fd=%d\n", console->fd );
 }
 
-static int console_add_queue( struct object *obj, struct wait_queue_entry *entry )
+static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry )
 {
-    struct console *console = (struct console *)obj;
-    assert( obj->ops == &console_ops );
+    struct console_input *console = (struct console_input *)obj;
+    assert( obj->ops == &console_input_ops );
     if (!obj->head)  /* first on the queue */
     {
-        if (!add_select_user( console->fd,
-                              console->is_read ? READ_EVENT : WRITE_EVENT,
-                              &select_ops, console ))
+        if (!add_select_user( console->fd, READ_EVENT, &select_ops, console ))
         {
             SET_ERROR( ERROR_OUTOFMEMORY );
             return 0;
@@ -145,10 +304,10 @@ static int console_add_queue( struct object *obj, struct wait_queue_entry *entry
     return 1;
 }
 
-static void console_remove_queue( struct object *obj, struct wait_queue_entry *entry )
+static void console_input_remove_queue( struct object *obj, struct wait_queue_entry *entry )
 {
-    struct console *console = (struct console *)grab_object(obj);
-    assert( obj->ops == &console_ops );
+    struct console_input *console = (struct console_input *)grab_object(obj);
+    assert( obj->ops == &console_input_ops );
 
     remove_queue( obj, entry );
     if (!obj->head)  /* last on the queue is gone */
@@ -156,58 +315,101 @@ static void console_remove_queue( struct object *obj, struct wait_queue_entry *e
     release_object( obj );
 }
 
-static int console_signaled( struct object *obj, struct thread *thread )
+static int console_input_signaled( struct object *obj, struct thread *thread )
 {
     fd_set fds;
     struct timeval tv = { 0, 0 };
-    struct console *console = (struct console *)obj;
-    assert( obj->ops == &console_ops );
+    struct console_input *console = (struct console_input *)obj;
+    assert( obj->ops == &console_input_ops );
 
     FD_ZERO( &fds );
     FD_SET( console->fd, &fds );
-    if (console->is_read)
-        return select( console->fd + 1, &fds, NULL, NULL, &tv ) > 0;
-    else
-        return select( console->fd + 1, NULL, &fds, NULL, &tv ) > 0;
+    return select( console->fd + 1, &fds, NULL, NULL, &tv ) > 0;
 }
 
-static int console_get_read_fd( struct object *obj )
+static int console_input_get_read_fd( struct object *obj )
 {
-    struct console *console = (struct console *)obj;
-    assert( obj->ops == &console_ops );
-
-    if (!console->is_read)
-    {
-        SET_ERROR( ERROR_ACCESS_DENIED );
-        return -1;
-    }
+    struct console_input *console = (struct console_input *)obj;
+    assert( obj->ops == &console_input_ops );
     return dup( console->fd );
 }
 
-static int console_get_write_fd( struct object *obj )
+static int console_get_info( struct object *obj, struct get_file_info_reply *reply )
 {
-    struct console *console = (struct console *)obj;
-    assert( obj->ops == &console_ops );
+    memset( reply, 0, sizeof(*reply) );
+    reply->type = FILE_TYPE_CHAR;
+    return 1;
+}
+
+static void console_input_destroy( struct object *obj )
+{
+    struct console_input *console = (struct console_input *)obj;
+    assert( obj->ops == &console_input_ops );
+    close( console->fd );
+    if (console->output) console->output->input = NULL;
+    free( console );
+}
 
-    if (console->is_read)
+static void screen_buffer_dump( struct object *obj, int verbose )
+{
+    struct screen_buffer *console = (struct screen_buffer *)obj;
+    assert( obj->ops == &screen_buffer_ops );
+    fprintf( stderr, "Console screen buffer fd=%d\n", console->fd );
+}
+
+static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry *entry )
+{
+    struct screen_buffer *console = (struct screen_buffer *)obj;
+    assert( obj->ops == &screen_buffer_ops );
+    if (!obj->head)  /* first on the queue */
     {
-        SET_ERROR( ERROR_ACCESS_DENIED );
-        return -1;
+        if (!add_select_user( console->fd, WRITE_EVENT, &select_ops, console ))
+        {
+            SET_ERROR( ERROR_OUTOFMEMORY );
+            return 0;
+        }
     }
-    return dup( console->fd );
+    add_queue( obj, entry );
+    return 1;
 }
 
-static int console_get_info( struct object *obj, struct get_file_info_reply *reply )
+static void screen_buffer_remove_queue( struct object *obj, struct wait_queue_entry *entry )
 {
-    memset( reply, 0, sizeof(*reply) );
-    reply->type = FILE_TYPE_CHAR;
-    return 1;
+    struct screen_buffer *console = (struct screen_buffer *)grab_object(obj);
+    assert( obj->ops == &screen_buffer_ops );
+
+    remove_queue( obj, entry );
+    if (!obj->head)  /* last on the queue is gone */
+        remove_select_user( console->fd );
+    release_object( obj );
+}
+
+static int screen_buffer_signaled( struct object *obj, struct thread *thread )
+{
+    fd_set fds;
+    struct timeval tv = { 0, 0 };
+    struct screen_buffer *console = (struct screen_buffer *)obj;
+    assert( obj->ops == &screen_buffer_ops );
+
+    FD_ZERO( &fds );
+    FD_SET( console->fd, &fds );
+    return select( console->fd + 1, NULL, &fds, NULL, &tv ) > 0;
+}
+
+static int screen_buffer_get_write_fd( struct object *obj )
+{
+    struct screen_buffer *console = (struct screen_buffer *)obj;
+    assert( obj->ops == &screen_buffer_ops );
+    return dup( console->fd );
 }
 
-static void console_destroy( struct object *obj )
+static void screen_buffer_destroy( struct object *obj )
 {
-    struct console *console = (struct console *)obj;
-    assert( obj->ops == &console_ops );
+    struct screen_buffer *console = (struct screen_buffer *)obj;
+    assert( obj->ops == &screen_buffer_ops );
     close( console->fd );
+    if (console->input) console->input->output = NULL;
+    if (console->pid) kill( console->pid, SIGTERM );
+    if (console->title) free( console->title );
     free( console );
 }
diff --git a/server/file.c b/server/file.c
index c786807e861..1ade0967264 100644
--- a/server/file.c
+++ b/server/file.c
@@ -423,3 +423,17 @@ int set_file_time( int handle, time_t access_time, time_t write_time )
     return 1;
     
 }
+
+int file_lock( struct file *file, int offset_high, int offset_low,
+               int count_high, int count_low )
+{
+    /* FIXME: implement this */
+    return 1;
+}
+
+int file_unlock( struct file *file, int offset_high, int offset_low,
+                 int count_high, int count_low )
+{
+    /* FIXME: implement this */
+    return 1;
+}
diff --git a/server/process.c b/server/process.c
index c9ba9c83f23..6cd3e581c09 100644
--- a/server/process.c
+++ b/server/process.c
@@ -52,6 +52,10 @@ struct process
     int                  running_threads; /* number of threads running in this process */
     struct timeval       start_time;      /* absolute time at process start */
     struct timeval       end_time;        /* absolute time at process end */
+    int                  priority;        /* priority class */
+    int                  affinity;        /* process affinity mask */
+    struct object       *console_in;      /* console input */
+    struct object       *console_out;     /* console output */
 };
 
 static struct process *first_process;
@@ -84,11 +88,12 @@ static const struct object_ops process_ops =
 /* create a new process */
 struct process *create_process(void)
 {
-    struct process *process;
+    struct process *process, *parent;
 
     if (!(process = mem_alloc( sizeof(*process) ))) return NULL;
 
-    if (!copy_handle_table( process, current ? current->process : NULL ))
+    parent = current ? current->process : NULL;
+    if (!copy_handle_table( process, parent ))
     {
         free( process );
         return NULL;
@@ -99,6 +104,15 @@ struct process *create_process(void)
     process->thread_list     = NULL;
     process->exit_code       = 0x103;  /* STILL_ACTIVE */
     process->running_threads = 0;
+    process->priority        = NORMAL_PRIORITY_CLASS;
+    process->affinity        = 1;
+    process->console_in      = NULL;
+    process->console_out     = NULL;
+    if (parent)
+    {
+        if (parent->console_in) process->console_in = grab_object( parent->console_in );
+        if (parent->console_out) process->console_out = grab_object( parent->console_out );
+    }
 
     if (first_process) first_process->prev = process;
     first_process = process;
@@ -126,6 +140,7 @@ static void process_destroy( struct object *obj )
     if (process->next) process->next->prev = process->prev;
     if (process->prev) process->prev->next = process->next;
     else first_process = process->next;
+    free_console( process );
     free_handles( process );
     if (debug_level) memset( process, 0xbb, sizeof(process) );  /* catch errors */
     free( process );
@@ -506,6 +521,55 @@ void kill_process( struct process *process, int exit_code )
 void get_process_info( struct process *process,
                        struct get_process_info_reply *reply )
 {
-    reply->pid       = process;
-    reply->exit_code = process->exit_code;
+    reply->pid              = process;
+    reply->exit_code        = process->exit_code;
+    reply->priority         = process->priority;
+    reply->process_affinity = process->affinity;
+    reply->system_affinity  = 1;
+}
+
+/* set all information about a process */
+void set_process_info( struct process *process,
+                       struct set_process_info_request *req )
+{
+    if (req->mask & SET_PROCESS_INFO_PRIORITY)
+        process->priority = req->priority;
+    if (req->mask & SET_PROCESS_INFO_AFFINITY)
+    {
+        if (req->affinity != 1) SET_ERROR( ERROR_INVALID_PARAMETER );
+        else process->affinity = req->affinity;
+    }
+}
+
+/* allocate a console for this process */
+int alloc_console( struct process *process )
+{
+    struct object *obj[2];
+    if (process->console_in || process->console_out)
+    {
+        SET_ERROR( ERROR_ACCESS_DENIED );
+        return 0;
+    }
+    if (!create_console( -1, obj )) return 0;
+    process->console_in  = obj[0];
+    process->console_out = obj[1];
+    return 1;
+}
+
+/* free the console for this process */
+int free_console( struct process *process )
+{
+    if (process->console_in) release_object( process->console_in );
+    if (process->console_out) release_object( process->console_out );
+    process->console_in = process->console_out = NULL;
+    return 1;
+}
+
+/* get the process console */
+struct object *get_console( struct process *process, int output )
+{
+    struct object *obj;
+    if (!(obj = output ? process->console_out : process->console_in))
+        return NULL;
+    return grab_object( obj );
 }
diff --git a/server/request.c b/server/request.c
index f1fc2fdd3a5..bfdcae51e49 100644
--- a/server/request.c
+++ b/server/request.c
@@ -227,7 +227,7 @@ DECL_HANDLER(dup_handle)
 DECL_HANDLER(get_process_info)
 {
     struct process *process;
-    struct get_process_info_reply reply = { 0, 0 };
+    struct get_process_info_reply reply = { 0, 0, 0 };
 
     if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
     {
@@ -237,6 +237,19 @@ DECL_HANDLER(get_process_info)
     send_reply( current, -1, 1, &reply, sizeof(reply) );
 }
 
+/* set information about a process */
+DECL_HANDLER(set_process_info)
+{
+    struct process *process;
+
+    if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION )))
+    {
+        set_process_info( process, req );
+        release_object( process );
+    }
+    send_reply( current, -1, 0 );
+}
+
 /* fetch information about a thread */
 DECL_HANDLER(get_thread_info)
 {
@@ -251,6 +264,59 @@ DECL_HANDLER(get_thread_info)
     send_reply( current, -1, 1, &reply, sizeof(reply) );
 }
 
+/* set information about a thread */
+DECL_HANDLER(set_thread_info)
+{
+    struct thread *thread;
+
+    if ((thread = get_thread_from_handle( req->handle, THREAD_SET_INFORMATION )))
+    {
+        set_thread_info( thread, req );
+        release_object( thread );
+    }
+    send_reply( current, -1, 0 );
+}
+
+/* suspend a thread */
+DECL_HANDLER(suspend_thread)
+{
+    struct thread *thread;
+    struct suspend_thread_reply reply = { -1 };
+    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
+    {
+        reply.count = suspend_thread( thread );
+        release_object( thread );
+    }
+    send_reply( current, -1, 1, &reply, sizeof(reply) );
+    
+}
+
+/* resume a thread */
+DECL_HANDLER(resume_thread)
+{
+    struct thread *thread;
+    struct resume_thread_reply reply = { -1 };
+    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
+    {
+        reply.count = resume_thread( thread );
+        release_object( thread );
+    }
+    send_reply( current, -1, 1, &reply, sizeof(reply) );
+    
+}
+
+/* queue an APC for a thread */
+DECL_HANDLER(queue_apc)
+{
+    struct thread *thread;
+    if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
+    {
+        thread_queue_apc( thread, req->func, req->param );
+        release_object( thread );
+    }
+    send_reply( current, -1, 0 );
+}
+
 /* open a handle to a process */
 DECL_HANDLER(open_process)
 {
@@ -488,6 +554,36 @@ DECL_HANDLER(get_file_info)
     send_reply( current, -1, 1, &reply, sizeof(reply) );
 }
 
+/* lock a region of a file */
+DECL_HANDLER(lock_file)
+{
+    struct file *file;
+
+    if ((file = get_file_obj( current->process, req->handle, 0 )))
+    {
+        file_lock( file, req->offset_high, req->offset_low,
+                   req->count_high, req->count_low );
+        release_object( file );
+    }
+    send_reply( current, -1, 0 );
+}
+
+
+/* unlock a region of a file */
+DECL_HANDLER(unlock_file)
+{
+    struct file *file;
+
+    if ((file = get_file_obj( current->process, req->handle, 0 )))
+    {
+        file_unlock( file, req->offset_high, req->offset_low,
+                     req->count_high, req->count_low );
+        release_object( file );
+    }
+    send_reply( current, -1, 0 );
+}
+
+
 /* create an anonymous pipe */
 DECL_HANDLER(create_pipe)
 {
@@ -512,34 +608,72 @@ DECL_HANDLER(create_pipe)
     send_reply( current, -1, 1, &reply, sizeof(reply) );
 }
 
-/* create a console */
-DECL_HANDLER(create_console)
+/* allocate a console for the current process */
+DECL_HANDLER(alloc_console)
 {
-    struct create_console_reply reply = { -1, -1 };
-    struct object *obj[2];
-    if (create_console( fd, obj ))
+    alloc_console( current->process );
+    send_reply( current, -1, 0 );
+}
+
+/* free the console of the current process */
+DECL_HANDLER(free_console)
+{
+    free_console( current->process );
+    send_reply( current, -1, 0 );
+}
+
+/* open a handle to the process console */
+DECL_HANDLER(open_console)
+{
+    struct object *obj;
+    struct open_console_reply reply = { -1 };
+    if ((obj = get_console( current->process, req->output )))
     {
-        reply.handle_read = alloc_handle( current->process, obj[0],
-                                          STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
-                                          req->inherit );
-        if (reply.handle_read != -1)
-        {
-            reply.handle_write = alloc_handle( current->process, obj[1],
-                                               STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
-                                               req->inherit );
-            if (reply.handle_write == -1)
-                close_handle( current->process, reply.handle_read );
-        }
-        release_object( obj[0] );
-        release_object( obj[1] );
+        reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
+        release_object( obj );
     }
     send_reply( current, -1, 1, &reply, sizeof(reply) );
 }
 
+/* set info about a console (output only) */
+DECL_HANDLER(set_console_info)
+{
+    char *name = (char *)data;
+    if (!len) name = NULL;
+    else CHECK_STRING( "set_console_info", name, len );
+    set_console_info( req->handle, req, name );
+    send_reply( current, -1, 0 );
+}
+
+/* get info about a console (output only) */
+DECL_HANDLER(get_console_info)
+{
+    struct get_console_info_reply reply;
+    const char *title;
+    get_console_info( req->handle, &reply, &title );
+    send_reply( current, -1, 2, &reply, sizeof(reply),
+                title, title ? strlen(title)+1 : 0 );
+}
+
 /* set a console fd */
 DECL_HANDLER(set_console_fd)
 {
-    set_console_fd( req->handle, fd );
+    set_console_fd( req->handle, fd, req->pid );
+    send_reply( current, -1, 0 );
+}
+
+/* get a console mode (input or output) */
+DECL_HANDLER(get_console_mode)
+{
+    struct get_console_mode_reply reply;
+    get_console_mode( req->handle, &reply.mode );
+    send_reply( current, -1, 1, &reply, sizeof(reply) );
+}
+
+/* set a console mode (input or output) */
+DECL_HANDLER(set_console_mode)
+{
+    set_console_mode( req->handle, req->mode );
     send_reply( current, -1, 0 );
 }
 
@@ -585,3 +719,18 @@ DECL_HANDLER(get_mapping_info)
     int map_fd = get_mapping_info( req->handle, &reply );
     send_reply( current, map_fd, 1, &reply, sizeof(reply) );
 }
+
+/* create a device */
+DECL_HANDLER(create_device)
+{
+    struct object *obj;
+    struct create_device_reply reply = { -1 };
+
+    if ((obj = create_device( req->id )))
+    {
+        reply.handle = alloc_handle( current->process, obj,
+                                     req->access, req->inherit );
+        release_object( obj );
+    }
+    send_reply( current, -1, 1, &reply, sizeof(reply) );
+}
diff --git a/server/thread.c b/server/thread.c
index 21614c9e026..5e5e3d6e584 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -38,6 +38,15 @@ struct thread_wait
     struct wait_queue_entry queues[1];
 };
 
+/* asynchronous procedure calls */
+
+struct thread_apc
+{
+    void                   *func;    /* function to call in client */
+    void                   *param;   /* function param */
+};
+#define MAX_THREAD_APC  16  /* Max outstanding APCs for a thread */
+
 
 /* thread operations */
 
@@ -86,11 +95,16 @@ struct thread *create_thread( int fd, void *pid, int *thread_handle,
     thread->name      = NULL;
     thread->mutex     = NULL;
     thread->wait      = NULL;
+    thread->apc       = NULL;
+    thread->apc_count = 0;
     thread->error     = 0;
     thread->state     = STARTING;
     thread->exit_code = 0x103;  /* STILL_ACTIVE */
     thread->next      = first_thread;
     thread->prev      = NULL;
+    thread->priority  = THREAD_PRIORITY_NORMAL;
+    thread->affinity  = 1;
+    thread->suspend   = 0;
 
     if (first_thread) first_thread->prev = thread;
     first_thread = thread;
@@ -136,6 +150,7 @@ static void destroy_thread( struct object *obj )
     if (thread->prev) thread->prev->next = thread->next;
     else first_thread = thread->next;
     if (thread->name) free( thread->name );
+    if (thread->apc) free( thread->apc );
     if (debug_level) memset( thread, 0xaa, sizeof(thread) );  /* catch errors */
     free( thread );
 }
@@ -178,6 +193,49 @@ void get_thread_info( struct thread *thread,
 {
     reply->pid       = thread;
     reply->exit_code = thread->exit_code;
+    reply->priority  = thread->priority;
+}
+
+
+/* set all information about a thread */
+void set_thread_info( struct thread *thread,
+                      struct set_thread_info_request *req )
+{
+    if (req->mask & SET_THREAD_INFO_PRIORITY)
+        thread->priority = req->priority;
+    if (req->mask & SET_THREAD_INFO_AFFINITY)
+    {
+        if (req->affinity != 1) SET_ERROR( ERROR_INVALID_PARAMETER );
+        else thread->affinity = req->affinity;
+    }
+}
+
+/* suspend a thread */
+int suspend_thread( struct thread *thread )
+{
+    int old_count = thread->suspend;
+    if (thread->suspend < MAXIMUM_SUSPEND_COUNT)
+    {
+        if (!thread->suspend++)
+        {
+            if (thread->unix_pid) kill( thread->unix_pid, SIGSTOP );
+        }
+    }
+    return old_count;
+}
+
+/* resume a thread */
+int resume_thread( struct thread *thread )
+{
+    int old_count = thread->suspend;
+    if (thread->suspend > 0)
+    {
+        if (!--thread->suspend)
+        {
+            if (thread->unix_pid) kill( thread->unix_pid, SIGCONT );
+        }
+    }
+    return old_count;
 }
 
 /* send a reply to a thread */
@@ -297,13 +355,12 @@ static int check_wait( struct thread *thread, int *signaled )
     int i;
     struct thread_wait *wait = thread->wait;
     struct wait_queue_entry *entry = wait->queues;
-    struct timeval now;
 
     assert( wait );
     if (wait->flags & SELECT_ALL)
     {
         for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
-            if (!entry->obj->ops->signaled( entry->obj, thread )) goto check_timeout;
+            if (!entry->obj->ops->signaled( entry->obj, thread )) goto other_checks;
         /* Wait satisfied: tell it to all objects */
         *signaled = 0;
         for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
@@ -323,61 +380,82 @@ static int check_wait( struct thread *thread, int *signaled )
             return 1;
         }
     }
- check_timeout:
-    if (!(wait->flags & SELECT_TIMEOUT)) return 0;
-    gettimeofday( &now, NULL );
-    if ((now.tv_sec > wait->timeout.tv_sec) ||
-        ((now.tv_sec == wait->timeout.tv_sec) &&
-         (now.tv_usec >= wait->timeout.tv_usec)))
+
+ other_checks:
+    if ((wait->flags & SELECT_ALERTABLE) && thread->apc)
     {
-        *signaled = STATUS_TIMEOUT;
+        *signaled = STATUS_USER_APC;
         return 1;
     }
+    if (wait->flags & SELECT_TIMEOUT)
+    {
+        struct timeval now;
+        gettimeofday( &now, NULL );
+        if ((now.tv_sec > wait->timeout.tv_sec) ||
+            ((now.tv_sec == wait->timeout.tv_sec) &&
+             (now.tv_usec >= wait->timeout.tv_usec)))
+        {
+            *signaled = STATUS_TIMEOUT;
+            return 1;
+        }
+    }
     return 0;
 }
 
-/* sleep on a list of objects */
-void sleep_on( struct thread *thread, int count, int *handles, int flags, int timeout )
+/* send the select reply to wake up the client */
+static void send_select_reply( struct thread *thread, int signaled )
 {
     struct select_reply reply;
-
-    assert( !thread->wait );
-    reply.signaled = -1;
-    if (!wait_on( thread, count, handles, flags, timeout )) goto done;
-    if (!check_wait( thread, &reply.signaled ))
+    reply.signaled = signaled;
+    if ((signaled == STATUS_USER_APC) && thread->apc)
     {
-        /* we need to wait */
-        if (flags & SELECT_TIMEOUT)
-            set_select_timeout( thread->client_fd, &thread->wait->timeout );
-        return;
+        struct thread_apc *apc = thread->apc;
+        int len = thread->apc_count * sizeof(*apc);
+        thread->apc = NULL;
+        thread->apc_count = 0;
+        send_reply( thread, -1, 2, &reply, sizeof(reply),
+                    apc, len );
+        free( apc );
     }
-    end_wait( thread );
- done:
-    send_reply( thread, -1, 1, &reply, sizeof(reply) );
+    else send_reply( thread, -1, 1, &reply, sizeof(reply) );
 }
 
 /* attempt to wake up a thread */
 /* return 1 if OK, 0 if the wait condition is still not satisfied */
 static int wake_thread( struct thread *thread )
 {
-    struct select_reply reply;
+    int signaled;
 
-    if (!check_wait( thread, &reply.signaled )) return 0;
+    if (!check_wait( thread, &signaled )) return 0;
     end_wait( thread );
-    send_reply( thread, -1, 1, &reply, sizeof(reply) );
+    send_select_reply( thread, signaled );
     return 1;
 }
 
+/* sleep on a list of objects */
+void sleep_on( struct thread *thread, int count, int *handles, int flags, int timeout )
+{
+    assert( !thread->wait );
+    if (!wait_on( thread, count, handles, flags, timeout ))
+    {
+        /* return an error */
+        send_select_reply( thread, -1 );
+        return;
+    }
+    if (!wake_thread( thread ))
+    {
+        /* we need to wait */
+        if (flags & SELECT_TIMEOUT)
+            set_select_timeout( thread->client_fd, &thread->wait->timeout );
+    }
+}
+
 /* timeout for the current thread */
 void thread_timeout(void)
 {
-    struct select_reply reply;
-
     assert( current->wait );
-
-    reply.signaled = STATUS_TIMEOUT;
     end_wait( current );
-    send_reply( current, -1, 1, &reply, sizeof(reply) );
+    send_select_reply( current, STATUS_TIMEOUT );
 }
 
 /* attempt to wake threads sleeping on the object wait queue */
@@ -396,6 +474,29 @@ void wake_up( struct object *obj, int max )
     }
 }
 
+/* queue an async procedure call */
+int thread_queue_apc( struct thread *thread, void *func, void *param )
+{
+    struct thread_apc *apc;
+    if (!func)
+    {
+        SET_ERROR( ERROR_INVALID_PARAMETER );
+        return 0;
+    }
+    if (!thread->apc)
+    {
+        if (!(thread->apc = mem_alloc( MAX_THREAD_APC * sizeof(*apc) )))
+            return 0;
+        thread->apc_count = 0;
+    }
+    else if (thread->apc_count >= MAX_THREAD_APC) return 0;
+    thread->apc[thread->apc_count].func  = func;
+    thread->apc[thread->apc_count].param = param;
+    thread->apc_count++;
+    wake_thread( thread );
+    return 1;
+}
+
 /* kill a thread on the spot */
 void kill_thread( struct thread *thread, int exit_code )
 {
diff --git a/server/trace.c b/server/trace.c
index ed257c4affb..1c1b8df53c2 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -57,7 +57,19 @@ static int dump_get_process_info_request( struct get_process_info_request *req,
 static int dump_get_process_info_reply( struct get_process_info_reply *req, int len )
 {
     fprintf( stderr, " pid=%p,", req->pid );
-    fprintf( stderr, " exit_code=%d", req->exit_code );
+    fprintf( stderr, " exit_code=%d,", req->exit_code );
+    fprintf( stderr, " priority=%d,", req->priority );
+    fprintf( stderr, " process_affinity=%d,", req->process_affinity );
+    fprintf( stderr, " system_affinity=%d", req->system_affinity );
+    return (int)sizeof(*req);
+}
+
+static int dump_set_process_info_request( struct set_process_info_request *req, int len )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " mask=%d,", req->mask );
+    fprintf( stderr, " priority=%d,", req->priority );
+    fprintf( stderr, " affinity=%d", req->affinity );
     return (int)sizeof(*req);
 }
 
@@ -70,7 +82,49 @@ static int dump_get_thread_info_request( struct get_thread_info_request *req, in
 static int dump_get_thread_info_reply( struct get_thread_info_reply *req, int len )
 {
     fprintf( stderr, " pid=%p,", req->pid );
-    fprintf( stderr, " exit_code=%d", req->exit_code );
+    fprintf( stderr, " exit_code=%d,", req->exit_code );
+    fprintf( stderr, " priority=%d", req->priority );
+    return (int)sizeof(*req);
+}
+
+static int dump_set_thread_info_request( struct set_thread_info_request *req, int len )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " mask=%d,", req->mask );
+    fprintf( stderr, " priority=%d,", req->priority );
+    fprintf( stderr, " affinity=%d", req->affinity );
+    return (int)sizeof(*req);
+}
+
+static int dump_suspend_thread_request( struct suspend_thread_request *req, int len )
+{
+    fprintf( stderr, " handle=%d", req->handle );
+    return (int)sizeof(*req);
+}
+
+static int dump_suspend_thread_reply( struct suspend_thread_reply *req, int len )
+{
+    fprintf( stderr, " count=%d", req->count );
+    return (int)sizeof(*req);
+}
+
+static int dump_resume_thread_request( struct resume_thread_request *req, int len )
+{
+    fprintf( stderr, " handle=%d", req->handle );
+    return (int)sizeof(*req);
+}
+
+static int dump_resume_thread_reply( struct resume_thread_reply *req, int len )
+{
+    fprintf( stderr, " count=%d", req->count );
+    return (int)sizeof(*req);
+}
+
+static int dump_queue_apc_request( struct queue_apc_request *req, int len )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " func=%p,", req->func );
+    fprintf( stderr, " param=%p", req->param );
     return (int)sizeof(*req);
 }
 
@@ -297,6 +351,26 @@ static int dump_get_file_info_reply( struct get_file_info_reply *req, int len )
     return (int)sizeof(*req);
 }
 
+static int dump_lock_file_request( struct lock_file_request *req, int len )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " offset_low=%08x,", req->offset_low );
+    fprintf( stderr, " offset_high=%08x,", req->offset_high );
+    fprintf( stderr, " count_low=%08x,", req->count_low );
+    fprintf( stderr, " count_high=%08x", req->count_high );
+    return (int)sizeof(*req);
+}
+
+static int dump_unlock_file_request( struct unlock_file_request *req, int len )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " offset_low=%08x,", req->offset_low );
+    fprintf( stderr, " offset_high=%08x,", req->offset_high );
+    fprintf( stderr, " count_low=%08x,", req->count_low );
+    fprintf( stderr, " count_high=%08x", req->count_high );
+    return (int)sizeof(*req);
+}
+
 static int dump_create_pipe_request( struct create_pipe_request *req, int len )
 {
     fprintf( stderr, " inherit=%d", req->inherit );
@@ -310,25 +384,80 @@ static int dump_create_pipe_reply( struct create_pipe_reply *req, int len )
     return (int)sizeof(*req);
 }
 
-static int dump_create_console_request( struct create_console_request *req, int len )
+static int dump_alloc_console_request( struct alloc_console_request *req, int len )
+{
+    return (int)sizeof(*req);
+}
+
+static int dump_free_console_request( struct free_console_request *req, int len )
+{
+    return (int)sizeof(*req);
+}
+
+static int dump_open_console_request( struct open_console_request *req, int len )
 {
+    fprintf( stderr, " output=%d,", req->output );
+    fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " inherit=%d", req->inherit );
     return (int)sizeof(*req);
 }
 
-static int dump_create_console_reply( struct create_console_reply *req, int len )
+static int dump_open_console_reply( struct open_console_reply *req, int len )
 {
-    fprintf( stderr, " handle_read=%d,", req->handle_read );
-    fprintf( stderr, " handle_write=%d", req->handle_write );
+    fprintf( stderr, " handle=%d", req->handle );
     return (int)sizeof(*req);
 }
 
 static int dump_set_console_fd_request( struct set_console_fd_request *req, int len )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " pid=%d", req->pid );
+    return (int)sizeof(*req);
+}
+
+static int dump_get_console_mode_request( struct get_console_mode_request *req, int len )
+{
+    fprintf( stderr, " handle=%d", req->handle );
+    return (int)sizeof(*req);
+}
+
+static int dump_get_console_mode_reply( struct get_console_mode_reply *req, int len )
+{
+    fprintf( stderr, " mode=%d", req->mode );
+    return (int)sizeof(*req);
+}
+
+static int dump_set_console_mode_request( struct set_console_mode_request *req, int len )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " mode=%d", req->mode );
+    return (int)sizeof(*req);
+}
+
+static int dump_set_console_info_request( struct set_console_info_request *req, int len )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " mask=%d,", req->mask );
+    fprintf( stderr, " cursor_size=%d,", req->cursor_size );
+    fprintf( stderr, " cursor_visible=%d,", req->cursor_visible );
+    fprintf( stderr, " title=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) );
+    return len;
+}
+
+static int dump_get_console_info_request( struct get_console_info_request *req, int len )
 {
     fprintf( stderr, " handle=%d", req->handle );
     return (int)sizeof(*req);
 }
 
+static int dump_get_console_info_reply( struct get_console_info_reply *req, int len )
+{
+    fprintf( stderr, " cursor_size=%d,", req->cursor_size );
+    fprintf( stderr, " cursor_visible=%d,", req->cursor_visible );
+    fprintf( stderr, " pid=%d", req->pid );
+    return (int)sizeof(*req);
+}
+
 static int dump_create_change_notification_request( struct create_change_notification_request *req, int len )
 {
     fprintf( stderr, " subtree=%d,", req->subtree );
@@ -372,6 +501,20 @@ static int dump_get_mapping_info_reply( struct get_mapping_info_reply *req, int
     return (int)sizeof(*req);
 }
 
+static int dump_create_device_request( struct create_device_request *req, int len )
+{
+    fprintf( stderr, " access=%08x,", req->access );
+    fprintf( stderr, " inherit=%d,", req->inherit );
+    fprintf( stderr, " id=%d", req->id );
+    return (int)sizeof(*req);
+}
+
+static int dump_create_device_reply( struct create_device_reply *req, int len )
+{
+    fprintf( stderr, " handle=%d", req->handle );
+    return (int)sizeof(*req);
+}
+
 struct dumper
 {
     int (*dump_req)( void *data, int len );
@@ -392,8 +535,18 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] =
       (void(*)())0 },
     { (int(*)(void *,int))dump_get_process_info_request,
       (void(*)())dump_get_process_info_reply },
+    { (int(*)(void *,int))dump_set_process_info_request,
+      (void(*)())0 },
     { (int(*)(void *,int))dump_get_thread_info_request,
       (void(*)())dump_get_thread_info_reply },
+    { (int(*)(void *,int))dump_set_thread_info_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_suspend_thread_request,
+      (void(*)())dump_suspend_thread_reply },
+    { (int(*)(void *,int))dump_resume_thread_request,
+      (void(*)())dump_resume_thread_reply },
+    { (int(*)(void *,int))dump_queue_apc_request,
+      (void(*)())0 },
     { (int(*)(void *,int))dump_close_handle_request,
       (void(*)())0 },
     { (int(*)(void *,int))dump_dup_handle_request,
@@ -432,18 +585,36 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] =
       (void(*)())0 },
     { (int(*)(void *,int))dump_get_file_info_request,
       (void(*)())dump_get_file_info_reply },
+    { (int(*)(void *,int))dump_lock_file_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_unlock_file_request,
+      (void(*)())0 },
     { (int(*)(void *,int))dump_create_pipe_request,
       (void(*)())dump_create_pipe_reply },
-    { (int(*)(void *,int))dump_create_console_request,
-      (void(*)())dump_create_console_reply },
+    { (int(*)(void *,int))dump_alloc_console_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_free_console_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_open_console_request,
+      (void(*)())dump_open_console_reply },
     { (int(*)(void *,int))dump_set_console_fd_request,
       (void(*)())0 },
+    { (int(*)(void *,int))dump_get_console_mode_request,
+      (void(*)())dump_get_console_mode_reply },
+    { (int(*)(void *,int))dump_set_console_mode_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_set_console_info_request,
+      (void(*)())0 },
+    { (int(*)(void *,int))dump_get_console_info_request,
+      (void(*)())dump_get_console_info_reply },
     { (int(*)(void *,int))dump_create_change_notification_request,
       (void(*)())dump_create_change_notification_reply },
     { (int(*)(void *,int))dump_create_mapping_request,
       (void(*)())dump_create_mapping_reply },
     { (int(*)(void *,int))dump_get_mapping_info_request,
       (void(*)())dump_get_mapping_info_reply },
+    { (int(*)(void *,int))dump_create_device_request,
+      (void(*)())dump_create_device_reply },
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] =
@@ -454,7 +625,12 @@ static const char * const req_names[REQ_NB_REQUESTS] =
     "terminate_process",
     "terminate_thread",
     "get_process_info",
+    "set_process_info",
     "get_thread_info",
+    "set_thread_info",
+    "suspend_thread",
+    "resume_thread",
+    "queue_apc",
     "close_handle",
     "dup_handle",
     "open_process",
@@ -474,12 +650,21 @@ static const char * const req_names[REQ_NB_REQUESTS] =
     "set_file_time",
     "flush_file",
     "get_file_info",
+    "lock_file",
+    "unlock_file",
     "create_pipe",
-    "create_console",
+    "alloc_console",
+    "free_console",
+    "open_console",
     "set_console_fd",
+    "get_console_mode",
+    "set_console_mode",
+    "set_console_info",
+    "get_console_info",
     "create_change_notification",
     "create_mapping",
     "get_mapping_info",
+    "create_device",
 };
 
 void trace_request( enum request req, void *data, int len, int fd )
diff --git a/win32/console.c b/win32/console.c
index e2bc6229269..0328d432bec 100644
--- a/win32/console.c
+++ b/win32/console.c
@@ -50,14 +50,7 @@
 /* The CONSOLE kernel32 Object */
 typedef struct _CONSOLE {
 	K32OBJ  		header;
-	DWORD			mode;
-	CONSOLE_CURSOR_INFO	cinfo;
-
-	int			master;	/* xterm side of pty */
-	int			infd,outfd;
-        int                     hread, hwrite;  /* server handles (hack) */
-	int			pid;	/* xterm's pid, -1 if no xterm */
-        LPSTR   		title;	/* title of console */
+
 	INPUT_RECORD		*irs;	/* buffered input records */
 	int			nrofirs;/* nr of buffered input records */
 } CONSOLE;
@@ -79,16 +72,34 @@ static void CONSOLE_Destroy(K32OBJ *obj)
 
 	obj->type = K32OBJ_UNKNOWN;
 
-	if (console->title)
-	  	  HeapFree( SystemHeap, 0, console->title );
-	console->title = NULL;
-	/* if there is a xterm, kill it. */
-	if (console->pid != -1)
-		kill(console->pid, SIGTERM);
 	HeapFree(SystemHeap, 0, console);
 }
 
 
+/***********************************************************************
+ * CONSOLE_GetPtr
+ */
+static CONSOLE *CONSOLE_GetPtr( HANDLE32 handle )
+{
+    return (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), handle,
+                                       K32OBJ_CONSOLE, 0, NULL );
+}
+
+/****************************************************************************
+ *		CONSOLE_GetInfo
+ */
+static BOOL32 CONSOLE_GetInfo( HANDLE32 handle, struct get_console_info_reply *reply )
+{
+    struct get_console_info_request req;
+
+    if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
+                                              K32OBJ_CONSOLE, GENERIC_READ )) == -1)
+        return FALSE;
+    CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
+    return !CLIENT_WaitSimpleReply( reply, sizeof(*reply), NULL );
+}
+
+
 /****************************************************************************
  *		CONSOLE_add_input_record			[internal]
  *
@@ -110,8 +121,7 @@ static void
 CONSOLE_string_to_IR( HANDLE32 hConsoleInput,unsigned char *buf,int len) {
     int			j,k;
     INPUT_RECORD	ir;
-    CONSOLE *console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput,
-                                                   K32OBJ_CONSOLE, 0, NULL);
+    CONSOLE *console = CONSOLE_GetPtr( hConsoleInput );
 
     for (j=0;j<len;j++) {
     	unsigned char inchar = buf[j];
@@ -489,8 +499,15 @@ BOOL32 WINAPI FreeConsole(VOID)
 		return FALSE;
 	}
 
-        HANDLE_CloseAll( pdb, &console->header );
+        CLIENT_SendRequest( REQ_FREE_CONSOLE, -1, 0 );
+        if (CLIENT_WaitReply( NULL, NULL, 0 ) != ERROR_SUCCESS)
+        {
+            K32OBJ_DecCount(&console->header);
+            SYSTEM_UNLOCK();
+            return FALSE;
+        }
 
+        HANDLE_CloseAll( pdb, &console->header );
 	K32OBJ_DecCount( &console->header );
 	pdb->console = NULL;
 	SYSTEM_UNLOCK();
@@ -498,33 +515,43 @@ BOOL32 WINAPI FreeConsole(VOID)
 }
 
 
-/** 
- *  It looks like the openpty that comes with glibc in RedHat 5.0
- *  is buggy (second call returns what looks like a dup of 0 and 1
- *  instead of a new pty), this is a generic replacement.
+/*************************************************************************
+ * 		CONSOLE_OpenHandle
+ *
+ * Open a handle to the current process console.
  */
-static int CONSOLE_openpty(CONSOLE *console, char *name, 
-			struct termios *term, struct winsize *winsize)
+HANDLE32 CONSOLE_OpenHandle( BOOL32 output, DWORD access, LPSECURITY_ATTRIBUTES sa )
 {
-        int temp, slave;
-        struct set_console_fd_request req;
-
-        temp = wine_openpty(&console->master, &slave, name, term,
-           winsize);
-        console->infd = console->outfd = slave;
+    struct open_console_request req;
+    struct open_console_reply reply;
+    CONSOLE *console;
+    HANDLE32 handle;
 
-        req.handle = console->hread;
-        CLIENT_SendRequest(REQ_SET_CONSOLE_FD, dup(slave), 1,
-           &req, sizeof(req));
-        CLIENT_WaitReply( NULL, NULL, 0);
-        req.handle = console->hwrite;
-        CLIENT_SendRequest( REQ_SET_CONSOLE_FD, dup(slave), 1,
-           &req, sizeof(req));
-        CLIENT_WaitReply( NULL, NULL, 0);
+    req.output  = output;
+    req.access  = access;
+    req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+    CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
+    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
+    if (reply.handle == -1) return INVALID_HANDLE_VALUE32;
 
-        return temp;  /* The same result as the openpty call */
+    SYSTEM_LOCK();
+    if (!(console = (CONSOLE*)HeapAlloc( SystemHeap, 0, sizeof(*console))))
+    {
+        SYSTEM_UNLOCK();
+        return FALSE;
+    }
+    console->header.type     = K32OBJ_CONSOLE;
+    console->header.refcount = 1;
+    console->nrofirs         = 0;
+    console->irs             = HeapAlloc(GetProcessHeap(),0,1);;
+    handle = HANDLE_Alloc( PROCESS_Current(), &console->header, req.access,
+                           req.inherit, reply.handle );
+    SYSTEM_UNLOCK();
+    K32OBJ_DecCount(&console->header);
+    return handle;
 }
 
+
 /*************************************************************************
  * 		CONSOLE_make_complex			[internal]
  *
@@ -537,29 +564,37 @@ static int CONSOLE_openpty(CONSOLE *console, char *name,
  * 
  * All other functions should work indedependend from this call.
  *
- * To test for complex console: pid == -1 -> simple, otherwise complex.
+ * To test for complex console: pid == 0 -> simple, otherwise complex.
  */
-static BOOL32 CONSOLE_make_complex(HANDLE32 handle,CONSOLE *console)
+static BOOL32 CONSOLE_make_complex(HANDLE32 handle)
 {
+        struct set_console_fd_request req;
+        struct get_console_info_reply info;
 	struct termios term;
-	char buf[30],*title;
+	char buf[256];
 	char c = '\0';
 	int status = 0;
-	int i,xpid;
+	int i,xpid,master,slave;
 	DWORD	xlen;
 
-	if (console->pid != -1)
-		return TRUE; /* already complex */
+        if (!CONSOLE_GetInfo( handle, &info )) return FALSE;
+        if (info.pid) return TRUE; /* already complex */
 
 	MSG("Console: Making console complex (creating an xterm)...\n");
 
 	if (tcgetattr(0, &term) < 0) return FALSE;
 	term.c_lflag = ~(ECHO|ICANON);
-	if (CONSOLE_openpty(console, NULL, &term, NULL) < 0) return FALSE;
+
+        if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
+                                                  K32OBJ_CONSOLE, 0 )) == -1)
+            return FALSE;
+
+        if (wine_openpty(&master, &slave, NULL, &term, NULL) < 0)
+            return FALSE;
 
 	if ((xpid=fork()) == 0) {
-		tcsetattr(console->infd, TCSADRAIN, &term);
-		sprintf(buf, "-Sxx%d", console->master);
+		tcsetattr(slave, TCSADRAIN, &term);
+		sprintf(buf, "-Sxx%d", master);
 		/* "-fn vga" for VGA font. Harmless if vga is not present:
 		 *  xterm: unable to open font "vga", trying "fixed".... 
 		 */
@@ -567,53 +602,39 @@ static BOOL32 CONSOLE_make_complex(HANDLE32 handle,CONSOLE *console)
 		ERR(console, "error creating AllocConsole xterm\n");
 		exit(1);
 	}
-	console->pid = xpid;
+
+        req.pid = xpid;
+        CLIENT_SendRequest( REQ_SET_CONSOLE_FD, dup(slave), 1, &req, sizeof(req) );
+        CLIENT_WaitReply( NULL, NULL, 0 );
 
 	/* most xterms like to print their window ID when used with -S;
 	 * read it and continue before the user has a chance...
 	 */
-	for (i=0; c!='\n'; (status=read(console->infd, &c, 1)), i++) {
+	for (i=0; c!='\n'; (status=read(slave, &c, 1)), i++) {
 		if (status == -1 && c == '\0') {
 				/* wait for xterm to be created */
 			usleep(100);
 		}
 		if (i > 10000) {
 			ERR(console, "can't read xterm WID\n");
-			kill(console->pid, SIGKILL);
+			kill(xpid, SIGKILL);
 			return FALSE;
 		}
 	}
 	/* enable mouseclicks */
 	sprintf(buf,"%c[?1001s%c[?1000h",27,27);
 	WriteFile(handle,buf,strlen(buf),&xlen,NULL);
-	if (console->title) {
-	    title = HeapAlloc(GetProcessHeap(),0,strlen("\033]2;\a")+1+strlen(console->title));
-	    sprintf(title,"\033]2;%s\a",console->title);
-	    WriteFile(handle,title,strlen(title),&xlen,NULL);
-	    HeapFree(GetProcessHeap(),0,title);
+        
+        if (GetConsoleTitle32A( buf, sizeof(buf) ))
+        {
+	    WriteFile(handle,"\033]2;",4,&xlen,NULL);
+	    WriteFile(handle,buf,strlen(buf),&xlen,NULL);
+	    WriteFile(handle,"\a",1,&xlen,NULL);
 	}
 	return TRUE;
 
 }
 
-/***********************************************************************
- *		CONSOLE_GetConsoleHandle
- *	 returns a 16-bit style console handle
- * note: only called from _lopen
- */
-HFILE32 CONSOLE_GetConsoleHandle(VOID)
-{
-	PDB32 *pdb = PROCESS_Current();
-	HFILE32 handle = HFILE_ERROR32;
-
-	SYSTEM_LOCK();
-	if (pdb->console != NULL) {
-		CONSOLE *console = (CONSOLE *)pdb->console;
-		handle = (HFILE32)HANDLE_Alloc(pdb, &console->header, 0, TRUE, -1);
-	}
-	SYSTEM_UNLOCK();
-	return handle;
-}
 
 /***********************************************************************
  *            AllocConsole (KERNEL32.103)
@@ -622,17 +643,14 @@ HFILE32 CONSOLE_GetConsoleHandle(VOID)
  */
 BOOL32 WINAPI AllocConsole(VOID)
 {
-        struct create_console_request req;
-        struct create_console_reply reply;
+        struct open_console_request req;
+        struct open_console_reply reply;
 	PDB32 *pdb = PROCESS_Current();
 	CONSOLE *console;
 	HANDLE32 hIn, hOut, hErr;
 
 	SYSTEM_LOCK();		/* FIXME: really only need to lock the process */
 
-	SetLastError(ERROR_CANNOT_MAKE);  /* this might not be the right 
-					     error, but it's a good guess :) */
-
 	console = (CONSOLE *)pdb->console;
 
 	/* don't create a console if we already have one */
@@ -650,39 +668,46 @@ BOOL32 WINAPI AllocConsole(VOID)
 
         console->header.type     = K32OBJ_CONSOLE;
         console->header.refcount = 1;
-        console->pid             = -1;
-        console->title           = NULL;
 	console->nrofirs	 = 0;
 	console->irs	 	 = HeapAlloc(GetProcessHeap(),0,1);;
-    	console->mode		 =   ENABLE_PROCESSED_INPUT
-				   | ENABLE_LINE_INPUT
-				   | ENABLE_ECHO_INPUT;
-	/* FIXME: we shouldn't probably use hardcoded UNIX values here. */
-	console->infd		 = 0;
-	console->outfd		 = 1;
-        console->hread = console->hwrite = -1;
-
-        CLIENT_SendRequest( REQ_CREATE_CONSOLE, -1, 1, &req, sizeof(req) );
-        if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS)
+
+        CLIENT_SendRequest( REQ_ALLOC_CONSOLE, -1, 0 );
+        if (CLIENT_WaitReply( NULL, NULL, 0 ) != ERROR_SUCCESS)
         {
             K32OBJ_DecCount(&console->header);
             SYSTEM_UNLOCK();
             return FALSE;
         }
-        console->hread = reply.handle_read;
-        console->hwrite = reply.handle_write;
 
-	if ((hIn = HANDLE_Alloc(pdb,&console->header, 0, TRUE,
-                                reply.handle_read)) == INVALID_HANDLE_VALUE32)
+        req.output = 0;
+        req.access = GENERIC_READ | GENERIC_WRITE;
+        req.inherit = FALSE;
+        CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
+        if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS)
+        {
+            K32OBJ_DecCount(&console->header);
+            SYSTEM_UNLOCK();
+            return FALSE;
+        }
+	if ((hIn = HANDLE_Alloc(pdb,&console->header, req.access,
+                                FALSE, reply.handle)) == INVALID_HANDLE_VALUE32)
         {
-            CLIENT_CloseHandle( reply.handle_write );
             K32OBJ_DecCount(&console->header);
             SYSTEM_UNLOCK();
             return FALSE;
 	}
 
-	if ((hOut = HANDLE_Alloc(pdb,&console->header, 0, TRUE,
-                                 reply.handle_write)) == INVALID_HANDLE_VALUE32)
+        req.output = 1;
+        CLIENT_SendRequest( REQ_OPEN_CONSOLE, -1, 1, &req, sizeof(req) );
+        if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) != ERROR_SUCCESS)
+        {
+            CloseHandle(hIn);
+            K32OBJ_DecCount(&console->header);
+            SYSTEM_UNLOCK();
+            return FALSE;
+        }
+	if ((hOut = HANDLE_Alloc(pdb,&console->header, req.access,
+                                 FALSE, reply.handle)) == INVALID_HANDLE_VALUE32)
         {
             CloseHandle(hIn);
             K32OBJ_DecCount(&console->header);
@@ -742,14 +767,15 @@ UINT32 WINAPI GetConsoleOutputCP(VOID)
  */
 BOOL32 WINAPI GetConsoleMode(HANDLE32 hcon,LPDWORD mode)
 {
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
-
-    if (!console) {
-    	FIXME(console,"(%d,%p), no console handle passed!\n",hcon,mode);
-	return FALSE;
-    }
-    *mode = console->mode;
-    K32OBJ_DecCount(&console->header);
+    struct get_console_mode_request req;
+    struct get_console_mode_reply reply;
+
+    if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon,
+                                              K32OBJ_CONSOLE, GENERIC_READ )) == -1)
+        return FALSE;
+    CLIENT_SendRequest( REQ_GET_CONSOLE_MODE, -1, 1, &req, sizeof(req));
+    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return FALSE;
+    *mode = reply.mode;
     return TRUE;
 }
 
@@ -767,16 +793,14 @@ BOOL32 WINAPI GetConsoleMode(HANDLE32 hcon,LPDWORD mode)
  */
 BOOL32 WINAPI SetConsoleMode( HANDLE32 hcon, DWORD mode )
 {
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
-
-    if (!console) {
-    	FIXME(console,"(%d,%ld), no console handle passed!\n",hcon,mode);
-	return FALSE;
-    }
-    FIXME(console,"(0x%08x,0x%08lx): stub\n",hcon,mode);
-    console->mode = mode;
-    K32OBJ_DecCount(&console->header);
-    return TRUE;
+    struct set_console_mode_request req;
+
+    if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon,
+                                              K32OBJ_CONSOLE, GENERIC_READ )) == -1)
+        return FALSE;
+    req.mode = mode;
+    CLIENT_SendRequest( REQ_SET_CONSOLE_MODE, -1, 1, &req, sizeof(req));
+    return !CLIENT_WaitReply( NULL, NULL, 0 );
 }
 
 
@@ -785,14 +809,29 @@ BOOL32 WINAPI SetConsoleMode( HANDLE32 hcon, DWORD mode )
  */
 DWORD WINAPI GetConsoleTitle32A(LPSTR title,DWORD size)
 {
-    PDB32 *pdb = PROCESS_Current();
-    CONSOLE *console= (CONSOLE *)pdb->console;
-
-    if(console && console->title) {
-	lstrcpyn32A(title,console->title,size);
-	return strlen(title);
+    struct get_console_info_request req;
+    struct get_console_info_reply reply;
+    int len;
+    DWORD ret = 0;
+    HANDLE32 hcon;
+
+    if ((hcon = CreateFile32A( "CONOUT$", GENERIC_READ, 0, NULL,
+                               OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE32)
+        return 0;
+    if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon,
+                                              K32OBJ_CONSOLE, GENERIC_READ )) == -1)
+    {
+        CloseHandle( hcon );
+        return 0;
     }
-    return 0;
+    CLIENT_SendRequest( REQ_GET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
+    if (!CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply), title, size ))
+    {
+        if (len > sizeof(reply)+size) title[size-1] = 0;
+        ret = strlen(title);
+    }
+    CloseHandle( hcon );
+    return ret;
 }
 
 
@@ -809,14 +848,14 @@ DWORD WINAPI GetConsoleTitle32A(LPSTR title,DWORD size)
  */
 DWORD WINAPI GetConsoleTitle32W( LPWSTR title, DWORD size )
 {
-    PDB32 *pdb = PROCESS_Current();
-    CONSOLE *console= (CONSOLE *)pdb->console;
-    if(console && console->title) 
-    {
-        lstrcpynAtoW(title,console->title,size);
-        return (lstrlen32W(title));
-    }
-    return 0;
+    char *tmp;
+    DWORD ret;
+
+    if (!(tmp = HeapAlloc( GetProcessHeap(), 0, size ))) return 0;
+    ret = GetConsoleTitle32A( tmp, size );
+    lstrcpyAtoW( title, tmp );
+    HeapFree( GetProcessHeap(), 0, tmp );
+    return ret;
 }
 
 
@@ -858,13 +897,7 @@ BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput,
     	0,4,2,6,
 	1,5,3,7,
     };
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleOutput, K32OBJ_CONSOLE, 0, NULL);
-
-    if (!console) {
-    	FIXME(console,"(%d,...): no console handle!\n",hConsoleOutput);
-	return FALSE;
-    }
-    CONSOLE_make_complex(hConsoleOutput,console);
+    CONSOLE_make_complex(hConsoleOutput);
     buffer = HeapAlloc(GetProcessHeap(),0,100);;
     curbufsize = 100;
 
@@ -897,7 +930,6 @@ BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput,
     sprintf(sbuf,"%c[0m",27);SADD(sbuf);
     WriteFile(hConsoleOutput,buffer,bufused,&res,NULL);
     HeapFree(GetProcessHeap(),0,buffer);
-    K32OBJ_DecCount(&console->header);
     return TRUE;
 }
 
@@ -932,7 +964,7 @@ BOOL32 WINAPI ReadConsole32A( HANDLE32 hConsoleInput,
                               LPDWORD lpNumberOfCharsRead,
                               LPVOID lpReserved )
 {
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL);
+    CONSOLE *console = CONSOLE_GetPtr( hConsoleInput );
     int		i,charsread = 0;
     LPSTR	xbuf = (LPSTR)lpBuffer;
 
@@ -1007,7 +1039,7 @@ BOOL32 WINAPI ReadConsoleInput32A(HANDLE32 hConsoleInput,
 				  LPINPUT_RECORD lpBuffer,
 				  DWORD nLength, LPDWORD lpNumberOfEventsRead)
 {
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL);
+    CONSOLE *console = CONSOLE_GetPtr( hConsoleInput );
 
     TRACE(console, "(%d,%p,%ld,%p)\n",hConsoleInput, lpBuffer, nLength,
           lpNumberOfEventsRead);
@@ -1056,6 +1088,7 @@ BOOL32 WINAPI ReadConsoleInput32A(HANDLE32 hConsoleInput,
  */
 BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title)
 {
+#if 0
     PDB32 *pdb = PROCESS_Current();
     CONSOLE *console;
     DWORD written;
@@ -1079,6 +1112,7 @@ BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title)
     }
 
     sprintf(titlestring,titleformat,title);
+#if 0
     /* only set title for complex console (own xterm) */
     if (console->pid != -1) {
 	WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),titlestring,strlen(titlestring),&written,NULL);
@@ -1086,9 +1120,41 @@ BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title)
 	    ret =TRUE;
     } else
     	ret = TRUE;
+#endif
     HeapFree( GetProcessHeap(), 0, titlestring );
     K32OBJ_DecCount(&console->header);
     return ret;
+
+
+
+#endif
+
+    struct set_console_info_request req;
+    struct get_console_info_reply info;
+    HANDLE32 hcon;
+    DWORD written;
+
+    if ((hcon = CreateFile32A( "CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL,
+                               OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE32)
+        return FALSE;
+    if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon,
+                                              K32OBJ_CONSOLE, GENERIC_WRITE )) == -1)
+        goto error;
+    req.mask = SET_CONSOLE_INFO_TITLE;
+    CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 2, &req, sizeof(req),
+                        title, strlen(title)+1 );
+    if (CLIENT_WaitReply( NULL, NULL, 0 )) goto error;
+    if (CONSOLE_GetInfo( hcon, &info ) && info.pid)
+    {
+        /* only set title for complex console (own xterm) */
+        WriteFile( hcon, "\033]2;", 4, &written, NULL );
+        WriteFile( hcon, title, strlen(title), &written, NULL );
+        WriteFile( hcon, "\a", 1, &written, NULL );
+    }
+    return TRUE;
+ error:
+    CloseHandle( hcon );
+    return FALSE;
 }
 
 
@@ -1132,7 +1198,7 @@ BOOL32 WINAPI ReadConsoleInput32W(HANDLE32 hConsoleInput,
  */
 BOOL32 WINAPI FlushConsoleInputBuffer(HANDLE32 hConsoleInput)
 {
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL);
+    CONSOLE *console = CONSOLE_GetPtr( hConsoleInput );
 
     if (!console)
     	return FALSE;
@@ -1156,19 +1222,13 @@ BOOL32 WINAPI SetConsoleCursorPosition( HANDLE32 hcon, COORD pos )
 {
     char 	xbuf[20];
     DWORD	xlen;
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
 
-    if (!console) {
-    	FIXME(console,"(%d,...), no console handle!\n",hcon);
-    	return FALSE;
-    }
-    CONSOLE_make_complex(hcon,console);
+    CONSOLE_make_complex(hcon);
     TRACE(console, "%d (%dx%d)\n", hcon, pos.x , pos.y );
     /* x are columns, y rows */
     sprintf(xbuf,"%c[%d;%dH", 0x1B, pos.y+1, pos.x+1);
     /* FIXME: store internal if we start using own console buffers */
     WriteFile(hcon,xbuf,strlen(xbuf),&xlen,NULL);
-    K32OBJ_DecCount(&console->header);
     return TRUE;
 }
 
@@ -1177,7 +1237,7 @@ BOOL32 WINAPI SetConsoleCursorPosition( HANDLE32 hcon, COORD pos )
  */
 BOOL32 WINAPI GetNumberOfConsoleInputEvents(HANDLE32 hcon,LPDWORD nrofevents)
 {
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
+    CONSOLE *console = CONSOLE_GetPtr( hcon );
 
     if (!console) {
     	FIXME(console,"(%d,%p), no console handle!\n",hcon,nrofevents);
@@ -1211,7 +1271,7 @@ BOOL32 WINAPI PeekConsoleInput32A(HANDLE32 hConsoleInput,
                                   DWORD cInRecords,
                                   LPDWORD lpcRead)
 {
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hConsoleInput, K32OBJ_CONSOLE, 0, NULL);
+    CONSOLE *console = CONSOLE_GetPtr( hConsoleInput );
 
     if (!console) {
         FIXME(console,"(%d,%p,%ld,%p), No console handle passed!\n",hConsoleInput, pirBuffer, cInRecords, lpcRead);
@@ -1260,17 +1320,14 @@ BOOL32 WINAPI PeekConsoleInput32W(HANDLE32 hConsoleInput,
 BOOL32 WINAPI GetConsoleCursorInfo32( HANDLE32 hcon,
                                       LPCONSOLE_CURSOR_INFO cinfo )
 {
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
+    struct get_console_info_reply reply;
 
-    if (!console) {
-    	FIXME(console, "(%x,%p), no console handle!\n", hcon, cinfo);
-	return FALSE;
+    if (!CONSOLE_GetInfo( hcon, &reply )) return FALSE;
+    if (cinfo)
+    {
+        cinfo->dwSize = reply.cursor_size;
+        cinfo->bVisible = reply.cursor_visible;
     }
-    TRACE(console, "(%x,%p)\n", hcon, cinfo);
-    if (!cinfo)
-    	return FALSE;
-    *cinfo = console->cinfo;
-    K32OBJ_DecCount(&console->header);
     return TRUE;
 }
 
@@ -1286,19 +1343,22 @@ BOOL32 WINAPI SetConsoleCursorInfo32(
     HANDLE32 hcon,                /* [in] Handle to console screen buffer */
     LPCONSOLE_CURSOR_INFO cinfo)  /* [in] Address of cursor information */
 {
+    struct set_console_info_request req;
     char	buf[8];
     DWORD	xlen;
-    CONSOLE	*console = (CONSOLE*)HANDLE_GetObjPtr( PROCESS_Current(), hcon, K32OBJ_CONSOLE, 0, NULL);
 
-    TRACE(console, "(%x,%ld,%i): stub\n", hcon,cinfo->dwSize,cinfo->bVisible);
-    if (!console)
-    	return FALSE;
-    CONSOLE_make_complex(hcon,console);
-    sprintf(buf,"%c[?25%c",27,cinfo->bVisible?'h':'l');
+    if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), hcon,
+                                              K32OBJ_CONSOLE, GENERIC_WRITE )) == -1)
+        return FALSE;
+    CONSOLE_make_complex(hcon);
+    sprintf(buf,"\033[?25%c",cinfo->bVisible?'h':'l');
     WriteFile(hcon,buf,strlen(buf),&xlen,NULL);
-    console->cinfo = *cinfo;
-    K32OBJ_DecCount(&console->header);
-    return TRUE;
+
+    req.cursor_size    = cinfo->dwSize;
+    req.cursor_visible = cinfo->bVisible;
+    req.mask           = SET_CONSOLE_INFO_CURSOR;
+    CLIENT_SendRequest( REQ_SET_CONSOLE_INFO, -1, 1, &req, sizeof(req) );
+    return !CLIENT_WaitReply( NULL, NULL, 0 );
 }
 
 
diff --git a/win32/device.c b/win32/device.c
index 9a6b1df9522..36b8b5a0631 100644
--- a/win32/device.c
+++ b/win32/device.c
@@ -30,28 +30,15 @@
 #include "winnt.h"
 #include "msdos.h"
 #include "miscemu.h"
+#include "server.h"
 
-static void DEVICE_Destroy(K32OBJ *dev);
 
-const K32OBJ_OPS DEVICE_Ops =
-{
-    DEVICE_Destroy	/* destroy */
-};
-
-/* The device object */
-typedef struct
-{
-    K32OBJ    header;
-    struct VxDInfo *info;
-} DEVICE_OBJECT;
-
-
-static BOOL32 DeviceIo_VTDAPI(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
+static BOOL32 DeviceIo_VTDAPI(DWORD dwIoControlCode, 
 			      LPVOID lpvInBuffer, DWORD cbInBuffer,
 			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
 			      LPDWORD lpcbBytesReturned,
 			      LPOVERLAPPED lpOverlapped);
-static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
+static BOOL32 DeviceIo_MONODEBG(DWORD dwIoControlCode, 
 			      LPVOID lpvInBuffer, DWORD cbInBuffer,
 			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
 			      LPDWORD lpcbBytesReturned,
@@ -59,13 +46,13 @@ static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
 
 static BOOL32 VxDCall_VMM( DWORD *retv, DWORD service, CONTEXT *context );
 
-static BOOL32 DeviceIo_IFSMgr(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
+static BOOL32 DeviceIo_IFSMgr(DWORD dwIoControlCode, 
 			      LPVOID lpvInBuffer, DWORD cbInBuffer,
 			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
 			      LPDWORD lpcbBytesReturned,
 			      LPOVERLAPPED lpOverlapped);
 
-static BOOL32 DeviceIo_VWin32(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
+static BOOL32 DeviceIo_VWin32(DWORD dwIoControlCode, 
 			      LPVOID lpvInBuffer, DWORD cbInBuffer,
 			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
 			      LPDWORD lpcbBytesReturned,
@@ -80,10 +67,11 @@ struct VxDInfo
     LPCSTR  name;
     WORD    id;
     BOOL32  (*vxdcall)(DWORD *, DWORD, CONTEXT *);
-    BOOL32  (*deviceio)(DEVICE_OBJECT *, DWORD, LPVOID, DWORD, 
+    BOOL32  (*deviceio)(DWORD, LPVOID, DWORD, 
                         LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
-}   
-    VxDList[] = 
+};
+
+static const struct VxDInfo VxDList[] = 
 {
     /* Standard VxD IDs */
     { "VMM",      0x0001, VxDCall_VMM, NULL },
@@ -266,43 +254,39 @@ LPCSTR VMM_Service_Name[N_VMM_SERVICE] =
     "<KERNEL32.101>"          /* 0x0028 -- What does this do??? */
 };
 
-HANDLE32 DEVICE_Open(LPCSTR filename) 
+HANDLE32 DEVICE_Open( LPCSTR filename, DWORD access,
+                      LPSECURITY_ATTRIBUTES sa )
 {
-	DEVICE_OBJECT *dev;
-	HANDLE32 handle;
-	int i;
-
-	dev = HeapAlloc( SystemHeap, 0, sizeof(DEVICE_OBJECT) );
-	if (!dev) return INVALID_HANDLE_VALUE32;
-
-	dev->header.type = K32OBJ_DEVICE_IOCTL;
-	dev->header.refcount = 1;
-	dev->info       = NULL;
-
-	for (i = 0; VxDList[i].name; i++)
-	    if (!lstrcmpi32A(VxDList[i].name, filename))
-	        break;
-	if (VxDList[i].name)
-	    dev->info = &VxDList[i];
-	else
-	    FIXME(win32, "Unknown VxD %s\n", filename);
+    const struct VxDInfo *info;
 
+    for (info = VxDList; info->name; info++)
+        if (!lstrcmpi32A( info->name, filename ))
+            return FILE_CreateDevice( info->id | 0x10000, access, sa );
 
-	handle = HANDLE_Alloc( PROCESS_Current(), &(dev->header),
-			       FILE_ALL_ACCESS | GENERIC_READ |
-			       GENERIC_WRITE | GENERIC_EXECUTE /*FIXME*/, TRUE, -1 );
-	/* If the allocation failed, the object is already destroyed */
-	if (handle == INVALID_HANDLE_VALUE32) dev = NULL;
-	return handle;
+    FIXME(win32, "Unknown VxD %s\n", filename);
+    return FILE_CreateDevice( 0x10000, access, sa );
 }
 
-static void DEVICE_Destroy(K32OBJ *obj) 
+static const struct VxDInfo *DEVICE_GetInfo( HANDLE32 handle )
 {
-    DEVICE_OBJECT *dev = (DEVICE_OBJECT *)obj;
-    assert( obj->type == K32OBJ_DEVICE_IOCTL );
+    struct get_file_info_request req;
+    struct get_file_info_reply reply;
+
+    if ((req.handle = HANDLE_GetServerHandle( PROCESS_Current(), handle,
+                                              K32OBJ_FILE, 0 )) == -1)
+        return NULL;
+    CLIENT_SendRequest( REQ_GET_FILE_INFO, -1, 1, &req, sizeof(req) );
+    if (!CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ) &&
+        (reply.type == FILE_TYPE_UNKNOWN) &&
+        (reply.attr & 0x10000))
+    {
+        const struct VxDInfo *info;
 
-    obj->type = K32OBJ_UNKNOWN;
-    HeapFree( SystemHeap, 0, dev );
+        for (info = VxDList; info->name; info++)
+            if (info->id == LOWORD(reply.attr)) break;
+        return info;
+    }
+    return NULL;
 }
 
 /****************************************************************************
@@ -320,15 +304,14 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
 			      LPDWORD lpcbBytesReturned,
 			      LPOVERLAPPED lpOverlapped)
 {
-	DEVICE_OBJECT	*dev = (DEVICE_OBJECT *)HANDLE_GetObjPtr(
-		PROCESS_Current(), hDevice, K32OBJ_DEVICE_IOCTL, 0 /*FIXME*/, NULL );
+        const struct VxDInfo *info;
 
         TRACE(win32, "(%d,%ld,%p,%ld,%p,%ld,%p,%p)\n",
 		hDevice,dwIoControlCode,lpvInBuffer,cbInBuffer,
 		lpvOutBuffer,cbOutBuffer,lpcbBytesReturned,lpOverlapped
 	);
 
-	if (!dev)
+	if (!(info = DEVICE_GetInfo( hDevice )))
 	{
 		SetLastError( ERROR_INVALID_PARAMETER );
 		return FALSE;
@@ -337,9 +320,9 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
 	/* Check if this is a user defined control code for a VxD */
 	if( HIWORD( dwIoControlCode ) == 0 )
 	{
-		if ( dev->info && dev->info->deviceio )
+		if ( info->deviceio )
 		{
-			return dev->info->deviceio( dev, dwIoControlCode, 
+			return info->deviceio( dwIoControlCode, 
                                         lpvInBuffer, cbInBuffer, 
                                         lpvOutBuffer, cbOutBuffer, 
                                         lpcbBytesReturned, lpOverlapped );
@@ -348,7 +331,7 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
 		{
 			/* FIXME: Set appropriate error */
 			FIXME( win32, "Unimplemented control %ld for VxD device %s\n", 
-                               dwIoControlCode, dev->info ? dev->info->name : "???" );
+                               dwIoControlCode, info->name ? info->name : "???" );
 		}
 	}
 	else
@@ -403,8 +386,7 @@ BOOL32 WINAPI DeviceIoControl(HANDLE32 hDevice, DWORD dwIoControlCode,
 /***********************************************************************
  *           DeviceIo_VTDAPI
  */
-static BOOL32 DeviceIo_VTDAPI(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
-			      LPVOID lpvInBuffer, DWORD cbInBuffer,
+static BOOL32 DeviceIo_VTDAPI(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
 			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
 			      LPDWORD lpcbBytesReturned,
 			      LPOVERLAPPED lpOverlapped)
@@ -765,15 +747,14 @@ static void CONTEXT_2_win32apieq(CONTEXT *pCxt,struct win32apireq *pOut)
 	/* FIXME: pOut->ar_pad ignored */
 }
 
-static BOOL32 DeviceIo_IFSMgr(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
-			      LPVOID lpvInBuffer, DWORD cbInBuffer,
+static BOOL32 DeviceIo_IFSMgr(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer,
 			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
 			      LPDWORD lpcbBytesReturned,
 			      LPOVERLAPPED lpOverlapped)
 {
     BOOL32 retv = TRUE;
-	TRACE(win32,"(%p,%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
-			dev,dwIoControlCode,
+	TRACE(win32,"(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
+			dwIoControlCode,
 			lpvInBuffer,cbInBuffer,
 			lpvOutBuffer,cbOutBuffer,
 			lpcbBytesReturned,
@@ -866,7 +847,7 @@ static void CONTEXT_2_DIOCRegs( CONTEXT *pCxt, DIOC_REGISTERS *pOut )
 }
 
 
-static BOOL32 DeviceIo_VWin32(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
+static BOOL32 DeviceIo_VWin32(DWORD dwIoControlCode, 
 			      LPVOID lpvInBuffer, DWORD cbInBuffer,
 			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
 			      LPDWORD lpcbBytesReturned,
@@ -928,7 +909,7 @@ static BOOL32 DeviceIo_VWin32(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
 
 
 /* this is used by some Origin games */
-static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode, 
+static BOOL32 DeviceIo_MONODEBG(DWORD dwIoControlCode, 
 			      LPVOID lpvInBuffer, DWORD cbInBuffer,
 			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
 			      LPDWORD lpcbBytesReturned,
@@ -942,8 +923,8 @@ static BOOL32 DeviceIo_MONODEBG(DEVICE_OBJECT *dev, DWORD dwIoControlCode,
 		fprintf(stderr,"MONODEBG: %s\n",debugstr_a(lpvInBuffer));
 		break;
 	default:
-		FIXME(win32,"(%p,%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
-			dev,dwIoControlCode,
+		FIXME(win32,"(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
+			dwIoControlCode,
 			lpvInBuffer,cbInBuffer,
 			lpvOutBuffer,cbOutBuffer,
 			lpcbBytesReturned,
diff --git a/win32/process.c b/win32/process.c
index f18817d2802..37443906230 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -19,45 +19,6 @@
 #include "debug.h"
 
 
-/**********************************************************************
- *          GetProcessAffinityMask
- */
-BOOL32 WINAPI GetProcessAffinityMask(HANDLE32 hProcess,
-                                     LPDWORD lpProcessAffinityMask,
-                                     LPDWORD lpSystemAffinityMask)
-{
-	TRACE(task,"(%x,%lx,%lx)\n",
-		hProcess,(lpProcessAffinityMask?*lpProcessAffinityMask:0),
-		(lpSystemAffinityMask?*lpSystemAffinityMask:0));
-	/* It is definitely important for a process to know on what processor
-	   it is running :-) */
-	if(lpProcessAffinityMask)
-		*lpProcessAffinityMask=1;
-	if(lpSystemAffinityMask)
-		*lpSystemAffinityMask=1;
-	return TRUE;
-}
-
-/**********************************************************************
- *           SetThreadAffinityMask
- * Works now like the Windows95 (no MP support) version
- */
-BOOL32 WINAPI SetThreadAffinityMask(HANDLE32 hThread, DWORD dwThreadAffinityMask)
-{
-	THDB	*thdb = THREAD_GetPtr( hThread, THREAD_SET_INFORMATION, NULL );
-
-	if (!thdb) 
-		return FALSE;
-	if (dwThreadAffinityMask!=1) {
-		WARN(thread,"(%d,%ld): only 1 processor supported.\n",
-                    (int)hThread,dwThreadAffinityMask);
-		K32OBJ_DecCount((K32OBJ*)thdb);
-		return FALSE;
-	}
-	K32OBJ_DecCount((K32OBJ*)thdb);
-	return TRUE;
-}
-
 /**********************************************************************
  *  ContinueDebugEvent [KERNEL32.146]
  */
-- 
GitLab