Redesign of the server communication protocol to allow arbitrary sized
data to be exchanged.
Split request and reply structures to make backwards compatibility
easier.
Moved many console functions to dlls/kernel, added code page support,
changed a few requests to behave properly with the new protocol.

diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
index ee9bfde..2f850df 100644
--- a/dlls/advapi32/registry.c
+++ b/dlls/advapi32/registry.c
@@ -1220,14 +1220,14 @@
         goto done;
     }
 
-    SERVER_START_VAR_REQ( load_registry, len )
+    SERVER_START_REQ( load_registry )
     {
         req->hkey  = hkey;
         req->file  = file;
-        memcpy( server_data_ptr(req), subkey, len );
-        ret = RtlNtStatusToDosError( SERVER_CALL() );
+        wine_server_add_data( req, subkey, len );
+        ret = RtlNtStatusToDosError( wine_server_call(req) );
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     CloseHandle( file );
 
  done:
@@ -1241,6 +1241,7 @@
  */
 LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
 {
+    WCHAR buffer[MAX_PATH];
     HANDLE file;
     DWORD ret, len, err = GetLastError();
 
@@ -1249,8 +1250,8 @@
     if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
     if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
 
-    len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), NULL, 0 ) * sizeof(WCHAR);
-    if (len > MAX_PATH*sizeof(WCHAR)) return ERROR_INVALID_PARAMETER;
+    if (!(len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), buffer, MAX_PATH )))
+        return ERROR_INVALID_PARAMETER;
 
     if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
                              FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE)
@@ -1259,15 +1260,14 @@
         goto done;
     }
 
-    SERVER_START_VAR_REQ( load_registry, len )
+    SERVER_START_REQ( load_registry )
     {
         req->hkey  = hkey;
         req->file  = file;
-        MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey),
-                             server_data_ptr(req), len/sizeof(WCHAR) );
-        ret = RtlNtStatusToDosError( SERVER_CALL() );
+        wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
+        ret = RtlNtStatusToDosError( wine_server_call(req) );
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     CloseHandle( file );
 
  done:
@@ -1315,7 +1315,7 @@
     {
         req->hkey = hkey;
         req->file = handle;
-        ret = RtlNtStatusToDosError( SERVER_CALL() );
+        ret = RtlNtStatusToDosError( wine_server_call( req ) );
     }
     SERVER_END_REQ;
 
diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in
index 0ea6a7c..b818bf6 100644
--- a/dlls/kernel/Makefile.in
+++ b/dlls/kernel/Makefile.in
@@ -9,6 +9,7 @@
 
 C_SRCS = \
 	comm.c \
+	console.c \
 	debugger.c \
 	format_msg.c \
 	kernel_main.c \
diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c
index 2079193..95c6c09 100644
--- a/dlls/kernel/comm.c
+++ b/dlls/kernel/comm.c
@@ -379,7 +379,7 @@
         req->handle = handle;
         req->flags = SERIALINFO_SET_ERROR;
         req->commerror = error;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -395,8 +395,8 @@
     SERVER_START_REQ( get_serial_info )
     {
         req->handle = handle;
-        ret = !SERVER_CALL_ERR();
-        *lperror = req->commerror;
+        ret = !wine_server_call_err( req );
+        *lperror = reply->commerror;
     }
     SERVER_END_REQ;
 
@@ -748,9 +748,9 @@
     SERVER_START_REQ( get_serial_info )
     {
         req->handle = handle;
-        if ((ret = !SERVER_CALL_ERR()))
+        if ((ret = !wine_server_call_err( req )))
         {
-            if (evtmask) *evtmask = req->eventmask;
+            if (evtmask) *evtmask = reply->eventmask;
         }
     }
     SERVER_END_REQ;
@@ -781,7 +781,7 @@
         req->handle    = handle;
         req->flags     = SERIALINFO_SET_MASK;
         req->eventmask = evtmask;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -1347,13 +1347,13 @@
     SERVER_START_REQ( get_serial_info )
     {
         req->handle = hComm;
-        if ((ret = !SERVER_CALL_ERR()))
+        if ((ret = !wine_server_call_err( req )))
         {
-            lptimeouts->ReadIntervalTimeout         = req->readinterval;
-            lptimeouts->ReadTotalTimeoutMultiplier  = req->readmult;
-            lptimeouts->ReadTotalTimeoutConstant    = req->readconst;
-            lptimeouts->WriteTotalTimeoutMultiplier = req->writemult;
-            lptimeouts->WriteTotalTimeoutConstant   = req->writeconst;
+            lptimeouts->ReadIntervalTimeout         = reply->readinterval;
+            lptimeouts->ReadTotalTimeoutMultiplier  = reply->readmult;
+            lptimeouts->ReadTotalTimeoutConstant    = reply->readconst;
+            lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
+            lptimeouts->WriteTotalTimeoutConstant   = reply->writeconst;
         }
     }
     SERVER_END_REQ;
@@ -1401,7 +1401,7 @@
         req->readconst    = lptimeouts->ReadTotalTimeoutConstant ;
         req->writemult    = lptimeouts->WriteTotalTimeoutMultiplier ;
         req->writeconst   = lptimeouts->WriteTotalTimeoutConstant ;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     if (!ret) return FALSE;
@@ -1562,7 +1562,7 @@
         req->count = 0;
         req->type = ASYNC_TYPE_WAIT;
 
-        ret=SERVER_CALL_ERR();
+        ret=wine_server_call_err( req );
     }
     SERVER_END_REQ;
 
diff --git a/dlls/kernel/console.c b/dlls/kernel/console.c
new file mode 100644
index 0000000..14517d1
--- /dev/null
+++ b/dlls/kernel/console.c
@@ -0,0 +1,806 @@
+/*
+ * Win32 kernel functions
+ *
+ * Copyright 1995 Martin von Loewis and Cameron Heide
+ * Copyright 1997 Karl Garrison
+ * Copyright 1998 John Richardson
+ * Copyright 1998 Marcus Meissner
+ * Copyright 2001 Eric Pouech
+ * Copyright 2001 Alexandre Julliard
+ */
+
+/* Reference applications:
+ * -  IDA (interactive disassembler) full version 3.75. Works.
+ * -  LYNX/W32. Works mostly, some keys crash it.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "winbase.h"
+#include "winnls.h"
+#include "winerror.h"
+#include "wincon.h"
+#include "wine/server.h"
+#include "wine/exception.h"
+#include "wine/unicode.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(console);
+
+
+static UINT console_input_codepage;
+static UINT console_output_codepage;
+
+/* map input records to Ascii */
+static void input_records_WtoA( INPUT_RECORD *buffer, int count )
+{
+    int i;
+    char ch;
+
+    for (i = 0; i < count; i++)
+    {
+        if (buffer[i].EventType != KEY_EVENT) continue;
+        WideCharToMultiByte( GetConsoleCP(), 0,
+                             &buffer[i].Event.KeyEvent.uChar.UnicodeChar, 1, &ch, 1, NULL, NULL );
+        buffer[i].Event.KeyEvent.uChar.AsciiChar = ch;
+    }
+}
+
+/* map input records to Unicode */
+static void input_records_AtoW( INPUT_RECORD *buffer, int count )
+{
+    int i;
+    WCHAR ch;
+
+    for (i = 0; i < count; i++)
+    {
+        if (buffer[i].EventType != KEY_EVENT) continue;
+        MultiByteToWideChar( GetConsoleCP(), 0,
+                             &buffer[i].Event.KeyEvent.uChar.AsciiChar, 1, &ch, 1 );
+        buffer[i].Event.KeyEvent.uChar.UnicodeChar = ch;
+    }
+}
+
+/* map char infos to Ascii */
+static void char_info_WtoA( CHAR_INFO *buffer, int count )
+{
+    char ch;
+
+    while (count-- > 0)
+    {
+        WideCharToMultiByte( GetConsoleOutputCP(), 0, &buffer->Char.UnicodeChar, 1,
+                             &ch, 1, NULL, NULL );
+        buffer->Char.AsciiChar = ch;
+        buffer++;
+    }
+}
+
+/* map char infos to Unicode */
+static void char_info_AtoW( CHAR_INFO *buffer, int count )
+{
+    WCHAR ch;
+
+    while (count-- > 0)
+    {
+        MultiByteToWideChar( GetConsoleOutputCP(), 0, &buffer->Char.AsciiChar, 1, &ch, 1 );
+        buffer->Char.UnicodeChar = ch;
+        buffer++;
+    }
+}
+
+
+/******************************************************************************
+ * GetConsoleCP [KERNEL32.@]  Returns the OEM code page for the console
+ *
+ * RETURNS
+ *    Code page code
+ */
+UINT WINAPI GetConsoleCP(VOID)
+{
+    if (!console_input_codepage) console_input_codepage = GetOEMCP();
+    return console_input_codepage;
+}
+
+
+/******************************************************************************
+ *  SetConsoleCP	 [KERNEL32.@]
+ */
+BOOL WINAPI SetConsoleCP(UINT cp)
+{
+    if (!IsValidCodePage( cp )) return FALSE;
+    console_input_codepage = cp;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *            GetConsoleOutputCP   (KERNEL32.@)
+ */
+UINT WINAPI GetConsoleOutputCP(VOID)
+{
+    if (!console_output_codepage) console_output_codepage = GetOEMCP();
+    return console_output_codepage;
+}
+
+
+/******************************************************************************
+ * SetConsoleOutputCP [KERNEL32.@]  Set the output codepage used by the console
+ *
+ * PARAMS
+ *    cp [I] code page to set
+ *
+ * RETURNS
+ *    Success: TRUE
+ *    Failure: FALSE
+ */
+BOOL WINAPI SetConsoleOutputCP(UINT cp)
+{
+    if (!IsValidCodePage( cp )) return FALSE;
+    console_output_codepage = cp;
+    return TRUE;
+}
+
+
+/******************************************************************************
+ * WriteConsoleInputA [KERNEL32.@]
+ */
+BOOL WINAPI WriteConsoleInputA( HANDLE handle, const INPUT_RECORD *buffer,
+                                DWORD count, LPDWORD written )
+{
+    INPUT_RECORD *recW;
+    BOOL ret;
+
+    if (!(recW = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*recW) ))) return FALSE;
+    memcpy( recW, buffer, count );
+    input_records_AtoW( recW, count );
+    ret = WriteConsoleInputW( handle, recW, count, written );
+    HeapFree( GetProcessHeap(), 0, recW );
+    return ret;
+}
+
+
+/******************************************************************************
+ * WriteConsoleInputW [KERNEL32.@]
+ */
+BOOL WINAPI WriteConsoleInputW( HANDLE handle, const INPUT_RECORD *buffer,
+                                DWORD count, LPDWORD written )
+{
+    BOOL ret;
+
+    TRACE("(%d,%p,%ld,%p)\n", handle, buffer, count, written);
+
+    if (written) *written = 0;
+    SERVER_START_REQ( write_console_input )
+    {
+        req->handle = handle;
+        wine_server_add_data( req, buffer, count * sizeof(INPUT_RECORD) );
+        if ((ret = !wine_server_call_err( req )))
+        {
+            if (written) *written = reply->written;
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/***********************************************************************
+ *            WriteConsoleOutputA   (KERNEL32.@)
+ */
+BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
+                                 COORD size, COORD coord, LPSMALL_RECT region )
+{
+    int y;
+    BOOL ret;
+    COORD new_size, new_coord;
+    CHAR_INFO *ciw;
+
+    new_size.X = min( region->Right - region->Left + 1, size.X - coord.X );
+    new_size.Y = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
+
+    if (new_size.X <= 0 || new_size.Y <= 0)
+    {
+        region->Bottom = region->Top + new_size.Y - 1;
+        region->Right = region->Left + new_size.X - 1;
+        return TRUE;
+    }
+
+    /* only copy the useful rectangle */
+    if (!(ciw = HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO) * new_size.X * new_size.Y )))
+        return FALSE;
+    for (y = 0; y < new_size.Y; y++)
+    {
+        memcpy( &ciw[y * new_size.X], &lpBuffer[(y + coord.Y) * size.X + coord.X],
+                new_size.X * sizeof(CHAR_INFO) );
+        char_info_AtoW( ciw, new_size.X );
+    }
+    new_coord.X = new_coord.Y = 0;
+    ret = WriteConsoleOutputW( hConsoleOutput, ciw, new_size, new_coord, region );
+    if (ciw) HeapFree( GetProcessHeap(), 0, ciw );
+    return ret;
+}
+
+
+/***********************************************************************
+ *            WriteConsoleOutputW   (KERNEL32.@)
+ */
+BOOL WINAPI WriteConsoleOutputW( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
+                                 COORD size, COORD coord, LPSMALL_RECT region )
+{
+    int width, height, y;
+    BOOL ret = TRUE;
+
+    TRACE("(%x,%p,(%d,%d),(%d,%d),(%d,%dx%d,%d)\n",
+          hConsoleOutput, lpBuffer, size.X, size.Y, coord.X, coord.Y,
+          region->Left, region->Top, region->Right, region->Bottom);
+
+    width = min( region->Right - region->Left + 1, size.X - coord.X );
+    height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
+
+    if (width > 0 && height > 0)
+    {
+        for (y = 0; y < height; y++)
+        {
+            SERVER_START_REQ( write_console_output )
+            {
+                req->handle = hConsoleOutput;
+                req->x      = region->Left;
+                req->y      = region->Top + y;
+                req->mode   = CHAR_INFO_MODE_TEXTATTR;
+                req->wrap   = FALSE;
+                wine_server_add_data( req, &lpBuffer[(y + coord.Y) * size.X + coord.X],
+                                      width * sizeof(CHAR_INFO));
+                if ((ret = !wine_server_call_err( req )))
+                {
+                    width  = min( width, reply->width - region->Left );
+                    height = min( height, reply->height - region->Top );
+                }
+            }
+            SERVER_END_REQ;
+            if (!ret) break;
+        }
+    }
+    region->Bottom = region->Top + height - 1;
+    region->Right = region->Left + width - 1;
+    return ret;
+}
+
+
+/******************************************************************************
+ * WriteConsoleOutputCharacterA [KERNEL32.@]  Copies character to consecutive
+ * 					      cells in the console screen buffer
+ *
+ * PARAMS
+ *    hConsoleOutput    [I] Handle to screen buffer
+ *    str               [I] Pointer to buffer with chars to write
+ *    length            [I] Number of cells to write to
+ *    coord             [I] Coords of first cell
+ *    lpNumCharsWritten [O] Pointer to number of cells written
+ */
+BOOL WINAPI WriteConsoleOutputCharacterA( HANDLE hConsoleOutput, LPCSTR str, DWORD length,
+                                          COORD coord, LPDWORD lpNumCharsWritten )
+{
+    BOOL ret;
+    LPWSTR strW;
+    DWORD lenW;
+
+    TRACE("(%d,%s,%ld,%dx%d,%p)\n", hConsoleOutput,
+          debugstr_an(str, length), length, coord.X, coord.Y, lpNumCharsWritten);
+
+    lenW = MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, NULL, 0 );
+
+    if (lpNumCharsWritten) *lpNumCharsWritten = 0;
+
+    if (!(strW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) return FALSE;
+    MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, strW, lenW );
+
+    ret = WriteConsoleOutputCharacterW( hConsoleOutput, strW, lenW, coord, lpNumCharsWritten );
+    HeapFree( GetProcessHeap(), 0, strW );
+    return ret;
+}
+
+
+/******************************************************************************
+ * WriteConsoleOutputAttribute [KERNEL32.@]  Sets attributes for some cells in
+ * 					     the console screen buffer
+ *
+ * PARAMS
+ *    hConsoleOutput    [I] Handle to screen buffer
+ *    attr              [I] Pointer to buffer with write attributes
+ *    length            [I] Number of cells to write to
+ *    coord             [I] Coords of first cell
+ *    lpNumAttrsWritten [O] Pointer to number of cells written
+ *
+ * RETURNS
+ *    Success: TRUE
+ *    Failure: FALSE
+ * 
+ */
+BOOL WINAPI WriteConsoleOutputAttribute( HANDLE hConsoleOutput, CONST WORD *attr, DWORD length,
+                                         COORD coord, LPDWORD lpNumAttrsWritten )
+{
+    BOOL ret;
+
+    TRACE("(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput,attr,length,coord.X,coord.Y,lpNumAttrsWritten);
+
+    SERVER_START_REQ( write_console_output )
+    {
+        req->handle = hConsoleOutput;
+        req->x      = coord.X;
+        req->y      = coord.Y;
+        req->mode   = CHAR_INFO_MODE_ATTR;
+        req->wrap   = TRUE;
+        wine_server_add_data( req, attr, length * sizeof(WORD) );
+        if ((ret = !wine_server_call_err( req )))
+        {
+            if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/******************************************************************************
+ * FillConsoleOutputCharacterA [KERNEL32.@]
+ *
+ * PARAMS
+ *    hConsoleOutput    [I] Handle to screen buffer
+ *    ch                [I] Character to write
+ *    length            [I] Number of cells to write to
+ *    coord             [I] Coords of first cell
+ *    lpNumCharsWritten [O] Pointer to number of cells written
+ *
+ * RETURNS
+ *    Success: TRUE
+ *    Failure: FALSE
+ */
+BOOL WINAPI FillConsoleOutputCharacterA( HANDLE hConsoleOutput, CHAR ch, DWORD length,
+                                         COORD coord, LPDWORD lpNumCharsWritten )
+{
+    WCHAR wch;
+
+    MultiByteToWideChar( GetConsoleOutputCP(), 0, &ch, 1, &wch, 1 );
+    return FillConsoleOutputCharacterW(hConsoleOutput, wch, length, coord, lpNumCharsWritten);
+}
+
+
+/******************************************************************************
+ * FillConsoleOutputCharacterW [KERNEL32.@]  Writes characters to console
+ *
+ * PARAMS
+ *    hConsoleOutput    [I] Handle to screen buffer
+ *    ch                [I] Character to write
+ *    length            [I] Number of cells to write to
+ *    coord             [I] Coords of first cell
+ *    lpNumCharsWritten [O] Pointer to number of cells written
+ *
+ * RETURNS
+ *    Success: TRUE
+ *    Failure: FALSE
+ */
+BOOL WINAPI FillConsoleOutputCharacterW( HANDLE hConsoleOutput, WCHAR ch, DWORD length,
+                                         COORD coord, LPDWORD lpNumCharsWritten)
+{
+    BOOL ret;
+
+    TRACE("(%d,%s,%ld,(%dx%d),%p)\n",
+          hConsoleOutput, debugstr_wn(&ch, 1), length, coord.X, coord.Y, lpNumCharsWritten);
+
+    SERVER_START_REQ( fill_console_output )
+    {
+        req->handle  = hConsoleOutput;
+        req->x       = coord.X;
+        req->y       = coord.Y;
+        req->mode    = CHAR_INFO_MODE_TEXT;
+        req->wrap    = TRUE;
+        req->data.ch = ch;
+        req->count   = length;
+        if ((ret = !wine_server_call_err( req )))
+        {
+            if (lpNumCharsWritten) *lpNumCharsWritten = reply->written;
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/******************************************************************************
+ * FillConsoleOutputAttribute [KERNEL32.@]  Sets attributes for console
+ *
+ * PARAMS
+ *    hConsoleOutput    [I] Handle to screen buffer
+ *    attr              [I] Color attribute to write
+ *    length            [I] Number of cells to write to
+ *    coord             [I] Coords of first cell
+ *    lpNumAttrsWritten [O] Pointer to number of cells written
+ *
+ * RETURNS
+ *    Success: TRUE
+ *    Failure: FALSE
+ */
+BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput, WORD attr, DWORD length,
+                                        COORD coord, LPDWORD lpNumAttrsWritten )
+{
+    BOOL ret;
+
+    TRACE("(%d,%d,%ld,(%dx%d),%p)\n",
+          hConsoleOutput, attr, length, coord.X, coord.Y, lpNumAttrsWritten);
+
+    SERVER_START_REQ( fill_console_output )
+    {
+        req->handle    = hConsoleOutput;
+        req->x         = coord.X;
+        req->y         = coord.Y;
+        req->mode      = CHAR_INFO_MODE_ATTR;
+        req->wrap      = TRUE;
+        req->data.attr = attr;
+        req->count     = length;
+        if ((ret = !wine_server_call_err( req )))
+        {
+            if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/******************************************************************************
+ * ReadConsoleOutputCharacterA [KERNEL32.@]
+ * 
+ */
+BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpstr, DWORD count,
+                                        COORD coord, LPDWORD read_count)
+{
+    DWORD read;
+    BOOL ret;
+    LPWSTR wptr = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
+
+    if (read_count) *read_count = 0;
+    if (!wptr) return FALSE;
+
+    if ((ret = ReadConsoleOutputCharacterW( hConsoleOutput, wptr, count, coord, &read )))
+    {
+        read = WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr, read, lpstr, count, NULL, NULL);
+        if (read_count) *read_count = read;
+    }
+    HeapFree( GetProcessHeap(), 0, wptr );
+    return ret;
+}
+
+
+/******************************************************************************
+ * ReadConsoleOutputCharacterW [KERNEL32.@]
+ * 
+ */
+BOOL WINAPI ReadConsoleOutputCharacterW( HANDLE hConsoleOutput, LPWSTR buffer, DWORD count,
+                                         COORD coord, LPDWORD read_count )
+{
+    BOOL ret;
+
+    TRACE( "(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput, buffer, count, coord.X, coord.Y, read_count );
+
+    SERVER_START_REQ( read_console_output )
+    {
+        req->handle = hConsoleOutput;
+        req->x      = coord.X;
+        req->y      = coord.Y;
+        req->mode   = CHAR_INFO_MODE_TEXT;
+        req->wrap   = TRUE;
+        wine_server_set_reply( req, buffer, count * sizeof(WCHAR) );
+        if ((ret = !wine_server_call_err( req )))
+        {
+            if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WCHAR);
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/******************************************************************************
+ *  ReadConsoleOutputAttribute [KERNEL32.@]
+ */
+BOOL WINAPI ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD length,
+                                       COORD coord, LPDWORD read_count)
+{
+    BOOL ret;
+
+    TRACE("(%d,%p,%ld,%dx%d,%p)\n",
+          hConsoleOutput, lpAttribute, length, coord.X, coord.Y, read_count);
+
+    SERVER_START_REQ( read_console_output )
+    {
+        req->handle = hConsoleOutput;
+        req->x      = coord.X;
+        req->y      = coord.Y;
+        req->mode   = CHAR_INFO_MODE_ATTR;
+        req->wrap   = TRUE;
+        wine_server_set_reply( req, lpAttribute, length * sizeof(WORD) );
+        if ((ret = !wine_server_call_err( req )))
+        {
+            if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WORD);
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/******************************************************************************
+ *  ReadConsoleOutputA [KERNEL32.@]
+ * 
+ */
+BOOL WINAPI ReadConsoleOutputA( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
+                                COORD coord, LPSMALL_RECT region )
+{
+    BOOL ret;
+    int y;
+
+    ret = ReadConsoleOutputW( hConsoleOutput, lpBuffer, size, coord, region );
+    if (ret && region->Right >= region->Left)
+    {
+        for (y = 0; y <= region->Bottom - region->Top; y++)
+        {
+            char_info_WtoA( &lpBuffer[(coord.Y + y) * size.X + coord.X],
+                            region->Right - region->Left + 1 );
+        }
+    }
+    return ret;
+}
+
+
+/******************************************************************************
+ *  ReadConsoleOutputW [KERNEL32.@]
+ * 
+ * NOTE: The NT4 (sp5) kernel crashes on me if size is (0,0). I don't
+ * think we need to be *that* compatible.  -- AJ
+ */
+BOOL WINAPI ReadConsoleOutputW( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
+                                COORD coord, LPSMALL_RECT region )
+{
+    int width, height, y;
+    BOOL ret = TRUE;
+
+    width = min( region->Right - region->Left + 1, size.X - coord.X );
+    height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
+
+    if (width > 0 && height > 0)
+    {
+        for (y = 0; y < height; y++)
+        {
+            SERVER_START_REQ( read_console_output )
+            {
+                req->handle = hConsoleOutput;
+                req->x      = region->Left;
+                req->y      = region->Top + y;
+                req->mode   = CHAR_INFO_MODE_TEXTATTR;
+                req->wrap   = FALSE;
+                wine_server_set_reply( req, &lpBuffer[(y+coord.Y) * size.X + coord.X],
+                                       width * sizeof(CHAR_INFO) );
+                if ((ret = !wine_server_call_err( req )))
+                {
+                    width  = min( width, reply->width - region->Left );
+                    height = min( height, reply->height - region->Top );
+                }
+            }
+            SERVER_END_REQ;
+            if (!ret) break;
+        }
+    }
+    region->Bottom = region->Top + height - 1;
+    region->Right = region->Left + width - 1;
+    return ret;
+}
+
+
+/******************************************************************************
+ * ReadConsoleInputA [KERNEL32.@]  Reads data from a console
+ *
+ * PARAMS
+ *    handle   [I] Handle to console input buffer
+ *    buffer   [O] Address of buffer for read data
+ *    count    [I] Number of records to read
+ *    pRead    [O] Address of number of records read
+ *
+ * RETURNS
+ *    Success: TRUE
+ *    Failure: FALSE
+ */
+BOOL WINAPI ReadConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
+{
+    DWORD read;
+
+    if (!ReadConsoleInputW( handle, buffer, count, &read )) return FALSE;
+    input_records_WtoA( buffer, read );
+    if (pRead) *pRead = read;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *            PeekConsoleInputA   (KERNEL32.@)
+ *
+ * Gets 'count' first events (or less) from input queue.
+ */
+BOOL WINAPI PeekConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
+{
+    DWORD read;
+
+    if (!PeekConsoleInputW( handle, buffer, count, &read )) return FALSE;
+    input_records_WtoA( buffer, read );
+    if (pRead) *pRead = read;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *            PeekConsoleInputW   (KERNEL32.@)
+ */
+BOOL WINAPI PeekConsoleInputW( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD read )
+{
+    BOOL ret;
+    SERVER_START_REQ( read_console_input )
+    {
+        req->handle = handle;
+        req->flush  = FALSE;
+        wine_server_set_reply( req, buffer, count * sizeof(INPUT_RECORD) );
+        if ((ret = !wine_server_call_err( req )))
+        {
+            if (read) *read = count ? reply->read : 0;
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/***********************************************************************
+ *            GetNumberOfConsoleInputEvents   (KERNEL32.@)
+ */
+BOOL WINAPI GetNumberOfConsoleInputEvents( HANDLE handle, LPDWORD nrofevents )
+{
+    BOOL ret;
+    SERVER_START_REQ( read_console_input )
+    {
+        req->handle = handle;
+        req->flush  = FALSE;
+        if ((ret = !wine_server_call_err( req )))
+        {
+            if (nrofevents) *nrofevents = reply->read;
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/***********************************************************************
+ *            FlushConsoleInputBuffer   (KERNEL32.@)
+ */
+BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
+{
+    BOOL ret;
+    SERVER_START_REQ( read_console_input )
+    {
+        req->handle = handle;
+        req->flush  = TRUE;
+        ret = !wine_server_call_err( req );
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/***********************************************************************
+ *            SetConsoleTitleA   (KERNEL32.@)
+ */
+BOOL WINAPI SetConsoleTitleA( LPCSTR title )
+{
+    LPWSTR titleW;
+    BOOL ret;
+
+    DWORD len = MultiByteToWideChar( GetConsoleOutputCP(), 0, title, -1, NULL, 0 );
+    if (!(titleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) return FALSE;
+    MultiByteToWideChar( GetConsoleOutputCP(), 0, title, -1, titleW, len );
+    ret = SetConsoleTitleW(titleW);
+    HeapFree(GetProcessHeap(), 0, titleW);
+    return ret;
+}
+
+
+/***********************************************************************
+ *            GetConsoleTitleA   (KERNEL32.@)
+ */
+DWORD WINAPI GetConsoleTitleA(LPSTR title, DWORD size)
+{
+    WCHAR *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
+    DWORD ret;
+
+    if (!ptr) return 0;
+    ret = GetConsoleTitleW( ptr, size );
+    if (ret)
+    {
+        WideCharToMultiByte( GetConsoleOutputCP(), 0, ptr, ret + 1, title, size, NULL, NULL);
+        ret = strlen(title);
+    }
+    return ret;
+}
+
+
+/******************************************************************************
+ * GetConsoleTitleW [KERNEL32.@]  Retrieves title string for console
+ *
+ * PARAMS
+ *    title [O] Address of buffer for title
+ *    size  [I] Size of buffer
+ *
+ * RETURNS
+ *    Success: Length of string copied
+ *    Failure: 0
+ */
+DWORD WINAPI GetConsoleTitleW(LPWSTR title, DWORD size)
+{
+    DWORD ret = 0;
+
+    SERVER_START_REQ( get_console_input_info )
+    {
+        req->handle = 0;
+        wine_server_set_reply( req, title, (size-1) * sizeof(WCHAR) );
+        if (!wine_server_call_err( req ))
+        {
+            ret = wine_server_reply_size(reply) / sizeof(WCHAR);
+            title[ret] = 0;
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
+}
+
+
+/***********************************************************************
+ *            GetLargestConsoleWindowSize   (KERNEL32.@)
+ *
+ * NOTE
+ *	This should return a COORD, but calling convention for returning
+ *      structures is different between Windows and gcc on i386.
+ *
+ * VERSION: [i386]
+ */
+#ifdef __i386__
+#undef GetLargestConsoleWindowSize
+DWORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
+{
+    COORD c;
+    c.X = 80;
+    c.Y = 24;
+    return *(DWORD *)&c;
+}
+#endif /* defined(__i386__) */
+
+
+/***********************************************************************
+ *            GetLargestConsoleWindowSize   (KERNEL32.@)
+ *
+ * NOTE
+ *	This should return a COORD, but calling convention for returning
+ *      structures is different between Windows and gcc on i386.
+ *
+ * VERSION: [!i386]
+ */
+#ifndef __i386__
+COORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
+{
+    COORD c;
+    c.X = 80;
+    c.Y = 24;
+    return c;
+}
+#endif /* defined(__i386__) */
diff --git a/dlls/kernel/debugger.c b/dlls/kernel/debugger.c
index 0fdd382..fbe8ff6 100644
--- a/dlls/kernel/debugger.c
+++ b/dlls/kernel/debugger.c
@@ -36,78 +36,78 @@
     for (;;)
     {
         HANDLE wait = 0;
-        debug_event_t *data;
-        SERVER_START_VAR_REQ( wait_debug_event, sizeof(*data) )
+        debug_event_t data;
+        SERVER_START_REQ( wait_debug_event )
         {
             req->get_handle = (timeout != 0);
-            if (!(ret = !SERVER_CALL_ERR())) goto done;
+            wine_server_set_reply( req, &data, sizeof(data) );
+            if (!(ret = !wine_server_call_err( req ))) goto done;
 
-            if (!server_data_size(req))  /* timeout */
+            if (!wine_server_reply_size(reply))  /* timeout */
             {
-                wait = req->wait;
+                wait = reply->wait;
                 ret = FALSE;
                 goto done;
             }
-            data = server_data_ptr(req);
-            event->dwDebugEventCode = data->code;
-            event->dwProcessId      = (DWORD)req->pid;
-            event->dwThreadId       = (DWORD)req->tid;
-            switch(data->code)
+            event->dwDebugEventCode = data.code;
+            event->dwProcessId      = (DWORD)reply->pid;
+            event->dwThreadId       = (DWORD)reply->tid;
+            switch(data.code)
             {
             case EXCEPTION_DEBUG_EVENT:
-                event->u.Exception.ExceptionRecord = data->info.exception.record;
-                event->u.Exception.dwFirstChance   = data->info.exception.first;
+                event->u.Exception.ExceptionRecord = data.info.exception.record;
+                event->u.Exception.dwFirstChance   = data.info.exception.first;
                 break;
             case CREATE_THREAD_DEBUG_EVENT:
-                event->u.CreateThread.hThread           = data->info.create_thread.handle;
-                event->u.CreateThread.lpThreadLocalBase = data->info.create_thread.teb;
-                event->u.CreateThread.lpStartAddress    = data->info.create_thread.start;
+                event->u.CreateThread.hThread           = data.info.create_thread.handle;
+                event->u.CreateThread.lpThreadLocalBase = data.info.create_thread.teb;
+                event->u.CreateThread.lpStartAddress    = data.info.create_thread.start;
                 break;
             case CREATE_PROCESS_DEBUG_EVENT:
-                event->u.CreateProcessInfo.hFile                 = data->info.create_process.file;
-                event->u.CreateProcessInfo.hProcess              = data->info.create_process.process;
-                event->u.CreateProcessInfo.hThread               = data->info.create_process.thread;
-                event->u.CreateProcessInfo.lpBaseOfImage         = data->info.create_process.base;
-                event->u.CreateProcessInfo.dwDebugInfoFileOffset = data->info.create_process.dbg_offset;
-                event->u.CreateProcessInfo.nDebugInfoSize        = data->info.create_process.dbg_size;
-                event->u.CreateProcessInfo.lpThreadLocalBase     = data->info.create_process.teb;
-                event->u.CreateProcessInfo.lpStartAddress        = data->info.create_process.start;
-                event->u.CreateProcessInfo.lpImageName           = data->info.create_process.name;
-                event->u.CreateProcessInfo.fUnicode              = data->info.create_process.unicode;
-                if (data->info.create_process.file == -1) event->u.CreateProcessInfo.hFile = 0;
+                event->u.CreateProcessInfo.hFile                 = data.info.create_process.file;
+                event->u.CreateProcessInfo.hProcess              = data.info.create_process.process;
+                event->u.CreateProcessInfo.hThread               = data.info.create_process.thread;
+                event->u.CreateProcessInfo.lpBaseOfImage         = data.info.create_process.base;
+                event->u.CreateProcessInfo.dwDebugInfoFileOffset = data.info.create_process.dbg_offset;
+                event->u.CreateProcessInfo.nDebugInfoSize        = data.info.create_process.dbg_size;
+                event->u.CreateProcessInfo.lpThreadLocalBase     = data.info.create_process.teb;
+                event->u.CreateProcessInfo.lpStartAddress        = data.info.create_process.start;
+                event->u.CreateProcessInfo.lpImageName           = data.info.create_process.name;
+                event->u.CreateProcessInfo.fUnicode              = data.info.create_process.unicode;
+                if (data.info.create_process.file == -1) event->u.CreateProcessInfo.hFile = 0;
                 break;
             case EXIT_THREAD_DEBUG_EVENT:
-                event->u.ExitThread.dwExitCode = data->info.exit.exit_code;
+                event->u.ExitThread.dwExitCode = data.info.exit.exit_code;
                 break;
             case EXIT_PROCESS_DEBUG_EVENT:
-                event->u.ExitProcess.dwExitCode = data->info.exit.exit_code;
+                event->u.ExitProcess.dwExitCode = data.info.exit.exit_code;
                 break;
             case LOAD_DLL_DEBUG_EVENT:
-                event->u.LoadDll.hFile                 = data->info.load_dll.handle;
-                event->u.LoadDll.lpBaseOfDll           = data->info.load_dll.base;
-                event->u.LoadDll.dwDebugInfoFileOffset = data->info.load_dll.dbg_offset;
-                event->u.LoadDll.nDebugInfoSize        = data->info.load_dll.dbg_size;
-                event->u.LoadDll.lpImageName           = data->info.load_dll.name;
-                event->u.LoadDll.fUnicode              = data->info.load_dll.unicode;
-                if (data->info.load_dll.handle == -1) event->u.LoadDll.hFile = 0;
+                event->u.LoadDll.hFile                 = data.info.load_dll.handle;
+                event->u.LoadDll.lpBaseOfDll           = data.info.load_dll.base;
+                event->u.LoadDll.dwDebugInfoFileOffset = data.info.load_dll.dbg_offset;
+                event->u.LoadDll.nDebugInfoSize        = data.info.load_dll.dbg_size;
+                event->u.LoadDll.lpImageName           = data.info.load_dll.name;
+                event->u.LoadDll.fUnicode              = data.info.load_dll.unicode;
+                if (data.info.load_dll.handle == -1) event->u.LoadDll.hFile = 0;
                 break;
             case UNLOAD_DLL_DEBUG_EVENT:
-                event->u.UnloadDll.lpBaseOfDll = data->info.unload_dll.base;
+                event->u.UnloadDll.lpBaseOfDll = data.info.unload_dll.base;
                 break;
             case OUTPUT_DEBUG_STRING_EVENT:
-                event->u.DebugString.lpDebugStringData  = data->info.output_string.string;
-                event->u.DebugString.fUnicode           = data->info.output_string.unicode;
-                event->u.DebugString.nDebugStringLength = data->info.output_string.length;
+                event->u.DebugString.lpDebugStringData  = data.info.output_string.string;
+                event->u.DebugString.fUnicode           = data.info.output_string.unicode;
+                event->u.DebugString.nDebugStringLength = data.info.output_string.length;
                 break;
             case RIP_EVENT:
-                event->u.RipInfo.dwError = data->info.rip_info.error;
-                event->u.RipInfo.dwType  = data->info.rip_info.type;
+                event->u.RipInfo.dwError = data.info.rip_info.error;
+                event->u.RipInfo.dwType  = data.info.rip_info.type;
                 break;
             }
         done:
             /* nothing */ ;
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
         if (ret) return TRUE;
         if (!wait) break;
         res = WaitForSingleObject( wait, timeout );
@@ -140,7 +140,7 @@
         req->pid    = (void *)pid;
         req->tid    = (void *)tid;
         req->status = status;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -163,7 +163,7 @@
     SERVER_START_REQ( debug_process )
     {
         req->pid = (void *)pid;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -184,7 +184,7 @@
         req->string  = (void *)str;
         req->unicode = 0;
         req->length  = strlen(str) + 1;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
     WARN("%s\n", str);
@@ -205,7 +205,7 @@
         req->string  = (void *)str;
         req->unicode = 1;
         req->length  = (lstrlenW(str) + 1) * sizeof(WCHAR);
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
     WARN("%s\n", debugstr_w(str));
@@ -278,7 +278,7 @@
     SERVER_START_REQ( get_process_info )
     {
         req->handle = GetCurrentProcess();
-        if (!SERVER_CALL_ERR()) ret = req->debugged;
+        if (!wine_server_call_err( req )) ret = reply->debugged;
     }
     SERVER_END_REQ;
     return ret;
diff --git a/dlls/kernel/sync.c b/dlls/kernel/sync.c
index 5fe788a..4d74642 100644
--- a/dlls/kernel/sync.c
+++ b/dlls/kernel/sync.c
@@ -30,25 +30,16 @@
 HANDLE WINAPI CreateEventA( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
                             BOOL initial_state, LPCSTR name )
 {
-    HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
-    if (len >= MAX_PATH)
+    WCHAR buffer[MAX_PATH];
+
+    if (!name) return CreateEventW( sa, manual_reset, initial_state, NULL );
+
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( create_event, len * sizeof(WCHAR) )
-    {
-        req->manual_reset = manual_reset;
-        req->initial_state = initial_state;
-        req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return CreateEventW( sa, manual_reset, initial_state, buffer );
 }
 
 
@@ -74,17 +65,17 @@
         SetLastError( ERROR_INVALID_PARAMETER);
         return 0;
     }
-    SERVER_START_VAR_REQ( create_event, len * sizeof(WCHAR) )
+    SERVER_START_REQ( create_event )
     {
         req->manual_reset = manual_reset;
         req->initial_state = initial_state;
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -103,23 +94,16 @@
  */
 HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name )
 {
-    HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
-    if (len >= MAX_PATH)
+    WCHAR buffer[MAX_PATH];
+
+    if (!name) return OpenEventW( access, inherit, NULL );
+
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_event, len * sizeof(WCHAR) )
-    {
-        req->access  = access;
-        req->inherit = inherit;
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return OpenEventW( access, inherit, buffer );
 }
 
 
@@ -135,15 +119,15 @@
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_event, len * sizeof(WCHAR) )
+    SERVER_START_REQ( open_event )
     {
         req->access  = access;
         req->inherit = inherit;
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -160,7 +144,7 @@
     {
         req->handle = handle;
         req->op     = op;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -248,24 +232,16 @@
  */
 HANDLE WINAPI CreateMutexA( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCSTR name )
 {
-    HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
-    if (len >= MAX_PATH)
+    WCHAR buffer[MAX_PATH];
+
+    if (!name) return CreateMutexW( sa, owner, NULL );
+
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( create_mutex, len * sizeof(WCHAR) )
-    {
-        req->owned   = owner;
-        req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return CreateMutexW( sa, owner, buffer );
 }
 
 
@@ -281,47 +257,35 @@
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( create_mutex, len * sizeof(WCHAR) )
+    SERVER_START_REQ( create_mutex )
     {
         req->owned   = owner;
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
 
-/*
- * Mutexes
- */
-
-
 /***********************************************************************
  *           OpenMutexA   (KERNEL32.@)
  */
 HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name )
 {
-    HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
-    if (len >= MAX_PATH)
+    WCHAR buffer[MAX_PATH];
+
+    if (!name) return OpenMutexW( access, inherit, NULL );
+
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_mutex, len * sizeof(WCHAR) )
-    {
-        req->access  = access;
-        req->inherit = inherit;
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return OpenMutexW( access, inherit, buffer );
 }
 
 
@@ -337,15 +301,15 @@
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_mutex, len * sizeof(WCHAR) )
+    SERVER_START_REQ( open_mutex )
     {
         req->access  = access;
         req->inherit = inherit;
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -359,7 +323,7 @@
     SERVER_START_REQ( release_mutex )
     {
         req->handle = handle;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -376,34 +340,16 @@
  */
 HANDLE WINAPI CreateSemaphoreA( SECURITY_ATTRIBUTES *sa, LONG initial, LONG max, LPCSTR name )
 {
-    HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
+    WCHAR buffer[MAX_PATH];
 
-    /* Check parameters */
+    if (!name) return CreateSemaphoreW( sa, initial, max, NULL );
 
-    if ((max <= 0) || (initial < 0) || (initial > max))
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return 0;
-    }
-    if (len >= MAX_PATH)
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-
-    SERVER_START_VAR_REQ( create_semaphore, len * sizeof(WCHAR) )
-    {
-        req->initial = (unsigned int)initial;
-        req->max     = (unsigned int)max;
-        req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return CreateSemaphoreW( sa, initial, max, buffer );
 }
 
 
@@ -429,17 +375,17 @@
         return 0;
     }
 
-    SERVER_START_VAR_REQ( create_semaphore, len * sizeof(WCHAR) )
+    SERVER_START_REQ( create_semaphore )
     {
         req->initial = (unsigned int)initial;
         req->max     = (unsigned int)max;
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -449,23 +395,16 @@
  */
 HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name )
 {
-    HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
-    if (len >= MAX_PATH)
+    WCHAR buffer[MAX_PATH];
+
+    if (!name) return OpenSemaphoreW( access, inherit, NULL );
+
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_semaphore, len * sizeof(WCHAR) )
-    {
-        req->access  = access;
-        req->inherit = inherit;
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return OpenSemaphoreW( access, inherit, buffer );
 }
 
 
@@ -481,15 +420,15 @@
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_semaphore, len * sizeof(WCHAR) )
+    SERVER_START_REQ( open_semaphore )
     {
         req->access  = access;
         req->inherit = inherit;
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -518,35 +457,18 @@
                                 DWORD nOutBufferSize, DWORD nInBufferSize,
                                 DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES attr )
 {
-    HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
+    WCHAR buffer[MAX_PATH];
 
-    TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p): stub\n",
-          debugstr_a(name), dwOpenMode, dwPipeMode, nMaxInstances,
-          nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
+    if (!name) return CreateNamedPipeW( NULL, dwOpenMode, dwPipeMode, nMaxInstances,
+                                        nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
 
-    if (len >= MAX_PATH)
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( create_named_pipe, len * sizeof(WCHAR) )
-    {
-        req->openmode = dwOpenMode;
-        req->pipemode = dwPipeMode;
-        req->maxinstances = nMaxInstances;
-        req->outsize = nOutBufferSize;
-        req->insize = nInBufferSize;
-        req->timeout = nDefaultTimeOut;
-
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    TRACE("Returned %d\n",ret);
-    return ret;
+    return CreateNamedPipeW( buffer, dwOpenMode, dwPipeMode, nMaxInstances,
+                             nOutBufferSize, nInBufferSize, nDefaultTimeOut, attr );
 }
 
 
@@ -570,7 +492,7 @@
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( create_named_pipe, len * sizeof(WCHAR) )
+    SERVER_START_REQ( create_named_pipe )
     {
         req->openmode = dwOpenMode;
         req->pipemode = dwPipeMode;
@@ -578,13 +500,12 @@
         req->outsize = nOutBufferSize;
         req->insize = nInBufferSize;
         req->timeout = nDefaultTimeOut;
-
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -613,99 +534,40 @@
     SetEvent(overlapped->hEvent);
 }
 
-/***********************************************************************
- *           WaitNamedPipeA   (KERNEL32.@)
- */
-static BOOL SYNC_WaitNamedPipeA (LPCSTR name, DWORD nTimeOut, LPOVERLAPPED overlapped)
-{
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
-    BOOL ret;
-
-    if (len >= MAX_PATH)
-    {
-        SetLastError( ERROR_FILENAME_EXCED_RANGE );
-        return FALSE;
-    }
-
-    SERVER_START_VAR_REQ( wait_named_pipe, len * sizeof(WCHAR) )
-    {
-        req->timeout = nTimeOut;
-        req->overlapped = overlapped;
-        req->func = SYNC_CompletePipeOverlapped;
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        ret = !SERVER_CALL_ERR();
-    }
-    SERVER_END_REQ;
-
-    return ret;
-}
 
 /***********************************************************************
  *           WaitNamedPipeA   (KERNEL32.@)
  */
 BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
 {
-    BOOL ret;
-    OVERLAPPED ov;
+    WCHAR buffer[MAX_PATH];
 
-    TRACE("%s 0x%08lx\n",debugstr_a(name),nTimeOut);
+    if (!name) return WaitNamedPipeW( NULL, nTimeOut );
 
-    memset(&ov,0,sizeof ov);
-    ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
-    if (!ov.hEvent)
-        return FALSE;
-
-    /* expect to fail with STATUS_PENDING */
-    ret = SYNC_WaitNamedPipeA(name, nTimeOut, &ov);
-    if(ret)
-    {
-        if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
-        {
-            SetLastError(ov.Internal);
-            ret = (ov.Internal==STATUS_SUCCESS);
-        }
-    }
-
-    CloseHandle(ov.hEvent);
-    return ret;
-}
-
-
-/***********************************************************************
- *           WaitNamedPipeW   (KERNEL32.@)
- */
-static BOOL SYNC_WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut, LPOVERLAPPED overlapped)
-{
-    DWORD len = name ? strlenW(name) : 0;
-    BOOL ret;
-
-    if (len >= MAX_PATH)
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
-        return FALSE;
+        return 0;
     }
-
-    SERVER_START_VAR_REQ( wait_named_pipe, len * sizeof(WCHAR) )
-    {
-        req->timeout = nTimeOut;
-        req->overlapped = overlapped;
-        req->func = SYNC_CompletePipeOverlapped;
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
-        ret = !SERVER_CALL_ERR();
-    }
-    SERVER_END_REQ;
-
-    return ret;
+    return WaitNamedPipeW( buffer, nTimeOut );
 }
 
+
 /***********************************************************************
  *           WaitNamedPipeW   (KERNEL32.@)
  */
 BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
 {
+    DWORD len = name ? strlenW(name) : 0;
     BOOL ret;
     OVERLAPPED ov;
 
+    if (len >= MAX_PATH)
+    {
+        SetLastError( ERROR_FILENAME_EXCED_RANGE );
+        return FALSE;
+    }
+
     TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
 
     memset(&ov,0,sizeof ov);
@@ -713,7 +575,16 @@
     if (!ov.hEvent)
         return FALSE;
 
-    ret = SYNC_WaitNamedPipeW(name, nTimeOut, &ov);
+    SERVER_START_REQ( wait_named_pipe )
+    {
+        req->timeout = nTimeOut;
+        req->overlapped = &ov;
+        req->func = SYNC_CompletePipeOverlapped;
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
+        ret = !wine_server_call_err( req );
+    }
+    SERVER_END_REQ;
+
     if(ret)
     {
         if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
@@ -722,9 +593,7 @@
             ret = (ov.Internal==STATUS_SUCCESS);
         }
     }
-
     CloseHandle(ov.hEvent);
-
     return ret;
 }
 
@@ -746,7 +615,7 @@
         req->handle = hPipe;
         req->overlapped = overlapped;
         req->func = SYNC_CompletePipeOverlapped;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
 
@@ -798,7 +667,7 @@
     SERVER_START_REQ( disconnect_named_pipe )
     {
         req->handle = hPipe;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
 
@@ -835,15 +704,11 @@
     SERVER_START_REQ( get_named_pipe_info )
     {
         req->handle = hNamedPipe;
-        ret = !SERVER_CALL_ERR();
-        if(lpFlags)
-            *lpFlags = req->flags;
-        if(lpOutputBufferSize)
-            *lpOutputBufferSize = req->outsize;
-        if(lpInputBufferSize)
-            *lpInputBufferSize = req->outsize;
-        if(lpMaxInstances)
-            *lpMaxInstances = req->maxinstances;
+        ret = !wine_server_call_err( req );
+        if(lpFlags) *lpFlags = reply->flags;
+        if(lpOutputBufferSize) *lpOutputBufferSize = reply->outsize;
+        if(lpInputBufferSize) *lpInputBufferSize = reply->outsize;
+        if(lpMaxInstances) *lpMaxInstances = reply->maxinstances;
     }
     SERVER_END_REQ;
 
diff --git a/dlls/kernel/toolhelp.c b/dlls/kernel/toolhelp.c
index ed9ddb8..7c1dc71 100644
--- a/dlls/kernel/toolhelp.c
+++ b/dlls/kernel/toolhelp.c
@@ -206,8 +206,8 @@
         req->flags   = flags & ~TH32CS_INHERIT;
         req->inherit = (flags & TH32CS_INHERIT) != 0;
         req->pid     = (void *)process;
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
     SERVER_END_REQ;
     if (!ret) ret = INVALID_HANDLE_VALUE;
@@ -234,13 +234,13 @@
     {
         req->handle = handle;
         req->reset = first;
-        if ((ret = !SERVER_CALL_ERR()))
+        if ((ret = !wine_server_call_err( req )))
         {
-            lpte->cntUsage           = req->count;
-            lpte->th32ThreadID       = (DWORD)req->tid;
-            lpte->th32OwnerProcessID = (DWORD)req->pid;
-            lpte->tpBasePri          = req->base_pri;
-            lpte->tpDeltaPri         = req->delta_pri;
+            lpte->cntUsage           = reply->count;
+            lpte->th32ThreadID       = (DWORD)reply->tid;
+            lpte->th32OwnerProcessID = (DWORD)reply->pid;
+            lpte->tpBasePri          = reply->base_pri;
+            lpte->tpDeltaPri         = reply->delta_pri;
             lpte->dwFlags            = 0;  /* SDK: "reserved; do not use" */
         }
     }
@@ -287,15 +287,15 @@
     {
         req->handle = handle;
         req->reset = first;
-        if ((ret = !SERVER_CALL_ERR()))
+        if ((ret = !wine_server_call_err( req )))
         {
-            lppe->cntUsage            = req->count;
-            lppe->th32ProcessID       = (DWORD)req->pid;
+            lppe->cntUsage            = reply->count;
+            lppe->th32ProcessID       = (DWORD)reply->pid;
             lppe->th32DefaultHeapID   = 0;  /* FIXME */
             lppe->th32ModuleID        = 0;  /* FIXME */
-            lppe->cntThreads          = req->threads;
+            lppe->cntThreads          = reply->threads;
             lppe->th32ParentProcessID = 0;  /* FIXME */
-            lppe->pcPriClassBase      = req->priority;
+            lppe->pcPriClassBase      = reply->priority;
             lppe->dwFlags             = -1; /* FIXME */
             lppe->szExeFile[0]        = 0;  /* FIXME */
         }
@@ -345,15 +345,15 @@
     {
         req->handle = handle;
         req->reset = first;
-        if ((ret = !SERVER_CALL_ERR()))
+        if ((ret = !wine_server_call_err( req )))
         {
             lpme->th32ModuleID   = 0;  /* toolhelp internal id, never used */
-            lpme->th32ProcessID  = (DWORD)req->pid;
+            lpme->th32ProcessID  = (DWORD)reply->pid;
             lpme->GlblcntUsage   = 0; /* FIXME */
-            lpme->ProccntUsage   = 0; /* FIXME */ 
-            lpme->modBaseAddr    = req->base;
+            lpme->ProccntUsage   = 0; /* FIXME */
+            lpme->modBaseAddr    = reply->base;
             lpme->modBaseSize    = 0; /* FIXME */
-            lpme->hModule        = (DWORD)req->base;
+            lpme->hModule        = (DWORD)reply->base;
             lpme->szModule[0]    = 0;  /* FIXME */
             lpme->szExePath[0]   = 0;  /* FIXME */
         }
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index 90927ad..a59e30b 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -115,29 +115,28 @@
     int ret;
     HANDLE handle = 0;
 
-    SERVER_START_VAR_REQ( queue_exception_event, sizeof(*rec)+sizeof(*context) )
+    SERVER_START_REQ( queue_exception_event )
     {
-        CONTEXT *context_ptr = server_data_ptr(req);
-        EXCEPTION_RECORD *rec_ptr = (EXCEPTION_RECORD *)(context_ptr + 1);
         req->first   = first_chance;
-        *rec_ptr     = *rec;
-        *context_ptr = *context;
-        if (!SERVER_CALL()) handle = req->handle;
+        wine_server_add_data( req, context, sizeof(*context) );
+        wine_server_add_data( req, rec, sizeof(*rec) );
+        if (!wine_server_call( req )) handle = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     if (!handle) return 0;  /* no debugger present or other error */
 
     /* No need to wait on the handle since the process gets suspended
      * once the event is passed to the debugger, so when we get back
      * here the event has been continued already.
      */
-    SERVER_START_VAR_REQ( get_exception_status, sizeof(*context) )
+    SERVER_START_REQ( get_exception_status )
     {
         req->handle = handle;
-        if (!SERVER_CALL()) *context = *(CONTEXT *)server_data_ptr(req);
-        ret = req->status;
+        wine_server_set_reply( req, context, sizeof(*context) );
+        wine_server_call( req );
+        ret = reply->status;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     NtClose( handle );
     return ret;
 }
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index 46f1a10..73a4abe 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -82,8 +82,8 @@
     {
         req->handle    = handle;
         req->exit_code = exit_code;
-        ret = SERVER_CALL();
-        self = !ret && req->self;
+        ret = wine_server_call( req );
+        self = !ret && reply->self;
     }
     SERVER_END_REQ;
     if (self) exit( exit_code );
@@ -159,9 +159,9 @@
     {
         req->handle    = handle;
         req->exit_code = exit_code;
-        ret = SERVER_CALL();
-        self = !ret && req->self;
-        last = req->last;
+        ret = wine_server_call( req );
+        self = !ret && reply->self;
+        last = reply->last;
     }
     SERVER_END_REQ;
 
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index bd088f3..2cc319b 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1033,6 +1033,4 @@
 @ cdecl __wine_get_wmain_args(ptr) __wine_get_wmain_args
 
 # Server interface
-@ cdecl -norelay wine_server_call(ptr long) wine_server_call
-@ cdecl -norelay wine_server_alloc_req(ptr long) wine_server_alloc_req
-@ cdecl -norelay __wine_server_exception_handler(ptr ptr ptr ptr) __wine_server_exception_handler
+@ cdecl -norelay wine_server_call(ptr) wine_server_call
diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c
index 9a573b9..437d2b6 100644
--- a/dlls/ntdll/om.c
+++ b/dlls/ntdll/om.c
@@ -222,8 +222,8 @@
     SERVER_START_REQ( close_handle )
     {
         req->handle = Handle;
-        ret = SERVER_CALL();
-        if (!ret && req->fd != -1) close( req->fd );
+        ret = wine_server_call( req );
+        if (!ret && reply->fd != -1) close( reply->fd );
     }
     SERVER_END_REQ;
     return ret;
diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c
index 5dc307d..f271c0f 100644
--- a/dlls/ntdll/reg.c
+++ b/dlls/ntdll/reg.c
@@ -35,39 +35,29 @@
                              PULONG dispos )
 {
     NTSTATUS ret;
-    DWORD len = attr->ObjectName->Length;
 
     TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
            debugstr_us(class), options, access, retkey );
 
-    if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
-    len += sizeof(WCHAR);  /* for storing name length */
-    if (class)
-    {
-        len += class->Length;
-        if (len > REQUEST_MAX_VAR_SIZE) return STATUS_BUFFER_OVERFLOW;
-    }
+    if (attr->ObjectName->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
     if (!retkey) return STATUS_INVALID_PARAMETER;
 
-    SERVER_START_VAR_REQ( create_key, len )
+    SERVER_START_REQ( create_key )
     {
-        WCHAR *data = server_data_ptr(req);
-
         req->parent  = attr->RootDirectory;
         req->access  = access;
         req->options = options;
         req->modif   = 0;
-
-        *data++ = attr->ObjectName->Length;
-        memcpy( data, attr->ObjectName->Buffer, attr->ObjectName->Length );
-        if (class) memcpy( (char *)data + attr->ObjectName->Length, class->Buffer, class->Length );
-        if (!(ret = SERVER_CALL()))
+        req->namelen = attr->ObjectName->Length;
+        wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
+        if (class) wine_server_add_data( req, class->Buffer, class->Length );
+        if (!(ret = wine_server_call( req )))
         {
-            *retkey = req->hkey;
-            if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
+            *retkey = reply->hkey;
+            if (dispos) *dispos = reply->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
         }
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     TRACE("<- 0x%04x\n", *retkey);
     return ret;
 }
@@ -92,15 +82,15 @@
     if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
     if (!retkey) return STATUS_INVALID_PARAMETER;
 
-    SERVER_START_VAR_REQ( open_key, len )
+    SERVER_START_REQ( open_key )
     {
         req->parent = attr->RootDirectory;
         req->access = access;
-        memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
-        ret = SERVER_CALL();
-        *retkey = req->hkey;
+        wine_server_add_data( req, attr->ObjectName->Buffer, len );
+        ret = wine_server_call( req );
+        *retkey = reply->hkey;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     TRACE("<- 0x%04x\n", *retkey);
     return ret;
 }
@@ -119,7 +109,7 @@
     SERVER_START_REQ( delete_key )
     {
         req->hkey = hkey;
-        ret = SERVER_CALL();
+        ret = wine_server_call( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -137,102 +127,101 @@
     TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) );
     if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
 
-    SERVER_START_VAR_REQ( delete_key_value, name->Length )
+    SERVER_START_REQ( delete_key_value )
     {
         req->hkey = hkey;
-        memcpy( server_data_ptr(req), name->Buffer, name->Length );
-        ret = SERVER_CALL();
+        wine_server_add_data( req, name->Buffer, name->Length );
+        ret = wine_server_call( req );
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
 
 /******************************************************************************
- *     fill_key_info
+ *     enumerate_key
  *
- * Helper function for NtQueryKey and NtEnumerateKey
+ * Implementation of NtQueryKey and NtEnumerateKey
  */
-static NTSTATUS fill_key_info( KEY_INFORMATION_CLASS info_class, void *info, DWORD length,
-                               DWORD *result_len, const struct enum_key_request *req )
-{
-    WCHAR *name_ptr = server_data_ptr(req);
-    int name_size = *name_ptr++;
-    WCHAR *class_ptr = (WCHAR *)((char *)name_ptr + name_size);
-    int class_size = server_data_size(req) - sizeof(WCHAR) - name_size;
-    int fixed_size;
-    LARGE_INTEGER modif;
+static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS info_class,
+                               void *info, DWORD length, DWORD *result_len )
 
-    RtlSecondsSince1970ToTime( req->modif, (FILETIME *)&modif );
+{
+    NTSTATUS ret;
+    void *data_ptr;
+    size_t fixed_size;
 
     switch(info_class)
     {
-    case KeyBasicInformation:
-        {
-            KEY_BASIC_INFORMATION keyinfo;
-            fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
-            keyinfo.LastWriteTime = modif;
-            keyinfo.TitleIndex = 0;
-            keyinfo.NameLength = name_size;
-            memcpy( info, &keyinfo, min( length, fixed_size ) );
-            class_size = 0;
-        }
-        break;
-    case KeyFullInformation:
-        {
-            KEY_FULL_INFORMATION keyinfo;
-            fixed_size = (char *)keyinfo.Class - (char *)&keyinfo;
-            keyinfo.LastWriteTime = modif;
-            keyinfo.TitleIndex = 0;
-            keyinfo.ClassLength = class_size;
-            keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
-            keyinfo.SubKeys = req->subkeys;
-            keyinfo.MaxNameLen = req->max_subkey;
-            keyinfo.MaxClassLen = req->max_class;
-            keyinfo.Values = req->values;
-            keyinfo.MaxValueNameLen = req->max_value;
-            keyinfo.MaxValueDataLen = req->max_data;
-            memcpy( info, &keyinfo, min( length, fixed_size ) );
-            name_size = 0;
-        }
-        break;
-    case KeyNodeInformation:
-        {
-            KEY_NODE_INFORMATION keyinfo;
-            fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
-            keyinfo.LastWriteTime = modif;
-            keyinfo.TitleIndex = 0;
-            keyinfo.ClassLength = class_size;
-            keyinfo.ClassOffset = fixed_size + name_size;
-            if (!keyinfo.ClassLength || keyinfo.ClassOffset > length) keyinfo.ClassOffset = -1;
-            keyinfo.NameLength = name_size;
-            memcpy( info, &keyinfo, min( length, fixed_size ) );
-        }
-        break;
+    case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break;
+    case KeyFullInformation:  data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break;
+    case KeyNodeInformation:  data_ptr = ((KEY_NODE_INFORMATION *)info)->Name;  break;
     default:
-        FIXME("Information class not implemented\n");
+        FIXME( "Information class %d not implemented\n", info_class );
         return STATUS_INVALID_PARAMETER;
     }
+    fixed_size = (char *)data_ptr - (char *)info;
 
-    *result_len = fixed_size + name_size + class_size;
-    if (length <= fixed_size) return STATUS_BUFFER_OVERFLOW;
-    length -= fixed_size;
-
-    /* copy the name */
-    if (name_size)
+    SERVER_START_REQ( enum_key )
     {
-        memcpy( (char *)info + fixed_size, name_ptr, min(length,name_size) );
-        if (length < name_size) return STATUS_BUFFER_OVERFLOW;
-        length -= name_size;
-    }
+        req->hkey       = handle;
+        req->index      = index;
+        req->info_class = info_class;
+        if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
+        if (!(ret = wine_server_call( req )))
+        {
+            LARGE_INTEGER modif;
 
-    /* copy the class */
-    if (class_size)
-    {
-        memcpy( (char *)info + fixed_size + name_size, class_ptr, min(length,class_size) );
-        if (length < class_size) return STATUS_BUFFER_OVERFLOW;
+            RtlSecondsSince1970ToTime( reply->modif, (FILETIME *)&modif );
+
+            switch(info_class)
+            {
+            case KeyBasicInformation:
+                {
+                    KEY_BASIC_INFORMATION keyinfo;
+                    fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
+                    keyinfo.LastWriteTime = modif;
+                    keyinfo.TitleIndex = 0;
+                    keyinfo.NameLength = reply->namelen;
+                    memcpy( info, &keyinfo, min( length, fixed_size ) );
+                }
+                break;
+            case KeyFullInformation:
+                {
+                    KEY_FULL_INFORMATION keyinfo;
+                    fixed_size = (char *)keyinfo.Class - (char *)&keyinfo;
+                    keyinfo.LastWriteTime = modif;
+                    keyinfo.TitleIndex = 0;
+                    keyinfo.ClassLength = wine_server_reply_size(reply);
+                    keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
+                    keyinfo.SubKeys = reply->subkeys;
+                    keyinfo.MaxNameLen = reply->max_subkey;
+                    keyinfo.MaxClassLen = reply->max_class;
+                    keyinfo.Values = reply->values;
+                    keyinfo.MaxValueNameLen = reply->max_value;
+                    keyinfo.MaxValueDataLen = reply->max_data;
+                    memcpy( info, &keyinfo, min( length, fixed_size ) );
+                }
+                break;
+            case KeyNodeInformation:
+                {
+                    KEY_NODE_INFORMATION keyinfo;
+                    fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
+                    keyinfo.LastWriteTime = modif;
+                    keyinfo.TitleIndex = 0;
+                    keyinfo.ClassLength = max( 0, wine_server_reply_size(reply) - reply->namelen );
+                    keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size + reply->namelen : -1;
+                    keyinfo.NameLength = reply->namelen;
+                    memcpy( info, &keyinfo, min( length, fixed_size ) );
+                }
+                break;
+            }
+            *result_len = fixed_size + reply->total;
+            if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
+        }
     }
-    return STATUS_SUCCESS;
+    SERVER_END_REQ;
+    return ret;
 }
 
 
@@ -247,23 +236,9 @@
 NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class,
                                 void *info, DWORD length, DWORD *result_len )
 {
-    NTSTATUS ret;
-
     /* -1 means query key, so avoid it here */
     if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
-
-    SERVER_START_VAR_REQ( enum_key, REQUEST_MAX_VAR_SIZE )
-    {
-        req->hkey  = handle;
-        req->index = index;
-        req->full  = (info_class == KeyFullInformation);
-        if (!(ret = SERVER_CALL()))
-        {
-            ret = fill_key_info( info_class, info, length, result_len, req );
-        }
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return enumerate_key( handle, index, info_class, info, length, result_len );
 }
 
 
@@ -274,20 +249,7 @@
 NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class,
                             void *info, DWORD length, DWORD *result_len )
 {
-    NTSTATUS ret;
-
-    SERVER_START_VAR_REQ( enum_key, REQUEST_MAX_VAR_SIZE )
-    {
-        req->hkey  = handle;
-        req->index = -1;
-        req->full  = (info_class == KeyFullInformation);
-        if (!(ret = SERVER_CALL()))
-        {
-            ret = fill_key_info( info_class, info, length, result_len, req );
-        }
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return enumerate_key( handle, -1, info_class, info, length, result_len );
 }
 
 
@@ -344,98 +306,39 @@
                                      void *info, DWORD length, DWORD *result_len )
 {
     NTSTATUS ret;
-    UCHAR *data_ptr;
-    WCHAR *name_ptr;
-    int fixed_size = 0, name_len = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
+    void *ptr;
+    size_t fixed_size;
 
     TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle, index, info_class, info, length );
 
     /* compute the length we want to retrieve */
     switch(info_class)
     {
-    case KeyValueBasicInformation:
-        name_ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name;
-        data_ptr = NULL;
-        fixed_size = (char *)name_ptr - (char *)info;
-        break;
-    case KeyValueFullInformation:
-        name_ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name;
-        data_ptr = (UCHAR *)name_ptr;
-        fixed_size = (char *)name_ptr - (char *)info;
-        break;
-    case KeyValuePartialInformation:
-        name_ptr = NULL;
-        data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data;
-        fixed_size = (char *)data_ptr - (char *)info;
-        break;
+    case KeyValueBasicInformation:   ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name; break;
+    case KeyValueFullInformation:    ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name; break;
+    case KeyValuePartialInformation: ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; break;
     default:
         FIXME( "Information class %d not implemented\n", info_class );
         return STATUS_INVALID_PARAMETER;
     }
-    if (length > fixed_size) data_len = length - fixed_size;
+    fixed_size = (char *)ptr - (char *)info;
 
-    do
+    SERVER_START_REQ( enum_key_value )
     {
-        size_t reqlen = data_len + sizeof(WCHAR);
-        if (name_ptr && !offset) reqlen += MAX_PATH*sizeof(WCHAR);
-        reqlen = min( reqlen, REQUEST_MAX_VAR_SIZE );
-
-        SERVER_START_VAR_REQ( enum_key_value, reqlen )
+        req->hkey       = handle;
+        req->index      = index;
+        req->info_class = info_class;
+        if (length > fixed_size) wine_server_set_reply( req, ptr, length - fixed_size );
+        if (!(ret = wine_server_call( req )))
         {
-            req->hkey = handle;
-            req->index = index;
-            req->offset = offset;
-
-            if (!(ret = SERVER_CALL()))
-            {
-                size_t size = server_data_size(req) - sizeof(WCHAR);
-                WCHAR *name = server_data_ptr(req);
-                if (!offset)  /* name is only present on the first request */
-                {
-                    name_len = *name++;
-                    size -= name_len;
-                    if (name_ptr)
-                    {
-                        if (name_len > data_len)  /* overflow */
-                        {
-                            memcpy( name_ptr, name, data_len );
-                            data_len = 0;
-                            ret = STATUS_BUFFER_OVERFLOW;
-                        }
-                        else
-                        {
-                            memcpy( name_ptr, name, name_len );
-                            data_len -= name_len;
-                            if (data_ptr) data_ptr += name_len;
-                        }
-                    }
-                    name += name_len / sizeof(WCHAR);
-                }
-                else name++;  /* skip 0 length */
-
-                if (data_ptr)
-                {
-                    size = min( size, data_len );
-                    memcpy( data_ptr + offset, name, size );
-                    offset += size;
-                    data_len -= size;
-                }
-                type = req->type;
-                total_len = req->len;
-            }
+            copy_key_value_info( info_class, info, length, reply->type, reply->namelen,
+                                 wine_server_reply_size(reply) - reply->namelen );
+            *result_len = fixed_size + reply->total;
+            if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
         }
-        SERVER_END_VAR_REQ;
-        if (ret) return ret;
-    } while (data_len && data_ptr && offset < total_len);
-
-    *result_len = total_len + fixed_size + (name_ptr ? name_len : 0);
-
-    if (data_ptr && offset < total_len) ret = STATUS_BUFFER_OVERFLOW;
-    if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
-
-    copy_key_value_info( info_class, info, length, type, name_len, total_len );
+    }
+    SERVER_END_REQ;
     return ret;
-
 }
 
 
@@ -452,7 +355,7 @@
 {
     NTSTATUS ret;
     UCHAR *data_ptr;
-    int fixed_size = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
+    int fixed_size = 0;
 
     TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
 
@@ -477,45 +380,21 @@
         FIXME( "Information class %d not implemented\n", info_class );
         return STATUS_INVALID_PARAMETER;
     }
-    if (data_ptr && length > fixed_size) data_len = length - fixed_size;
 
-    do
+    SERVER_START_REQ( get_key_value )
     {
-        size_t reqlen = min( data_len, REQUEST_MAX_VAR_SIZE );
-        reqlen = max( reqlen, name->Length + sizeof(WCHAR) );
-
-        SERVER_START_VAR_REQ( get_key_value, reqlen )
+        req->hkey = handle;
+        wine_server_add_data( req, name->Buffer, name->Length );
+        if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
+        if (!(ret = wine_server_call( req )))
         {
-            WCHAR *nameptr = server_data_ptr(req);
-
-            req->hkey = handle;
-            req->offset = offset;
-            *nameptr++ = name->Length;
-            memcpy( nameptr, name->Buffer, name->Length );
-
-            if (!(ret = SERVER_CALL()))
-            {
-                size_t size = min( server_data_size(req), data_len );
-                type = req->type;
-                total_len = req->len;
-                if (size)
-                {
-                    memcpy( data_ptr + offset, server_data_ptr(req), size );
-                    offset += size;
-                    data_len -= size;
-                }
-            }
+            copy_key_value_info( info_class, info, length, reply->type,
+                                 0, wine_server_reply_size(reply) );
+            *result_len = fixed_size + reply->total;
+            if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
         }
-        SERVER_END_VAR_REQ;
-        if (ret) return ret;
-    } while (data_len && offset < total_len);
-
-    *result_len = total_len + fixed_size;
-
-    if (offset < total_len) ret = STATUS_BUFFER_OVERFLOW;
-    if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
-
-    copy_key_value_info( info_class, info, length, type, 0, total_len );
+    }
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -651,36 +530,21 @@
                                ULONG type, const void *data, ULONG count )
 {
     NTSTATUS ret;
-    ULONG namelen, pos;
 
     TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
 
     if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
 
-    namelen = name->Length + sizeof(WCHAR);  /* for storing length */
-    pos = 0;
-
-    do
+    SERVER_START_REQ( set_key_value )
     {
-        ULONG len = count - pos;
-        if (len > REQUEST_MAX_VAR_SIZE - namelen) len = REQUEST_MAX_VAR_SIZE - namelen;
-
-        SERVER_START_VAR_REQ( set_key_value, namelen + len )
-        {
-            WCHAR *name_ptr = server_data_ptr(req);
-
-            req->hkey   = hkey;
-            req->type   = type;
-            req->total  = count;
-            req->offset = pos;
-            *name_ptr++ = name->Length;
-            memcpy( name_ptr, name->Buffer, name->Length );
-            memcpy( (char *)name_ptr + name->Length, (char *)data + pos, len );
-            pos += len;
-            ret = SERVER_CALL();
-        }
-        SERVER_END_VAR_REQ;
-    } while (!ret && pos < count);
+        req->hkey    = hkey;
+        req->type    = type;
+        req->namelen = name->Length;
+        wine_server_add_data( req, name->Buffer, name->Length );
+        wine_server_add_data( req, data, count );
+        ret = wine_server_call( req );
+    }
+    SERVER_END_REQ;
     return ret;
 }
 
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 57a7bd4..37d8b62 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -36,16 +36,16 @@
     if ((MaximumCount <= 0) || (InitialCount > MaximumCount))
         return STATUS_INVALID_PARAMETER;
 
-    SERVER_START_VAR_REQ( create_semaphore, len )
+    SERVER_START_REQ( create_semaphore )
     {
         req->initial = InitialCount;
         req->max     = MaximumCount;
         req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
-        if (len) memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
-        ret = SERVER_CALL();
-        *SemaphoreHandle = req->handle;
+        if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
+        ret = wine_server_call( req );
+        *SemaphoreHandle = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -59,15 +59,15 @@
     DWORD len = attr && attr->ObjectName ? attr->ObjectName->Length : 0;
     NTSTATUS ret;
 
-    SERVER_START_VAR_REQ( open_semaphore, len )
+    SERVER_START_REQ( open_semaphore )
     {
         req->access  = access;
         req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
-        if (len) memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
-        ret = SERVER_CALL();
-        *SemaphoreHandle = req->handle;
+        if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
+        ret = wine_server_call( req );
+        *SemaphoreHandle = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -96,9 +96,9 @@
     {
         req->handle = handle;
         req->count  = count;
-        if (!(ret = SERVER_CALL()))
+        if (!(ret = wine_server_call( req )))
         {
-            if (previous) *previous = req->prev_count;
+            if (previous) *previous = reply->prev_count;
         }
     }
     SERVER_END_REQ;
@@ -123,16 +123,16 @@
     DWORD len = attr && attr->ObjectName ? attr->ObjectName->Length : 0;
     NTSTATUS ret;
 
-    SERVER_START_VAR_REQ( create_event, len )
+    SERVER_START_REQ( create_event )
     {
         req->manual_reset = ManualReset;
         req->initial_state = InitialState;
         req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
-        if (len) memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
-        ret = SERVER_CALL();
-        *EventHandle = req->handle;
+        if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
+        ret = wine_server_call( req );
+        *EventHandle = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -148,15 +148,15 @@
     DWORD len = attr && attr->ObjectName ? attr->ObjectName->Length : 0;
     NTSTATUS ret;
 
-    SERVER_START_VAR_REQ( open_event, len )
+    SERVER_START_REQ( open_event )
     {
         req->access  = DesiredAccess;
         req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
-        if (len) memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
-        ret = SERVER_CALL();
-        *EventHandle = req->handle;
+        if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
+        ret = wine_server_call( req );
+        *EventHandle = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -175,7 +175,7 @@
     {
         req->handle = handle;
         req->op     = SET_EVENT;
-        ret = SERVER_CALL();
+        ret = wine_server_call( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -195,7 +195,7 @@
     {
         req->handle = handle;
         req->op     = RESET_EVENT;
-        ret = SERVER_CALL();
+        ret = wine_server_call( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -226,7 +226,7 @@
     {
         req->handle = handle;
         req->op     = PULSE_EVENT;
-        ret = SERVER_CALL();
+        ret = wine_server_call( req );
     }
     SERVER_END_REQ;
     return ret;
diff --git a/dlls/user/message.c b/dlls/user/message.c
index e5e38a2..c22285e 100644
--- a/dlls/user/message.c
+++ b/dlls/user/message.c
@@ -200,26 +200,6 @@
 
 #undef SET
 
-/* compute the total size of the packed data */
-inline static size_t get_data_total_size( const struct packed_message *data )
-{
-    int i;
-    size_t total = 0;
-    for (i = 0; i < data->count; i++) total += data->size[i];
-    return total;
-}
-
-/* copy all the data of a packed message into a single dest buffer */
-inline static void copy_all_data( void *dest, const struct packed_message *data )
-{
-    int i;
-    for (i = 0; i < data->count; i++)
-    {
-        memcpy( dest, data->data[i], data->size[i] );
-        dest = (char *)dest + data->size[i];
-    }
-}
-
 /* add a data field to a packed message */
 inline static void push_data( struct packed_message *data, const void *ptr, size_t size )
 {
@@ -1032,7 +1012,7 @@
 static void reply_message( struct received_message_info *info, LRESULT result, BOOL remove )
 {
     struct packed_message data;
-    int replied = info->flags & ISMEX_REPLIED;
+    int i, replied = info->flags & ISMEX_REPLIED;
 
     if (info->flags & ISMEX_NOTIFY) return;  /* notify messages don't get replies */
     if (!remove && replied) return;  /* replied already */
@@ -1044,34 +1024,14 @@
     {
         pack_reply( info->msg.hwnd, info->msg.message, info->msg.wParam,
                     info->msg.lParam, result, &data );
-        if (data.count)
-        {
-            size_t total = get_data_total_size( &data );
-
-            if (total > REQUEST_MAX_VAR_SIZE)
-            {
-                FIXME( "inter-process msg data size %d not supported yet, expect trouble\n",
-                       total );
-                total = REQUEST_MAX_VAR_SIZE;
-            }
-
-            SERVER_START_VAR_REQ( reply_message, total )
-            {
-                req->result = result;
-                req->remove = remove;
-                copy_all_data( server_data_ptr(req), &data );
-                SERVER_CALL();
-            }
-            SERVER_END_VAR_REQ;
-            return;
-        }
     }
 
     SERVER_START_REQ( reply_message )
     {
         req->result = result;
         req->remove = remove;
-        SERVER_CALL();
+        for (i = 0; i < data.count; i++) wine_server_add_data( req, data.data[i], data.size[i] );
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 }
@@ -1170,7 +1130,6 @@
  */
 BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
 {
-    BOOL ret;
     LRESULT result;
     ULONG_PTR extra_info = 0;
     MESSAGEQUEUE *queue = QUEUE_Current();
@@ -1180,41 +1139,44 @@
 
     for (;;)
     {
+        NTSTATUS res;
         void *buffer = NULL;
-        size_t size = 0;
+        size_t size = 0, buffer_size = 0;
 
-        SERVER_START_VAR_REQ( get_message, REQUEST_MAX_VAR_SIZE )
+        do  /* loop while buffer is too small */
         {
-            req->flags     = flags;
-            req->get_win   = hwnd;
-            req->get_first = first;
-            req->get_last  = last;
-            if ((ret = !SERVER_CALL()))
+            if (buffer_size && !(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_size )))
+                return FALSE;
+            SERVER_START_REQ( get_message )
             {
-                info.type        = req->type;
-                info.msg.hwnd    = req->win;
-                info.msg.message = req->msg;
-                info.msg.wParam  = req->wparam;
-                info.msg.lParam  = req->lparam;
-                info.msg.time    = req->time;
-                info.msg.pt.x    = req->x;
-                info.msg.pt.y    = req->y;
-                extra_info       = req->info;
-
-                if ((size = server_data_size(req)))
+                req->flags     = flags;
+                req->get_win   = hwnd;
+                req->get_first = first;
+                req->get_last  = last;
+                if (buffer_size) wine_server_set_reply( req, buffer, buffer_size );
+                if (!(res = wine_server_call( req )))
                 {
-                    if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
-                    {
-                        ERR("out of memory for message data\n");
-                        ret = FALSE;
-                    }
-                    else memcpy( buffer, server_data_ptr(req), size );
+                    size = wine_server_reply_size( reply );
+                    info.type        = reply->type;
+                    info.msg.hwnd    = reply->win;
+                    info.msg.message = reply->msg;
+                    info.msg.wParam  = reply->wparam;
+                    info.msg.lParam  = reply->lparam;
+                    info.msg.time    = reply->time;
+                    info.msg.pt.x    = reply->x;
+                    info.msg.pt.y    = reply->y;
+                    extra_info       = reply->info;
+                }
+                else
+                {
+                    if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
+                    buffer_size = reply->total;
                 }
             }
-        }
-        SERVER_END_VAR_REQ;
+            SERVER_END_REQ;
+        } while (res == STATUS_BUFFER_OVERFLOW);
 
-        if (!ret) return FALSE;  /* no message available */
+        if (res) return FALSE;
 
         TRACE( "got type %d msg %x hwnd %x wp %x lp %lx\n",
                info.type, info.msg.message, info.msg.hwnd, info.msg.wParam, info.msg.lParam );
@@ -1241,26 +1203,27 @@
                      info.msg.wParam, info.msg.lParam, size );
                 /* ignore it */
                 reply_message( &info, 0, TRUE );
-                continue;
+                goto next;
             }
             break;
         case MSG_HARDWARE_RAW:
             if (!MSG_process_raw_hardware_message( &info.msg, extra_info,
                                                    hwnd, first, last, flags & GET_MSG_REMOVE ))
-                continue;
+                goto next;
             /* fall through */
         case MSG_HARDWARE_COOKED:
             if (!MSG_process_cooked_hardware_message( &info.msg, extra_info,
                                                       flags & GET_MSG_REMOVE ))
             {
                 flags |= GET_MSG_REMOVE_LAST;
-                continue;
+                goto next;
             }
             queue->GetMessagePosVal = MAKELONG( info.msg.pt.x, info.msg.pt.y );
             /* fall through */
         case MSG_POSTED:
             queue->GetMessageExtraInfoVal = extra_info;
             *msg = info.msg;
+            if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
             return TRUE;
         }
 
@@ -1271,7 +1234,7 @@
                                    info.msg.lParam, (info.type != MSG_ASCII) );
         reply_message( &info, result, TRUE );
         queue->receive_info = old_info;
-
+    next:
         if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
     }
 }
@@ -1298,10 +1261,10 @@
             req->wake_mask    = (flags & SMTO_BLOCK) ? 0 : QS_SENDMESSAGE;
             req->changed_mask = QS_SMRESULT | req->wake_mask;
             req->skip_wait    = 1;
-            if (!SERVER_CALL())
+            if (!wine_server_call( req ))
             {
-                wake_bits    = req->wake_bits;
-                changed_bits = req->changed_bits;
+                wake_bits    = reply->wake_bits;
+                changed_bits = reply->changed_bits;
             }
         }
         SERVER_END_REQ;
@@ -1338,8 +1301,9 @@
 static BOOL put_message_in_queue( DWORD dest_tid, const struct send_message_info *info,
                                   size_t *reply_size )
 {
+    struct packed_message data;
     unsigned int res;
-    int timeout = -1;
+    int i, timeout = -1;
 
     if (info->type != MSG_NOTIFY &&
         info->type != MSG_CALLBACK &&
@@ -1347,47 +1311,17 @@
         info->timeout != INFINITE)
         timeout = info->timeout;
 
+    data.count = 0;
     if (info->type == MSG_OTHER_PROCESS)
     {
-        struct packed_message data;
         *reply_size = pack_message( info->hwnd, info->msg, info->wparam, info->lparam, &data );
-
         if (data.count == -1)
         {
             WARN( "cannot pack message %x\n", info->msg );
             return FALSE;
         }
-
-        if (data.size[0]) /* need to send extra data along with the message */
-        {
-            size_t total = get_data_total_size( &data );
-
-            if (total > REQUEST_MAX_VAR_SIZE)
-            {
-                FIXME( "inter-process msg data size %d not supported yet, expect trouble\n",
-                       total );
-                total = REQUEST_MAX_VAR_SIZE;
-            }
-
-            SERVER_START_VAR_REQ( send_message, total )
-            {
-                req->id      = (void *)dest_tid;
-                req->type    = MSG_OTHER_PROCESS;
-                req->win     = info->hwnd;
-                req->msg     = info->msg;
-                req->wparam  = info->wparam;
-                req->lparam  = info->lparam;
-                req->time    = GetCurrentTime();
-                req->timeout = timeout;
-                copy_all_data( server_data_ptr(req), &data );
-                res = SERVER_CALL();
-            }
-            SERVER_END_VAR_REQ;
-            goto done;
-        }
     }
 
-    /* no extra data, or not inter-process message */
     SERVER_START_REQ( send_message )
     {
         req->id      = (void *)dest_tid;
@@ -1398,19 +1332,17 @@
         req->lparam  = info->lparam;
         req->time    = GetCurrentTime();
         req->timeout = timeout;
-        res = SERVER_CALL();
+        for (i = 0; i < data.count; i++) wine_server_add_data( req, data.data[i], data.size[i] );
+        if ((res = wine_server_call( req )))
+        {
+            if (res == STATUS_INVALID_PARAMETER)
+                /* FIXME: find a STATUS_ value for this one */
+                SetLastError( ERROR_INVALID_THREAD_ID );
+            else
+                SetLastError( RtlNtStatusToDosError(res) );
+        }
     }
     SERVER_END_REQ;
-
- done:
-    if (res)
-    {
-        if (res == STATUS_INVALID_PARAMETER)
-            /* FIXME: find a STATUS_ value for this one */
-            SetLastError( ERROR_INVALID_THREAD_ID );
-        else
-            SetLastError( RtlNtStatusToDosError(res) );
-    }
     return !res;
 }
 
@@ -1424,35 +1356,28 @@
                                size_t reply_size, LRESULT *result )
 {
     NTSTATUS status;
+    void *reply_data = NULL;
 
     if (reply_size)
     {
-        if (reply_size > REQUEST_MAX_VAR_SIZE)
+        if (!(reply_data = HeapAlloc( GetProcessHeap(), 0, reply_size )))
         {
-            WARN( "reply_size %d too large, reply may be truncated\n", reply_size );
-            reply_size = REQUEST_MAX_VAR_SIZE;
+            WARN( "no memory for reply %d bytes, will be truncated\n", reply_size );
+            reply_size = 0;
         }
-        SERVER_START_VAR_REQ( get_message_reply, reply_size )
-        {
-            req->cancel = 1;
-            if (!(status = SERVER_CALL()))
-            {
-                *result = req->result;
-                unpack_reply( info->hwnd, info->msg, info->wparam, info->lparam,
-                              server_data_ptr(req), server_data_size(req) );
-            }
-        }
-        SERVER_END_VAR_REQ;
     }
-    else
+    SERVER_START_REQ( get_message_reply )
     {
-        SERVER_START_REQ( get_message_reply )
-        {
-            req->cancel = 1;
-            if (!(status = SERVER_CALL())) *result = req->result;
-        }
-        SERVER_END_REQ;
+        req->cancel = 1;
+        if (reply_size) wine_server_set_reply( req, reply_data, reply_size );
+        if (!(status = wine_server_call( req ))) *result = reply->result;
+        reply_size = wine_server_reply_size( reply );
     }
+    SERVER_END_REQ;
+    if (!status && reply_size)
+        unpack_reply( info->hwnd, info->msg, info->wparam, info->lparam, reply_data, reply_size );
+
+    if (reply_data) HeapFree( GetProcessHeap(), 0, reply_data );
 
     TRACE( "hwnd %x msg %x (%s) wp %x lp %lx got reply %lx (err=%ld)\n",
            info->hwnd, info->msg, SPY_GetMsgName(info->msg, info->hwnd), info->wparam,
@@ -1955,10 +1880,10 @@
             req->wake_mask    = QS_SENDMESSAGE;
             req->changed_mask = mask;
             req->skip_wait    = 1;
-            if (!SERVER_CALL())
+            if (!wine_server_call( req ))
             {
-                wake_bits    = req->wake_bits;
-                changed_bits = req->changed_bits;
+                wake_bits    = reply->wake_bits;
+                changed_bits = reply->changed_bits;
             }
         }
         SERVER_END_REQ;
diff --git a/dlls/user/property.c b/dlls/user/property.c
index a3d32ec..be2d8f6 100644
--- a/dlls/user/property.c
+++ b/dlls/user/property.c
@@ -24,24 +24,30 @@
  */
 static property_data_t *get_properties( HWND hwnd, int *count )
 {
-    property_data_t *ret = NULL;
+    property_data_t *data;
+    int total = 32;
 
-    SERVER_START_VAR_REQ( get_window_properties, REQUEST_MAX_VAR_SIZE )
+    while (total)
     {
-        req->window = hwnd;
-        if (!SERVER_CALL())
+        int res = 0;
+        if (!(data = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*data) ))) break;
+        *count = 0;
+        SERVER_START_REQ( get_window_properties )
         {
-            size_t size = server_data_size(req);
-            if (size)
-            {
-                property_data_t *data = server_data_ptr(req);
-                if ((ret = HeapAlloc( GetProcessHeap(), 0, size ))) memcpy( ret, data, size );
-                *count = size / sizeof(*data);
-            }
+            req->window = hwnd;
+            wine_server_add_data( req, data, total * sizeof(*data) );
+            if (!wine_server_call( req )) res = reply->total;
         }
+        SERVER_END_REQ;
+        if (res && res <= total)
+        {
+            *count = res;
+            return data;
+        }
+        HeapFree( GetProcessHeap(), 0, data );
+        total = res;  /* restart with larger buffer */
     }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return NULL;
 }
 
 
@@ -102,7 +108,7 @@
     {
         req->window = hwnd;
         req->atom = atom;
-        if (!SERVER_CALL_ERR()) ret = req->handle;
+        if (!wine_server_call_err( req )) ret = reply->handle;
     }
     SERVER_END_REQ;
     return ret;
@@ -124,7 +130,7 @@
     {
         req->window = hwnd;
         req->atom = atom;
-        if (!SERVER_CALL_ERR()) ret = req->handle;
+        if (!wine_server_call_err( req )) ret = reply->handle;
     }
     SERVER_END_REQ;
     return ret;
@@ -148,7 +154,7 @@
         req->atom   = atom;
         req->string = (HIWORD(str) != 0);
         req->handle = handle;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
 
@@ -174,7 +180,7 @@
         req->atom   = atom;
         req->string = (HIWORD(str) != 0);
         req->handle = handle;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
 
@@ -217,7 +223,7 @@
     {
         req->window = hwnd;
         req->atom   = atom;
-        if (!SERVER_CALL_ERR()) ret = req->handle;
+        if (!wine_server_call_err( req )) ret = reply->handle;
     }
     SERVER_END_REQ;
 
diff --git a/dlls/winsock/socket.c b/dlls/winsock/socket.c
index 12b761c..78b65c2 100644
--- a/dlls/winsock/socket.c
+++ b/dlls/winsock/socket.c
@@ -233,7 +233,7 @@
         req->mask   = event;
         req->sstate = sstate;
         req->cstate = cstate;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 }
@@ -247,8 +247,8 @@
         req->service = FALSE;
         req->s_event = 0;
         req->c_event = 0;
-        SERVER_CALL();
-        ret = (req->state & FD_WINE_NONBLOCKING) == 0;
+        wine_server_call( req );
+        ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
     }
     SERVER_END_REQ;
     return ret;
@@ -263,8 +263,8 @@
         req->service = FALSE;
         req->s_event = 0;
         req->c_event = 0;
-        SERVER_CALL();
-        ret = req->mask;
+        wine_server_call( req );
+        ret = reply->mask;
     }
     SERVER_END_REQ;
     return ret;
@@ -279,18 +279,19 @@
 
 static int _get_sock_error(SOCKET s, unsigned int bit)
 {
-    int ret;
-    SERVER_START_VAR_REQ( get_socket_event, FD_MAX_EVENTS*sizeof(int) )
+    int events[FD_MAX_EVENTS];
+
+    SERVER_START_REQ( get_socket_event )
     {
         req->handle  = s;
         req->service = FALSE;
         req->s_event = 0;
         req->c_event = 0;
-        SERVER_CALL();
-        ret = *((int *)server_data_ptr(req) + bit);
+        wine_server_set_reply( req, events, sizeof(events) );
+        wine_server_call( req );
     }
-    SERVER_END_VAR_REQ;
-    return ret;
+    SERVER_END_REQ;
+    return events[bit];
 }
 
 static void WINSOCK_DeleteIData(void)
@@ -900,8 +901,8 @@
             req->lhandle = s;
             req->access  = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
             req->inherit = TRUE;
-            set_error( SERVER_CALL() );
-            as = (SOCKET)req->handle;
+            set_error( wine_server_call( req ) );
+            as = (SOCKET)reply->handle;
         }
         SERVER_END_REQ;
 	if (as)
@@ -2318,8 +2319,8 @@
         req->protocol = protocol;
         req->access   = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
         req->inherit  = TRUE;
-        set_error( SERVER_CALL() );
-        ret = (SOCKET)req->handle;
+        set_error( wine_server_call( req ) );
+        ret = (SOCKET)reply->handle;
     }
     SERVER_END_REQ;
     if (ret)
@@ -2718,19 +2719,16 @@
 
     TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
 
-    SERVER_START_VAR_REQ( get_socket_event, sizeof(lpEvent->iErrorCode) )
+    SERVER_START_REQ( get_socket_event )
     {
         req->handle  = s;
         req->service = TRUE;
         req->s_event = 0;
         req->c_event = hEvent;
-        if (!(ret = SERVER_CALL()))
-        {
-            lpEvent->lNetworkEvents = req->pmask & req->mask;
-            memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
-        }
+        wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
+        if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     if (!ret) return 0;
     SetLastError(WSAEINVAL);
     return SOCKET_ERROR;
@@ -2750,7 +2748,7 @@
         req->handle = s;
         req->mask   = lEvent;
         req->event  = hEvent;
-        ret = SERVER_CALL();
+        ret = wine_server_call( req );
     }
     SERVER_END_REQ;
     if (!ret) return 0;
@@ -2769,17 +2767,17 @@
 
     TRACE("socket %08x, event %08x\n", info->sock, info->event);
     SetLastError(0);
-    SERVER_START_VAR_REQ( get_socket_event, sizeof(errors) )
+    SERVER_START_REQ( get_socket_event )
     {
         req->handle  = info->sock;
         req->service = TRUE;
         req->s_event = info->event; /* <== avoid race conditions */
         req->c_event = info->event;
-        set_error( SERVER_CALL() );
-        pmask = req->pmask;
-        memcpy( errors, server_data_ptr(req), server_data_size(req) );
+        wine_server_set_reply( req, errors, sizeof(errors) );
+        set_error( wine_server_call(req) );
+        pmask = reply->pmask;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
     {
 	/* orphaned event (socket closed or something) */
diff --git a/files/change.c b/files/change.c
index 774a3de..1137cbb 100644
--- a/files/change.c
+++ b/files/change.c
@@ -36,7 +36,7 @@
     {
         req->subtree = bWatchSubtree;
         req->filter  = dwNotifyFilter;
-        if (!SERVER_CALL_ERR()) ret = req->handle;
+        if (!wine_server_call_err( req )) ret = reply->handle;
     }
     SERVER_END_REQ;
     return ret;
diff --git a/files/dos_fs.c b/files/dos_fs.c
index 497cc1b..d62cc92 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -690,11 +690,11 @@
     SERVER_START_REQ( get_file_info )
     {
         req->handle = hFile;
-        if (!SERVER_CALL() && (req->type == FILE_TYPE_UNKNOWN))
+        if (!wine_server_call( req ) && (reply->type == FILE_TYPE_UNKNOWN))
         {
-            if ((req->attr >= 0) &&
-                (req->attr < sizeof(DOSFS_Devices)/sizeof(DOSFS_Devices[0])))
-                ret = &DOSFS_Devices[req->attr];
+            if ((reply->attr >= 0) &&
+                (reply->attr < sizeof(DOSFS_Devices)/sizeof(DOSFS_Devices[0])))
+                ret = &DOSFS_Devices[reply->attr];
         }
     }
     SERVER_END_REQ;
@@ -709,7 +709,6 @@
 {
     HANDLE ret;
     char devname[40];
-    size_t len;
 
     TRACE_(file)("%s %lx %lx\n", name, access, attributes);
 
@@ -719,19 +718,18 @@
 
     TRACE("opening %s as %s\n", devname, name);
 
-    len = strlen(devname);
-    SERVER_START_VAR_REQ( create_serial, len )
+    SERVER_START_REQ( create_serial )
     {
         req->access  = access;
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
         req->attributes = attributes;
         req->sharing = FILE_SHARE_READ|FILE_SHARE_WRITE;
-        memcpy( server_data_ptr(req), devname, len );
+        wine_server_add_data( req, devname, strlen(devname) );
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
 
     if(!ret)
         ERR("Couldn't open device '%s' ! (check permissions)\n",devname);
diff --git a/files/file.c b/files/file.c
index 42f69e7..3ceb98e 100644
--- a/files/file.c
+++ b/files/file.c
@@ -193,8 +193,8 @@
         req->access  = access;
         req->inherit = inherit;
         req->fd      = fd;
-        SERVER_CALL();
-        ret = req->handle;
+        wine_server_call( req );
+        ret = reply->handle;
     }
     SERVER_END_REQ;
     return ret;
@@ -217,11 +217,11 @@
         {
             req->handle = handle;
             req->access = access;
-            if (!(ret = SERVER_CALL_ERR()))
+            if (!(ret = wine_server_call_err( req )))
             {
-                fd = req->fd;
+                fd = reply->fd;
             }
-	    if (type) *type = req->type;
+            if (type) *type = reply->type;
         }
         SERVER_END_REQ;
         if (ret) return -1;
@@ -267,8 +267,8 @@
 	req->share   = sharing;
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
     SERVER_END_REQ;
     return ret;
@@ -286,52 +286,44 @@
                         DWORD attributes, HANDLE template, BOOL fail_read_only,
                         UINT drive_type )
 {
-    DWORD err;
+    unsigned int err;
     HANDLE ret;
-    size_t len = strlen(filename);
 
-    if (len > REQUEST_MAX_VAR_SIZE)
+    for (;;)
     {
-        FIXME("filename '%s' too long\n", filename );
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return 0;
-    }
-
- restart:
-    SERVER_START_VAR_REQ( create_file, len )
-    {
-        req->access     = access;
-        req->inherit    = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        req->sharing    = sharing;
-        req->create     = creation;
-        req->attrs      = attributes;
-        req->drive_type = drive_type;
-        memcpy( server_data_ptr(req), filename, len );
-        SetLastError(0);
-        err = SERVER_CALL();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-
-    /* If write access failed, retry without GENERIC_WRITE */
-
-    if (!ret && !fail_read_only && (access & GENERIC_WRITE))
-    {
-	if ((err == STATUS_MEDIA_WRITE_PROTECTED) || (err == STATUS_ACCESS_DENIED))
+        SERVER_START_REQ( create_file )
         {
-	    TRACE("Write access failed for file '%s', trying without "
-		  "write access\n", filename);
-            access &= ~GENERIC_WRITE;
-            goto restart;
+            req->access     = access;
+            req->inherit    = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+            req->sharing    = sharing;
+            req->create     = creation;
+            req->attrs      = attributes;
+            req->drive_type = drive_type;
+            wine_server_add_data( req, filename, strlen(filename) );
+            SetLastError(0);
+            err = wine_server_call( req );
+            ret = reply->handle;
         }
+        SERVER_END_REQ;
+
+        /* If write access failed, retry without GENERIC_WRITE */
+
+        if (!ret && !fail_read_only && (access & GENERIC_WRITE))
+        {
+            if ((err == STATUS_MEDIA_WRITE_PROTECTED) || (err == STATUS_ACCESS_DENIED))
+            {
+                TRACE("Write access failed for file '%s', trying without "
+                      "write access\n", filename);
+                access &= ~GENERIC_WRITE;
+                continue;
+            }
+        }
+
+        if (err) SetLastError( RtlNtStatusToDosError(err) );
+
+        if (!ret) WARN("Unable to create file '%s' (GLE %ld)\n", filename, GetLastError());
+        return ret;
     }
-
-    if (err) SetLastError( RtlNtStatusToDosError(err) );
-
-    if (!ret)
-        WARN("Unable to create file '%s' (GLE %ld)\n", filename, GetLastError());
-
-    return ret;
 }
 
 
@@ -350,8 +342,8 @@
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
         req->id      = client_id;
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
     SERVER_END_REQ;
     return ret;
@@ -359,26 +351,24 @@
 
 static HANDLE FILE_OpenPipe(LPCSTR name, DWORD access)
 {
+    WCHAR buffer[MAX_PATH];
     HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
+    DWORD len = 0;
 
-    TRACE("name %s access %lx\n",name,access);
-
-    if (len >= MAX_PATH)
+    if (name && !(len = MultiByteToWideChar( CP_ACP, 0, name, strlen(name), buffer, MAX_PATH )))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_named_pipe, len * sizeof(WCHAR) )
+    SERVER_START_REQ( open_named_pipe )
     {
         req->access = access;
-
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     TRACE("Returned %d\n",ret);
     return ret;
 }
@@ -610,32 +600,31 @@
     SERVER_START_REQ( get_file_info )
     {
         req->handle = hFile;
-        if ((ret = !SERVER_CALL_ERR()))
+        if ((ret = !wine_server_call_err( req )))
         {
-	    /* FIXME: which file types are supported ?
-	     * Serial ports (FILE_TYPE_CHAR) are not,
-	     * and MSDN also says that pipes are not supported.
-	     * FILE_TYPE_REMOTE seems to be supported according to
-	     * MSDN q234741.txt */
-	    if ((req->type == FILE_TYPE_DISK)
-	    ||  (req->type == FILE_TYPE_REMOTE))
-	    {
-                RtlSecondsSince1970ToTime( req->write_time, &info->ftCreationTime );
-                RtlSecondsSince1970ToTime( req->write_time, &info->ftLastWriteTime );
-                RtlSecondsSince1970ToTime( req->access_time, &info->ftLastAccessTime );
-                info->dwFileAttributes     = req->attr;
-                info->dwVolumeSerialNumber = req->serial;
-                info->nFileSizeHigh        = req->size_high;
-                info->nFileSizeLow         = req->size_low;
-                info->nNumberOfLinks       = req->links;
-                info->nFileIndexHigh       = req->index_high;
-                info->nFileIndexLow        = req->index_low;
-	    }
-	    else
-	    {
-		SetLastError(ERROR_NOT_SUPPORTED);
-		ret = 0;
-	    }
+            /* FIXME: which file types are supported ?
+             * Serial ports (FILE_TYPE_CHAR) are not,
+             * and MSDN also says that pipes are not supported.
+             * FILE_TYPE_REMOTE seems to be supported according to
+             * MSDN q234741.txt */
+            if ((reply->type == FILE_TYPE_DISK) ||  (reply->type == FILE_TYPE_REMOTE))
+            {
+                RtlSecondsSince1970ToTime( reply->write_time, &info->ftCreationTime );
+                RtlSecondsSince1970ToTime( reply->write_time, &info->ftLastWriteTime );
+                RtlSecondsSince1970ToTime( reply->access_time, &info->ftLastAccessTime );
+                info->dwFileAttributes     = reply->attr;
+                info->dwVolumeSerialNumber = reply->serial;
+                info->nFileSizeHigh        = reply->size_high;
+                info->nFileSizeLow         = reply->size_low;
+                info->nNumberOfLinks       = reply->links;
+                info->nFileIndexHigh       = reply->index_high;
+                info->nFileIndexLow        = reply->index_low;
+            }
+            else
+            {
+                SetLastError(ERROR_NOT_SUPPORTED);
+                ret = 0;
+            }
         }
     }
     SERVER_END_REQ;
@@ -1354,9 +1343,9 @@
         req->count = txcount;
         req->type = type;
         req->file_handle = hFile;
-        ret = SERVER_CALL();
+        ret = wine_server_call( req );
         if(timeout)
-            *timeout = req->timeout;
+            *timeout = reply->timeout;
     }
     SERVER_END_REQ;
     return !ret;
@@ -1785,10 +1774,10 @@
         /* FIXME: assumes 1:1 mapping between Windows and Unix seek constants */
         req->whence = method;
         SetLastError( 0 );
-        if (!SERVER_CALL_ERR())
+        if (!wine_server_call_err( req ))
         {
-            ret = req->new_low;
-            if (highword) *highword = req->new_high;
+            ret = reply->new_low;
+            if (highword) *highword = reply->new_high;
         }
     }
     SERVER_END_REQ;
@@ -1940,7 +1929,7 @@
     SERVER_START_REQ( flush_file )
     {
         req->handle = hFile;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -1956,7 +1945,7 @@
     SERVER_START_REQ( truncate_file )
     {
         req->handle = hFile;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -2029,7 +2018,7 @@
     SERVER_START_REQ( get_file_info )
     {
         req->handle = hFile;
-        if (!SERVER_CALL_ERR()) ret = req->type;
+        if (!wine_server_call_err( req )) ret = reply->type;
     }
     SERVER_END_REQ;
     return ret;
@@ -2350,7 +2339,7 @@
             RtlTimeToSecondsSince1970( lpLastWriteTime, (DWORD *)&req->write_time );
         else
             req->write_time = 0; /* FIXME */
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -2371,7 +2360,7 @@
         req->offset_high = dwFileOffsetHigh;
         req->count_low   = nNumberOfBytesToLockLow;
         req->count_high  = nNumberOfBytesToLockHigh;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -2422,7 +2411,7 @@
         req->offset_high = dwFileOffsetHigh;
         req->count_low   = nNumberOfBytesToUnlockLow;
         req->count_high  = nNumberOfBytesToUnlockHigh;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
diff --git a/include/thread.h b/include/thread.h
index 7a15948..2107056 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -90,9 +90,7 @@
 
     /* The following are Wine-specific fields (NT: GDI stuff) */
     DWORD        cleanup;        /* --3 1fc Cleanup service handle */
-    void        *buffer;         /* --3 200 Buffer shared with server */
-    unsigned int buffer_pos;     /* --3 204 Buffer current position */
-    unsigned int buffer_size;    /* --3 208 Buffer size */
+    DWORD        unused[3];      /* --3 200 Was server buffer */
     int          request_fd;     /* --3 20c fd for sending server requests */
     int          reply_fd;       /* --3 210 fd for receiving server replies */
     int          wait_fd[2];     /* --3 214 fd for sleeping server requests */
diff --git a/include/winbase.h b/include/winbase.h
index f880122..9355baf 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -1609,7 +1609,7 @@
 BOOL      WINAPI WritePrivateProfileStructA(LPCSTR,LPCSTR,LPVOID,UINT,LPCSTR);
 BOOL      WINAPI WritePrivateProfileStructW(LPCWSTR,LPCWSTR,LPVOID,UINT,LPCWSTR);
 #define     WritePrivateProfileStruct WINELIB_NAME_AW(WritePrivateProfileStruct)
-BOOL        WINAPI WriteProcessMemory(HANDLE, LPVOID, LPVOID, DWORD, LPDWORD);
+BOOL        WINAPI WriteProcessMemory(HANDLE,LPVOID,LPCVOID,DWORD,LPDWORD);
 BOOL        WINAPI WriteProfileStringA(LPCSTR,LPCSTR,LPCSTR);
 BOOL        WINAPI WriteProfileStringW(LPCWSTR,LPCWSTR,LPCWSTR);
 #define     WriteProfileString WINELIB_NAME_AW(WriteProfileString)
diff --git a/include/wincon.h b/include/wincon.h
index 233acda..e98b2c1 100644
--- a/include/wincon.h
+++ b/include/wincon.h
@@ -177,10 +177,8 @@
                                          LPVOID lpScreenBufferData);
 BOOL WINAPI   FillConsoleOutputAttribute( HANDLE hConsoleOutput, WORD wAttribute, DWORD nLength,
                                           COORD dwCoord, LPDWORD lpNumAttrsWritten);
-BOOL WINAPI   FillConsoleOutputCharacterA( HANDLE hConsoleOutput, BYTE cCharacter, DWORD nLength,
-                                           COORD dwCoord, LPDWORD lpNumCharsWritten);
-BOOL WINAPI   FillConsoleOutputCharacterW( HANDLE hConsoleOutput, WCHAR cCharacter, DWORD nLength,
-                                           COORD dwCoord, LPDWORD lpNumCharsWritten);
+BOOL WINAPI   FillConsoleOutputCharacterA(HANDLE,CHAR,DWORD,COORD,LPDWORD);
+BOOL WINAPI   FillConsoleOutputCharacterW(HANDLE,WCHAR,DWORD,COORD,LPDWORD);
 #define       FillConsoleOutputCharacter WINELIB_NAME_AW(FillConsoleOutputCharacter)
 BOOL WINAPI   FlushConsoleInputBuffer( HANDLE handle);
 BOOL WINAPI   FreeConsole(VOID);
@@ -242,13 +240,11 @@
 BOOL WINAPI   WriteConsoleA(HANDLE,CONST VOID *,DWORD,LPDWORD,LPVOID);
 BOOL WINAPI   WriteConsoleW(HANDLE, CONST VOID *lpBuffer, DWORD,LPDWORD,LPVOID);
 #define       WriteConsole WINELIB_NAME_AW(WriteConsole)
-BOOL WINAPI   WriteConsoleInputA( HANDLE handle, INPUT_RECORD *buffer, DWORD, LPDWORD );
-BOOL WINAPI   WriteConsoleInputW( HANDLE handle, INPUT_RECORD *buffer, DWORD, LPDWORD );
+BOOL WINAPI   WriteConsoleInputA(HANDLE,const INPUT_RECORD *,DWORD,LPDWORD);
+BOOL WINAPI   WriteConsoleInputW(HANDLE,const INPUT_RECORD *,DWORD,LPDWORD);
 #define       WriteConsoleInput WINELIB_NAME_AW(WriteConsoleInput)
-BOOL WINAPI   WriteConsoleOutputA( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD dwBufferSize,
-                                   COORD dwBufferCoord, LPSMALL_RECT lpWriteRegion);
-BOOL WINAPI   WriteConsoleOutputW( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD dwBufferSize,
-                                   COORD dwBufferCoord, LPSMALL_RECT lpWriteRegion);
+BOOL WINAPI   WriteConsoleOutputA(HANDLE,const CHAR_INFO*,COORD,COORD,LPSMALL_RECT);
+BOOL WINAPI   WriteConsoleOutputW(HANDLE,const CHAR_INFO*,COORD,COORD,LPSMALL_RECT);
 #define       WriteConsoleOutput WINELIB_NAME_AW(WriteConsoleOutput)
 BOOL WINAPI   WriteConsoleOutputAttribute(HANDLE,CONST WORD *,DWORD,COORD,LPDWORD);
 BOOL WINAPI   WriteConsoleOutputCharacterA(HANDLE,LPCSTR,DWORD,COORD,LPDWORD);
diff --git a/include/wine/server.h b/include/wine/server.h
index 6bc18c5..b6d8cdb 100644
--- a/include/wine/server.h
+++ b/include/wine/server.h
@@ -14,83 +14,90 @@
 
 /* client communication functions */
 
-extern unsigned int wine_server_call( union generic_request *req, size_t size );
-extern void server_protocol_error( const char *err, ... ) WINE_NORETURN;
-extern void server_protocol_perror( const char *err ) WINE_NORETURN;
-extern void wine_server_alloc_req( union generic_request *req, size_t size );
+struct __server_iovec
+{
+    const void  *ptr;
+    unsigned int size;
+};
+
+#define __SERVER_MAX_DATA 4
+
+struct __server_request_info
+{
+    union
+    {
+        union generic_request req;    /* request structure */
+        union generic_reply   reply;  /* reply structure */
+    } u;
+    size_t                size;       /* size of request structure */
+    unsigned int          data_count; /* count of request data pointers */
+    void                 *reply_data; /* reply data pointer */
+    struct __server_iovec data[__SERVER_MAX_DATA];  /* request variable size data */
+};
+
+extern unsigned int wine_server_call( void *req_ptr );
 extern void wine_server_send_fd( int fd );
 extern int wine_server_recv_fd( handle_t handle );
-extern const char *get_config_dir(void);
 
 /* do a server call and set the last error code */
-inline static unsigned int __server_call_err( union generic_request *req, size_t size )
+inline static unsigned int wine_server_call_err( void *req_ptr )
 {
-    unsigned int res = wine_server_call( req, size );
+    unsigned int res = wine_server_call( req_ptr );
     if (res) SetLastError( RtlNtStatusToDosError(res) );
     return res;
 }
 
-/* get a pointer to the variable part of the request */
-inline static void *server_data_ptr( const void *req )
+/* get the size of the variable part of the returned reply */
+inline static size_t wine_server_reply_size( const void *reply )
 {
-    return (char *)NtCurrentTeb()->buffer + ((struct request_header *)req)->var_offset;
+    return ((struct reply_header *)reply)->reply_size;
 }
 
-/* get the size of the variable part of the request */
-inline static size_t server_data_size( const void *req )
+/* add some data to be sent along with the request */
+inline static void wine_server_add_data( void *req_ptr, const void *ptr, unsigned int size )
 {
-    return ((struct request_header *)req)->var_size;
+    struct __server_request_info * const req = req_ptr;
+    if (size)
+    {
+        req->data[req->data_count].ptr = ptr;
+        req->data[req->data_count++].size = size;
+        req->u.req.request_header.request_size += size;
+    }
 }
 
-
-/* exception support for server calls */
-
-extern DWORD __wine_server_exception_handler( PEXCEPTION_RECORD record, EXCEPTION_FRAME *frame,
-                                              CONTEXT *context, EXCEPTION_FRAME **pdispatcher );
-
-struct __server_exception_frame
+/* set the pointer and max size for the reply var data */
+inline static void wine_server_set_reply( void *req_ptr, void *ptr, unsigned int max_size )
 {
-    EXCEPTION_FRAME  frame;
-    unsigned int     buffer_pos;  /* saved buffer position */
-};
+    struct __server_request_info * const req = req_ptr;
+    req->reply_data = ptr;
+    req->u.req.request_header.reply_size = max_size;
+}
 
 
 /* macros for server requests */
 
 #define SERVER_START_REQ(type) \
     do { \
-        union generic_request __req; \
-        struct type##_request * const req = &__req.type; \
-        __req.header.req = REQ_##type; \
-        __req.header.var_size = 0; \
+        struct __server_request_info __req; \
+        struct type##_request * const req = &__req.u.req.type##_request; \
+        const struct type##_reply * const reply = &__req.u.reply.type##_reply; \
+        __req.u.req.request_header.req = REQ_##type; \
+        __req.u.req.request_header.request_size = 0; \
+        __req.u.req.request_header.reply_size = 0; \
+        __req.size = sizeof(*req); \
+        __req.data_count = 0; \
+        (void)reply; \
         do
 
 #define SERVER_END_REQ \
         while(0); \
     } while(0)
 
-#define SERVER_START_VAR_REQ(type,size) \
-    do { \
-        struct __server_exception_frame __f; \
-        union generic_request __req; \
-        struct type##_request * const req = &__req.type; \
-        __f.frame.Handler = __wine_server_exception_handler; \
-        __f.buffer_pos = NtCurrentTeb()->buffer_pos; \
-        __wine_push_frame( &__f.frame ); \
-        __req.header.req = REQ_##type; \
-        wine_server_alloc_req( &__req, (size) ); \
-        do
 
-#define SERVER_END_VAR_REQ \
-        while(0); \
-        NtCurrentTeb()->buffer_pos = __f.buffer_pos; \
-        __wine_pop_frame( &__f.frame ); \
-    } while(0)
-
-#define SERVER_CALL()      (wine_server_call( &__req, sizeof(*req) ))
-#define SERVER_CALL_ERR()  (__server_call_err( &__req, sizeof(*req) ))
-
-
+/* non-exported functions */
+extern void server_protocol_error( const char *err, ... ) WINE_NORETURN;
+extern void server_protocol_perror( const char *err ) WINE_NORETURN;
+extern const char *get_config_dir(void);
 extern void CLIENT_InitServer(void);
 extern void CLIENT_InitThread(void);
 extern void CLIENT_BootDone( int debug_level );
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 94f40d6..58cac3f 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -14,17 +14,15 @@
 
 struct request_header
 {
-    int            req;
-    unsigned short var_offset;
-    unsigned short var_size;
-    unsigned int   error;
+    int          req;
+    size_t       request_size;
+    size_t       reply_size;
 };
 
 struct reply_header
 {
-    unsigned int   error;
-    unsigned short var_offset;
-    unsigned short var_size;
+    unsigned int error;
+    size_t       reply_size;
 };
 
 
@@ -149,6 +147,13 @@
 } rectangle_t;
 
 
+typedef struct
+{
+    WCHAR          ch;
+    unsigned short attr;
+} char_info_t;
+
+
 
 
 
@@ -164,6 +169,10 @@
     handle_t     hstderr;
     int          cmd_show;
     /* VARARG(filename,string); */
+};
+struct new_process_reply
+{
+    struct reply_header __header;
     handle_t     info;
 };
 
@@ -175,6 +184,10 @@
     handle_t     info;
     int          pinherit;
     int          tinherit;
+};
+struct get_new_process_info_reply
+{
+    struct reply_header __header;
     void*        pid;
     handle_t     phandle;
     void*        tid;
@@ -190,6 +203,10 @@
     int          suspend;
     int          inherit;
     int          request_fd;
+};
+struct new_thread_reply
+{
+    struct reply_header __header;
     void*        tid;
     handle_t     handle;
 };
@@ -201,6 +218,10 @@
     struct request_header __header;
     int          debug_level;
 };
+struct boot_done_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -209,6 +230,10 @@
     struct request_header __header;
     void*        ldt_copy;
     int          ppid;
+};
+struct init_process_reply
+{
+    struct reply_header __header;
     int          create_flags;
     int          start_flags;
     unsigned int server_start;
@@ -230,6 +255,10 @@
     void*        name;
     handle_t     exe_file;
     int          gui;
+};
+struct init_process_done_reply
+{
+    struct reply_header __header;
     int          debugged;
 };
 
@@ -243,6 +272,10 @@
     void*        entry;
     int          reply_fd;
     int          wait_fd;
+};
+struct init_thread_reply
+{
+    struct reply_header __header;
     void*        pid;
     void*        tid;
     int          boot;
@@ -251,21 +284,15 @@
 
 
 
-struct set_thread_buffer_request
-{
-    struct request_header __header;
-    int          fd;
-    unsigned int offset;
-    unsigned int size;
-};
-
-
-
 struct terminate_process_request
 {
     struct request_header __header;
     handle_t     handle;
     int          exit_code;
+};
+struct terminate_process_reply
+{
+    struct reply_header __header;
     int          self;
 };
 
@@ -276,6 +303,10 @@
     struct request_header __header;
     handle_t     handle;
     int          exit_code;
+};
+struct terminate_thread_reply
+{
+    struct reply_header __header;
     int          self;
     int          last;
 };
@@ -286,6 +317,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct get_process_info_reply
+{
+    struct reply_header __header;
     void*        pid;
     int          debugged;
     int          exit_code;
@@ -304,6 +339,10 @@
     int          priority;
     int          affinity;
 };
+struct set_process_info_reply
+{
+    struct reply_header __header;
+};
 #define SET_PROCESS_INFO_PRIORITY 0x01
 #define SET_PROCESS_INFO_AFFINITY 0x02
 
@@ -314,6 +353,10 @@
     struct request_header __header;
     handle_t     handle;
     void*        tid_in;
+};
+struct get_thread_info_reply
+{
+    struct reply_header __header;
     void*        tid;
     void*        teb;
     int          exit_code;
@@ -330,6 +373,10 @@
     int          priority;
     int          affinity;
 };
+struct set_thread_info_reply
+{
+    struct reply_header __header;
+};
 #define SET_THREAD_INFO_PRIORITY 0x01
 #define SET_THREAD_INFO_AFFINITY 0x02
 
@@ -339,6 +386,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct suspend_thread_reply
+{
+    struct reply_header __header;
     int          count;
 };
 
@@ -348,6 +399,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct resume_thread_reply
+{
+    struct reply_header __header;
     int          count;
 };
 
@@ -362,6 +417,10 @@
     int          dbg_size;
     void*        name;
 };
+struct load_dll_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -370,6 +429,10 @@
     struct request_header __header;
     void*        base;
 };
+struct unload_dll_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -381,6 +444,10 @@
     void*        func;
     void*        param;
 };
+struct queue_apc_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -388,6 +455,10 @@
 {
     struct request_header __header;
     int          alertable;
+};
+struct get_apc_reply
+{
+    struct reply_header __header;
     void*        func;
     int          type;
     /* VARARG(args,ptrs); */
@@ -400,6 +471,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct close_handle_reply
+{
+    struct reply_header __header;
     int          fd;
 };
 
@@ -412,6 +487,10 @@
     int          flags;
     int          mask;
     int          fd;
+};
+struct set_handle_info_reply
+{
+    struct reply_header __header;
     int          old_flags;
     int          cur_fd;
 };
@@ -427,6 +506,10 @@
     unsigned int access;
     int          inherit;
     int          options;
+};
+struct dup_handle_reply
+{
+    struct reply_header __header;
     handle_t     handle;
     int          fd;
 };
@@ -442,6 +525,10 @@
     void*        pid;
     unsigned int access;
     int          inherit;
+};
+struct open_process_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -456,6 +543,10 @@
     int          usec;
     /* VARARG(handles,handles); */
 };
+struct select_reply
+{
+    struct reply_header __header;
+};
 #define SELECT_ALL           1
 #define SELECT_ALERTABLE     2
 #define SELECT_INTERRUPTIBLE 4
@@ -470,6 +561,10 @@
     int          initial_state;
     int          inherit;
     /* VARARG(name,unicode_str); */
+};
+struct create_event_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -480,6 +575,10 @@
     handle_t      handle;
     int           op;
 };
+struct event_op_reply
+{
+    struct reply_header __header;
+};
 enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
 
 
@@ -490,6 +589,10 @@
     unsigned int access;
     int          inherit;
     /* VARARG(name,unicode_str); */
+};
+struct open_event_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -501,6 +604,10 @@
     int          owned;
     int          inherit;
     /* VARARG(name,unicode_str); */
+};
+struct create_mutex_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -511,6 +618,10 @@
     struct request_header __header;
     handle_t     handle;
 };
+struct release_mutex_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -520,6 +631,10 @@
     unsigned int access;
     int          inherit;
     /* VARARG(name,unicode_str); */
+};
+struct open_mutex_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -532,6 +647,10 @@
     unsigned int max;
     int          inherit;
     /* VARARG(name,unicode_str); */
+};
+struct create_semaphore_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -542,6 +661,10 @@
     struct request_header __header;
     handle_t     handle;
     unsigned int count;
+};
+struct release_semaphore_reply
+{
+    struct reply_header __header;
     unsigned int prev_count;
 };
 
@@ -553,6 +676,10 @@
     unsigned int access;
     int          inherit;
     /* VARARG(name,unicode_str); */
+};
+struct open_semaphore_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -568,6 +695,10 @@
     unsigned int attrs;
     int          drive_type;
     /* VARARG(filename,string); */
+};
+struct create_file_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -579,6 +710,10 @@
     unsigned int access;
     int          inherit;
     int          fd;
+};
+struct alloc_file_handle_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -589,6 +724,10 @@
     struct request_header __header;
     handle_t     handle;
     unsigned int access;
+};
+struct get_handle_fd_reply
+{
+    struct reply_header __header;
     int          fd;
     int          type;
 };
@@ -607,6 +746,10 @@
     int          low;
     int          high;
     int          whence;
+};
+struct set_file_pointer_reply
+{
+    struct reply_header __header;
     int          new_low;
     int          new_high;
 };
@@ -618,6 +761,10 @@
     struct request_header __header;
     handle_t     handle;
 };
+struct truncate_file_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -628,6 +775,10 @@
     time_t       access_time;
     time_t       write_time;
 };
+struct set_file_time_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -636,6 +787,10 @@
     struct request_header __header;
     handle_t     handle;
 };
+struct flush_file_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -643,6 +798,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct get_file_info_reply
+{
+    struct reply_header __header;
     int          type;
     int          attr;
     time_t       access_time;
@@ -666,6 +825,10 @@
     unsigned int count_low;
     unsigned int count_high;
 };
+struct lock_file_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -678,6 +841,10 @@
     unsigned int count_low;
     unsigned int count_high;
 };
+struct unlock_file_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -685,6 +852,10 @@
 {
     struct request_header __header;
     int          inherit;
+};
+struct create_pipe_reply
+{
+    struct reply_header __header;
     handle_t     handle_read;
     handle_t     handle_write;
 };
@@ -699,6 +870,10 @@
     int          family;
     int          type;
     int          protocol;
+};
+struct create_socket_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -710,6 +885,10 @@
     handle_t     lhandle;
     unsigned int access;
     int          inherit;
+};
+struct accept_socket_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -722,6 +901,10 @@
     unsigned int mask;
     handle_t     event;
 };
+struct set_socket_event_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -732,6 +915,10 @@
     int          service;
     handle_t     s_event;
     handle_t     c_event;
+};
+struct get_socket_event_reply
+{
+    struct reply_header __header;
     unsigned int mask;
     unsigned int pmask;
     unsigned int state;
@@ -748,6 +935,10 @@
     unsigned int sstate;
     unsigned int cstate;
 };
+struct enable_socket_event_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -757,6 +948,10 @@
     unsigned int access;
     int          inherit;
     void*        pid;
+};
+struct alloc_console_reply
+{
+    struct reply_header __header;
     handle_t     handle_in;
     handle_t     event;
 };
@@ -767,6 +962,10 @@
 {
     struct request_header __header;
 };
+struct free_console_reply
+{
+    struct reply_header __header;
+};
 
 
 #define CONSOLE_RENDERER_NONE_EVENT        0x00
@@ -818,6 +1017,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct get_console_renderer_events_reply
+{
+    struct reply_header __header;
     /* VARARG(data,bytes); */
 };
 
@@ -831,6 +1034,10 @@
     unsigned int access;
     int          inherit;
     int          share;
+};
+struct open_console_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -840,6 +1047,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct get_console_mode_reply
+{
+    struct reply_header __header;
     int          mode;
 };
 
@@ -851,6 +1062,10 @@
     handle_t     handle;
     int          mode;
 };
+struct set_console_mode_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -864,6 +1079,10 @@
     int          history_size;
     /* VARARG(title,unicode_str); */
 };
+struct set_console_input_info_reply
+{
+    struct reply_header __header;
+};
 #define SET_CONSOLE_INPUT_INFO_ACTIVE_SB        0x01
 #define SET_CONSOLE_INPUT_INFO_TITLE            0x02
 #define SET_CONSOLE_INPUT_INFO_HISTORY_MODE     0x04
@@ -875,6 +1094,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct get_console_input_info_reply
+{
+    struct reply_header __header;
     int          history_mode;
     int          history_size;
     int          history_index;
@@ -889,6 +1112,10 @@
     handle_t     handle;
     /* VARARG(line,unicode_str); */
 };
+struct append_console_input_history_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -897,6 +1124,11 @@
     struct request_header __header;
     handle_t     handle;
     int          index;
+};
+struct get_console_input_history_reply
+{
+    struct reply_header __header;
+    int          total;
     /* VARARG(line,unicode_str); */
 };
 
@@ -909,6 +1141,10 @@
     int          access;
     int          share;
     int          inherit;
+};
+struct create_console_output_reply
+{
+    struct reply_header __header;
     handle_t     handle_out;
 };
 
@@ -933,6 +1169,10 @@
     short int    max_width;
     short int    max_height;
 };
+struct set_console_output_info_reply
+{
+    struct reply_header __header;
+};
 #define SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM     0x01
 #define SET_CONSOLE_OUTPUT_INFO_CURSOR_POS      0x02
 #define SET_CONSOLE_OUTPUT_INFO_SIZE            0x04
@@ -946,6 +1186,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct get_console_output_info_reply
+{
+    struct reply_header __header;
     short int    cursor_size;
     short int    cursor_visible;
     short int    cursor_x;
@@ -967,6 +1211,10 @@
     struct request_header __header;
     handle_t     handle;
     /* VARARG(rec,input_records); */
+};
+struct write_console_input_reply
+{
+    struct reply_header __header;
     int          written;
 };
 
@@ -977,6 +1225,10 @@
     struct request_header __header;
     handle_t     handle;
     int          flush;
+};
+struct read_console_input_reply
+{
+    struct reply_header __header;
     int          read;
     /* VARARG(rec,input_records); */
 };
@@ -987,18 +1239,45 @@
 {
     struct request_header __header;
     handle_t     handle;
+    int          x;
+    int          y;
     int          mode;
-
-    short int    x;
-    short int    y;
+    int          wrap;
     /* VARARG(data,bytes); */
+};
+struct write_console_output_reply
+{
+    struct reply_header __header;
+    int          written;
+    int          width;
+    int          height;
+};
+enum char_info_mode
+{
+    CHAR_INFO_MODE_TEXT,
+    CHAR_INFO_MODE_ATTR,
+    CHAR_INFO_MODE_TEXTATTR,
+    CHAR_INFO_MODE_TEXTSTDATTR
+};
+
+
+
+struct fill_console_output_request
+{
+    struct request_header __header;
+    handle_t     handle;
+    int          x;
+    int          y;
+    int          mode;
+    int          count;
+    int          wrap;
+    char_info_t  data;
+};
+struct fill_console_output_reply
+{
+    struct reply_header __header;
     int          written;
 };
-#define WRITE_CONSOLE_MODE_TEXT         0x00
-#define WRITE_CONSOLE_MODE_ATTR         0x01
-#define WRITE_CONSOLE_MODE_TEXTATTR     0x02
-#define WRITE_CONSOLE_MODE_TEXTSTDATTR  0x03
-#define WRITE_CONSOLE_MODE_UNIFORM      0x04
 
 
 
@@ -1006,12 +1285,16 @@
 {
     struct request_header __header;
     handle_t     handle;
-    short int    x;
-    short int    y;
-    short int    w;
-    short int    h;
-    short int    eff_w;
-    short int    eff_h;
+    int          x;
+    int          y;
+    int          mode;
+    int          wrap;
+};
+struct read_console_output_reply
+{
+    struct reply_header __header;
+    int          width;
+    int          height;
     /* VARARG(data,bytes); */
 };
 
@@ -1027,6 +1310,10 @@
     short int    w;
     short int    h;
 };
+struct move_console_output_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1035,6 +1322,10 @@
     struct request_header __header;
     int          subtree;
     int          filter;
+};
+struct create_change_notification_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -1049,6 +1340,10 @@
     int          inherit;
     handle_t     file_handle;
     /* VARARG(name,unicode_str); */
+};
+struct create_mapping_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -1069,6 +1364,10 @@
     unsigned int access;
     int          inherit;
     /* VARARG(name,unicode_str); */
+};
+struct open_mapping_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -1078,6 +1377,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct get_mapping_info_reply
+{
+    struct reply_header __header;
     int          size_high;
     int          size_low;
     int          protect;
@@ -1096,6 +1399,10 @@
     unsigned int access;
     int          inherit;
     int          id;
+};
+struct create_device_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -1107,6 +1414,10 @@
     int          inherit;
     int          flags;
     void*        pid;
+};
+struct create_snapshot_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -1117,6 +1428,10 @@
     struct request_header __header;
     handle_t     handle;
     int          reset;
+};
+struct next_process_reply
+{
+    struct reply_header __header;
     int          count;
     void*        pid;
     int          threads;
@@ -1130,6 +1445,10 @@
     struct request_header __header;
     handle_t     handle;
     int          reset;
+};
+struct next_thread_reply
+{
+    struct reply_header __header;
     int          count;
     void*        pid;
     void*        tid;
@@ -1144,6 +1463,10 @@
     struct request_header __header;
     handle_t     handle;
     int          reset;
+};
+struct next_module_reply
+{
+    struct reply_header __header;
     void*        pid;
     void*        base;
 };
@@ -1154,6 +1477,10 @@
 {
     struct request_header __header;
     int           get_handle;
+};
+struct wait_debug_event_reply
+{
+    struct reply_header __header;
     void*         pid;
     void*         tid;
     handle_t      wait;
@@ -1167,6 +1494,10 @@
     struct request_header __header;
     int              first;
     /* VARARG(record,exc_event); */
+};
+struct queue_exception_event_reply
+{
+    struct reply_header __header;
     handle_t         handle;
 };
 
@@ -1176,6 +1507,10 @@
 {
     struct request_header __header;
     handle_t         handle;
+};
+struct get_exception_status_reply
+{
+    struct reply_header __header;
     int              status;
     /* VARARG(context,context); */
 };
@@ -1189,6 +1524,10 @@
     int           unicode;
     int           length;
 };
+struct output_debug_string_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1199,6 +1538,10 @@
     void*        tid;
     int          status;
 };
+struct continue_debug_event_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1207,6 +1550,10 @@
     struct request_header __header;
     void*        pid;
 };
+struct debug_process_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1215,7 +1562,10 @@
     struct request_header __header;
     handle_t     handle;
     void*        addr;
-    int          len;
+};
+struct read_process_memory_reply
+{
+    struct reply_header __header;
     /* VARARG(data,bytes); */
 };
 
@@ -1226,11 +1576,14 @@
     struct request_header __header;
     handle_t     handle;
     void*        addr;
-    int          len;
     unsigned int first_mask;
     unsigned int last_mask;
     /* VARARG(data,bytes); */
 };
+struct write_process_memory_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1241,8 +1594,13 @@
     unsigned int access;
     unsigned int options;
     time_t       modif;
-    /* VARARG(name,unicode_len_str); */
+    size_t       namelen;
+    /* VARARG(name,unicode_str,namelen); */
     /* VARARG(class,unicode_str); */
+};
+struct create_key_reply
+{
+    struct reply_header __header;
     handle_t     hkey;
     int          created;
 };
@@ -1254,6 +1612,10 @@
     handle_t     parent;
     unsigned int access;
     /* VARARG(name,unicode_str); */
+};
+struct open_key_reply
+{
+    struct reply_header __header;
     handle_t     hkey;
 };
 
@@ -1264,6 +1626,10 @@
     struct request_header __header;
     handle_t     hkey;
 };
+struct delete_key_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1272,7 +1638,11 @@
     struct request_header __header;
     handle_t     hkey;
     int          index;
-    int          full;
+    int          info_class;
+};
+struct enum_key_reply
+{
+    struct reply_header __header;
     int          subkeys;
     int          max_subkey;
     int          max_class;
@@ -1280,7 +1650,9 @@
     int          max_value;
     int          max_data;
     time_t       modif;
-    /* VARARG(name,unicode_len_str); */
+    size_t       total;
+    size_t       namelen;
+    /* VARARG(name,unicode_str,namelen); */
     /* VARARG(class,unicode_str); */
 };
 
@@ -1291,11 +1663,14 @@
     struct request_header __header;
     handle_t     hkey;
     int          type;
-    unsigned int total;
-    unsigned int offset;
-    /* VARARG(name,unicode_len_str); */
+    size_t       namelen;
+    /* VARARG(name,unicode_str,namelen); */
     /* VARARG(data,bytes); */
 };
+struct set_key_value_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1303,10 +1678,13 @@
 {
     struct request_header __header;
     handle_t     hkey;
-    unsigned int offset;
-    /* VARARG(name,unicode_len_str); */
+    /* VARARG(name,unicode_str); */
+};
+struct get_key_value_reply
+{
+    struct reply_header __header;
     int          type;
-    int          len;
+    size_t       total;
     /* VARARG(data,bytes); */
 };
 
@@ -1317,10 +1695,15 @@
     struct request_header __header;
     handle_t     hkey;
     int          index;
-    unsigned int offset;
+    int          info_class;
+};
+struct enum_key_value_reply
+{
+    struct reply_header __header;
     int          type;
-    int          len;
-    /* VARARG(name,unicode_len_str); */
+    size_t       total;
+    size_t       namelen;
+    /* VARARG(name,unicode_str,namelen); */
     /* VARARG(data,bytes); */
 };
 
@@ -1332,6 +1715,10 @@
     handle_t     hkey;
     /* VARARG(name,unicode_str); */
 };
+struct delete_key_value_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1342,6 +1729,10 @@
     handle_t     file;
     /* VARARG(name,unicode_str); */
 };
+struct load_registry_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1351,6 +1742,10 @@
     handle_t     hkey;
     handle_t     file;
 };
+struct save_registry_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1360,6 +1755,10 @@
     handle_t     hkey;
     /* VARARG(file,string); */
 };
+struct save_registry_atexit_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1370,6 +1769,10 @@
     int          saving;
     int          period;
 };
+struct set_registry_levels_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1379,6 +1782,10 @@
     int          inherit;
     int          manual;
     /* VARARG(name,unicode_str); */
+};
+struct create_timer_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -1390,6 +1797,10 @@
     unsigned int access;
     int          inherit;
     /* VARARG(name,unicode_str); */
+};
+struct open_timer_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -1404,6 +1815,10 @@
     void*        callback;
     void*        arg;
 };
+struct set_timer_reply
+{
+    struct reply_header __header;
+};
 
 
 struct cancel_timer_request
@@ -1411,6 +1826,10 @@
     struct request_header __header;
     handle_t     handle;
 };
+struct cancel_timer_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1419,6 +1838,10 @@
     struct request_header __header;
     handle_t     handle;
     unsigned int flags;
+};
+struct get_thread_context_reply
+{
+    struct reply_header __header;
     /* VARARG(context,context); */
 };
 
@@ -1431,6 +1854,10 @@
     unsigned int flags;
     /* VARARG(context,context); */
 };
+struct set_thread_context_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1439,6 +1866,10 @@
     struct request_header __header;
     handle_t      handle;
     int           entry;
+};
+struct get_selector_entry_reply
+{
+    struct reply_header __header;
     unsigned int  base;
     unsigned int  limit;
     unsigned char flags;
@@ -1451,6 +1882,10 @@
     struct request_header __header;
     int           local;
     /* VARARG(name,unicode_str); */
+};
+struct add_atom_reply
+{
+    struct reply_header __header;
     atom_t        atom;
 };
 
@@ -1462,6 +1897,10 @@
     atom_t        atom;
     int           local;
 };
+struct delete_atom_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1470,6 +1909,10 @@
     struct request_header __header;
     int          local;
     /* VARARG(name,unicode_str); */
+};
+struct find_atom_reply
+{
+    struct reply_header __header;
     atom_t       atom;
 };
 
@@ -1480,6 +1923,10 @@
     struct request_header __header;
     atom_t       atom;
     int          local;
+};
+struct get_atom_name_reply
+{
+    struct reply_header __header;
     int          count;
     /* VARARG(name,unicode_str); */
 };
@@ -1491,12 +1938,20 @@
     struct request_header __header;
     int          entries;
 };
+struct init_atom_table_reply
+{
+    struct reply_header __header;
+};
 
 
 
 struct get_msg_queue_request
 {
     struct request_header __header;
+};
+struct get_msg_queue_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -1508,6 +1963,10 @@
     unsigned int wake_mask;
     unsigned int changed_mask;
     int          skip_wait;
+};
+struct set_queue_mask_reply
+{
+    struct reply_header __header;
     unsigned int wake_bits;
     unsigned int changed_bits;
 };
@@ -1518,6 +1977,10 @@
 {
     struct request_header __header;
     int          clear;
+};
+struct get_queue_status_reply
+{
+    struct reply_header __header;
     unsigned int wake_bits;
     unsigned int changed_bits;
 };
@@ -1529,6 +1992,10 @@
     struct request_header __header;
     handle_t     handle;
     int          timeout;
+};
+struct wait_input_idle_reply
+{
+    struct reply_header __header;
     handle_t     event;
 };
 
@@ -1550,6 +2017,10 @@
     int             timeout;
     /* VARARG(data,bytes); */
 };
+struct send_message_reply
+{
+    struct reply_header __header;
+};
 
 enum message_type
 {
@@ -1572,6 +2043,10 @@
     user_handle_t   get_win;
     unsigned int    get_first;
     unsigned int    get_last;
+};
+struct get_message_reply
+{
+    struct reply_header __header;
     int             type;
     user_handle_t   win;
     unsigned int    msg;
@@ -1581,6 +2056,7 @@
     int             y;
     unsigned int    time;
     unsigned int    info;
+    size_t          total;
     /* VARARG(data,bytes); */
 };
 #define GET_MSG_REMOVE      1
@@ -1595,6 +2071,10 @@
     int             remove;
     /* VARARG(data,bytes); */
 };
+struct reply_message_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1602,6 +2082,10 @@
 {
     struct request_header __header;
     int             cancel;
+};
+struct get_message_reply_reply
+{
+    struct reply_header __header;
     unsigned int    result;
     /* VARARG(data,bytes); */
 };
@@ -1617,6 +2101,10 @@
     unsigned int    rate;
     unsigned int    lparam;
 };
+struct set_win_timer_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1627,6 +2115,10 @@
     unsigned int    msg;
     unsigned int    id;
 };
+struct kill_win_timer_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1638,6 +2130,10 @@
     unsigned int attributes;
     unsigned int sharing;
     /* VARARG(name,string); */
+};
+struct create_serial_reply
+{
+    struct reply_header __header;
     handle_t     handle;
 };
 
@@ -1647,6 +2143,10 @@
 {
     struct request_header __header;
     handle_t     handle;
+};
+struct get_serial_info_reply
+{
+    struct reply_header __header;
     unsigned int readinterval;
     unsigned int readconst;
     unsigned int readmult;
@@ -1671,6 +2171,10 @@
     unsigned int eventmask;
     unsigned int commerror;
 };
+struct set_serial_info_reply
+{
+    struct reply_header __header;
+};
 #define SERIALINFO_SET_TIMEOUTS  0x01
 #define SERIALINFO_SET_MASK      0x02
 #define SERIALINFO_SET_ERROR     0x04
@@ -1683,6 +2187,10 @@
     handle_t     file_handle;
     int          count;
     int          type;
+};
+struct create_async_reply
+{
+    struct reply_header __header;
     int          timeout;
 };
 #define ASYNC_TYPE_READ  0x01
@@ -1701,6 +2209,10 @@
     unsigned int   insize;
     unsigned int   timeout;
     /* VARARG(filename,string); */
+};
+struct create_named_pipe_reply
+{
+    struct reply_header __header;
     handle_t       handle;
 };
 
@@ -1711,6 +2223,10 @@
     struct request_header __header;
     unsigned int   access;
     /* VARARG(filename,string); */
+};
+struct open_named_pipe_reply
+{
+    struct reply_header __header;
     handle_t       handle;
 };
 
@@ -1723,6 +2239,10 @@
     void*          overlapped;
     void*          func;
 };
+struct connect_named_pipe_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1734,6 +2254,10 @@
     void*          func;
     /* VARARG(filename,string); */
 };
+struct wait_named_pipe_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1742,12 +2266,20 @@
     struct request_header __header;
     handle_t       handle;
 };
+struct disconnect_named_pipe_reply
+{
+    struct reply_header __header;
+};
 
 
 struct get_named_pipe_info_request
 {
     struct request_header __header;
     handle_t       handle;
+};
+struct get_named_pipe_info_reply
+{
+    struct reply_header __header;
     unsigned int   flags;
     unsigned int   maxinstances;
     unsigned int   outsize;
@@ -1762,6 +2294,10 @@
     user_handle_t  parent;
     user_handle_t  owner;
     atom_t         atom;
+};
+struct create_window_reply
+{
+    struct reply_header __header;
     user_handle_t  handle;
 };
 
@@ -1773,6 +2309,10 @@
     user_handle_t  handle;
     user_handle_t  parent;
     user_handle_t  previous;
+};
+struct link_window_reply
+{
+    struct reply_header __header;
     user_handle_t  full_parent;
 };
 
@@ -1783,6 +2323,10 @@
     struct request_header __header;
     user_handle_t  handle;
 };
+struct destroy_window_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1791,6 +2335,10 @@
     struct request_header __header;
     user_handle_t  handle;
     user_handle_t  owner;
+};
+struct set_window_owner_reply
+{
+    struct reply_header __header;
     user_handle_t  full_owner;
 };
 
@@ -1800,6 +2348,10 @@
 {
     struct request_header __header;
     user_handle_t  handle;
+};
+struct get_window_info_reply
+{
+    struct reply_header __header;
     user_handle_t  full_handle;
     void*          pid;
     void*          tid;
@@ -1818,6 +2370,10 @@
     unsigned int   id;
     void*          instance;
     void*          user_data;
+};
+struct set_window_info_reply
+{
+    struct reply_header __header;
     unsigned int   old_style;
     unsigned int   old_ex_style;
     unsigned int   old_id;
@@ -1836,6 +2392,10 @@
 {
     struct request_header __header;
     user_handle_t  handle;
+};
+struct get_window_parents_reply
+{
+    struct reply_header __header;
     int            count;
     /* VARARG(parents,user_handles); */
 };
@@ -1848,6 +2408,10 @@
     user_handle_t  parent;
     atom_t         atom;
     void*          tid;
+};
+struct get_window_children_reply
+{
+    struct reply_header __header;
     int            count;
     /* VARARG(children,user_handles); */
 };
@@ -1858,6 +2422,10 @@
 {
     struct request_header __header;
     user_handle_t  handle;
+};
+struct get_window_tree_reply
+{
+    struct reply_header __header;
     user_handle_t  parent;
     user_handle_t  owner;
     user_handle_t  next_sibling;
@@ -1876,6 +2444,10 @@
     rectangle_t    window;
     rectangle_t    client;
 };
+struct set_window_rectangles_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1883,6 +2455,10 @@
 {
     struct request_header __header;
     user_handle_t  handle;
+};
+struct get_window_rectangles_reply
+{
+    struct reply_header __header;
     rectangle_t    window;
     rectangle_t    client;
 };
@@ -1893,6 +2469,10 @@
 {
     struct request_header __header;
     user_handle_t  handle;
+};
+struct get_window_text_reply
+{
+    struct reply_header __header;
     /* VARARG(text,unicode_str); */
 };
 
@@ -1904,6 +2484,10 @@
     user_handle_t  handle;
     /* VARARG(text,unicode_str); */
 };
+struct set_window_text_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1913,6 +2497,10 @@
     user_handle_t  handle;
     int             incr;
 };
+struct inc_window_paint_count_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1921,6 +2509,10 @@
     struct request_header __header;
     user_handle_t  from;
     user_handle_t  to;
+};
+struct get_windows_offset_reply
+{
+    struct reply_header __header;
     int            x;
     int            y;
 };
@@ -1935,6 +2527,10 @@
     int            string;
     handle_t       handle;
 };
+struct set_window_property_reply
+{
+    struct reply_header __header;
+};
 
 
 
@@ -1943,6 +2539,10 @@
     struct request_header __header;
     user_handle_t  window;
     atom_t         atom;
+};
+struct remove_window_property_reply
+{
+    struct reply_header __header;
     handle_t       handle;
 };
 
@@ -1953,6 +2553,10 @@
     struct request_header __header;
     user_handle_t  window;
     atom_t         atom;
+};
+struct get_window_property_reply
+{
+    struct reply_header __header;
     handle_t       handle;
 };
 
@@ -1962,6 +2566,11 @@
 {
     struct request_header __header;
     user_handle_t  window;
+};
+struct get_window_properties_reply
+{
+    struct reply_header __header;
+    int            total;
     /* VARARG(props,properties); */
 };
 
@@ -1975,7 +2584,6 @@
     REQ_init_process,
     REQ_init_process_done,
     REQ_init_thread,
-    REQ_set_thread_buffer,
     REQ_terminate_process,
     REQ_terminate_thread,
     REQ_get_process_info,
@@ -2034,6 +2642,7 @@
     REQ_write_console_input,
     REQ_read_console_input,
     REQ_write_console_output,
+    REQ_fill_console_output,
     REQ_read_console_output,
     REQ_move_console_output,
     REQ_create_change_notification,
@@ -2122,157 +2731,310 @@
 union generic_request
 {
     struct request_max_size max_size;
-    struct request_header header;
-    struct new_process_request new_process;
-    struct get_new_process_info_request get_new_process_info;
-    struct new_thread_request new_thread;
-    struct boot_done_request boot_done;
-    struct init_process_request init_process;
-    struct init_process_done_request init_process_done;
-    struct init_thread_request init_thread;
-    struct set_thread_buffer_request set_thread_buffer;
-    struct terminate_process_request terminate_process;
-    struct terminate_thread_request terminate_thread;
-    struct get_process_info_request get_process_info;
-    struct set_process_info_request set_process_info;
-    struct get_thread_info_request get_thread_info;
-    struct set_thread_info_request set_thread_info;
-    struct suspend_thread_request suspend_thread;
-    struct resume_thread_request resume_thread;
-    struct load_dll_request load_dll;
-    struct unload_dll_request unload_dll;
-    struct queue_apc_request queue_apc;
-    struct get_apc_request get_apc;
-    struct close_handle_request close_handle;
-    struct set_handle_info_request set_handle_info;
-    struct dup_handle_request dup_handle;
-    struct open_process_request open_process;
-    struct select_request select;
-    struct create_event_request create_event;
-    struct event_op_request event_op;
-    struct open_event_request open_event;
-    struct create_mutex_request create_mutex;
-    struct release_mutex_request release_mutex;
-    struct open_mutex_request open_mutex;
-    struct create_semaphore_request create_semaphore;
-    struct release_semaphore_request release_semaphore;
-    struct open_semaphore_request open_semaphore;
-    struct create_file_request create_file;
-    struct alloc_file_handle_request alloc_file_handle;
-    struct get_handle_fd_request get_handle_fd;
-    struct set_file_pointer_request set_file_pointer;
-    struct truncate_file_request truncate_file;
-    struct set_file_time_request set_file_time;
-    struct flush_file_request flush_file;
-    struct get_file_info_request get_file_info;
-    struct lock_file_request lock_file;
-    struct unlock_file_request unlock_file;
-    struct create_pipe_request create_pipe;
-    struct create_socket_request create_socket;
-    struct accept_socket_request accept_socket;
-    struct set_socket_event_request set_socket_event;
-    struct get_socket_event_request get_socket_event;
-    struct enable_socket_event_request enable_socket_event;
-    struct alloc_console_request alloc_console;
-    struct free_console_request free_console;
-    struct get_console_renderer_events_request get_console_renderer_events;
-    struct open_console_request open_console;
-    struct get_console_mode_request get_console_mode;
-    struct set_console_mode_request set_console_mode;
-    struct set_console_input_info_request set_console_input_info;
-    struct get_console_input_info_request get_console_input_info;
-    struct append_console_input_history_request append_console_input_history;
-    struct get_console_input_history_request get_console_input_history;
-    struct create_console_output_request create_console_output;
-    struct set_console_output_info_request set_console_output_info;
-    struct get_console_output_info_request get_console_output_info;
-    struct write_console_input_request write_console_input;
-    struct read_console_input_request read_console_input;
-    struct write_console_output_request write_console_output;
-    struct read_console_output_request read_console_output;
-    struct move_console_output_request move_console_output;
-    struct create_change_notification_request create_change_notification;
-    struct create_mapping_request create_mapping;
-    struct open_mapping_request open_mapping;
-    struct get_mapping_info_request get_mapping_info;
-    struct create_device_request create_device;
-    struct create_snapshot_request create_snapshot;
-    struct next_process_request next_process;
-    struct next_thread_request next_thread;
-    struct next_module_request next_module;
-    struct wait_debug_event_request wait_debug_event;
-    struct queue_exception_event_request queue_exception_event;
-    struct get_exception_status_request get_exception_status;
-    struct output_debug_string_request output_debug_string;
-    struct continue_debug_event_request continue_debug_event;
-    struct debug_process_request debug_process;
-    struct read_process_memory_request read_process_memory;
-    struct write_process_memory_request write_process_memory;
-    struct create_key_request create_key;
-    struct open_key_request open_key;
-    struct delete_key_request delete_key;
-    struct enum_key_request enum_key;
-    struct set_key_value_request set_key_value;
-    struct get_key_value_request get_key_value;
-    struct enum_key_value_request enum_key_value;
-    struct delete_key_value_request delete_key_value;
-    struct load_registry_request load_registry;
-    struct save_registry_request save_registry;
-    struct save_registry_atexit_request save_registry_atexit;
-    struct set_registry_levels_request set_registry_levels;
-    struct create_timer_request create_timer;
-    struct open_timer_request open_timer;
-    struct set_timer_request set_timer;
-    struct cancel_timer_request cancel_timer;
-    struct get_thread_context_request get_thread_context;
-    struct set_thread_context_request set_thread_context;
-    struct get_selector_entry_request get_selector_entry;
-    struct add_atom_request add_atom;
-    struct delete_atom_request delete_atom;
-    struct find_atom_request find_atom;
-    struct get_atom_name_request get_atom_name;
-    struct init_atom_table_request init_atom_table;
-    struct get_msg_queue_request get_msg_queue;
-    struct set_queue_mask_request set_queue_mask;
-    struct get_queue_status_request get_queue_status;
-    struct wait_input_idle_request wait_input_idle;
-    struct send_message_request send_message;
-    struct get_message_request get_message;
-    struct reply_message_request reply_message;
-    struct get_message_reply_request get_message_reply;
-    struct set_win_timer_request set_win_timer;
-    struct kill_win_timer_request kill_win_timer;
-    struct create_serial_request create_serial;
-    struct get_serial_info_request get_serial_info;
-    struct set_serial_info_request set_serial_info;
-    struct create_async_request create_async;
-    struct create_named_pipe_request create_named_pipe;
-    struct open_named_pipe_request open_named_pipe;
-    struct connect_named_pipe_request connect_named_pipe;
-    struct wait_named_pipe_request wait_named_pipe;
-    struct disconnect_named_pipe_request disconnect_named_pipe;
-    struct get_named_pipe_info_request get_named_pipe_info;
-    struct create_window_request create_window;
-    struct link_window_request link_window;
-    struct destroy_window_request destroy_window;
-    struct set_window_owner_request set_window_owner;
-    struct get_window_info_request get_window_info;
-    struct set_window_info_request set_window_info;
-    struct get_window_parents_request get_window_parents;
-    struct get_window_children_request get_window_children;
-    struct get_window_tree_request get_window_tree;
-    struct set_window_rectangles_request set_window_rectangles;
-    struct get_window_rectangles_request get_window_rectangles;
-    struct get_window_text_request get_window_text;
-    struct set_window_text_request set_window_text;
-    struct inc_window_paint_count_request inc_window_paint_count;
-    struct get_windows_offset_request get_windows_offset;
-    struct set_window_property_request set_window_property;
-    struct remove_window_property_request remove_window_property;
-    struct get_window_property_request get_window_property;
-    struct get_window_properties_request get_window_properties;
+    struct request_header request_header;
+    struct new_process_request new_process_request;
+    struct get_new_process_info_request get_new_process_info_request;
+    struct new_thread_request new_thread_request;
+    struct boot_done_request boot_done_request;
+    struct init_process_request init_process_request;
+    struct init_process_done_request init_process_done_request;
+    struct init_thread_request init_thread_request;
+    struct terminate_process_request terminate_process_request;
+    struct terminate_thread_request terminate_thread_request;
+    struct get_process_info_request get_process_info_request;
+    struct set_process_info_request set_process_info_request;
+    struct get_thread_info_request get_thread_info_request;
+    struct set_thread_info_request set_thread_info_request;
+    struct suspend_thread_request suspend_thread_request;
+    struct resume_thread_request resume_thread_request;
+    struct load_dll_request load_dll_request;
+    struct unload_dll_request unload_dll_request;
+    struct queue_apc_request queue_apc_request;
+    struct get_apc_request get_apc_request;
+    struct close_handle_request close_handle_request;
+    struct set_handle_info_request set_handle_info_request;
+    struct dup_handle_request dup_handle_request;
+    struct open_process_request open_process_request;
+    struct select_request select_request;
+    struct create_event_request create_event_request;
+    struct event_op_request event_op_request;
+    struct open_event_request open_event_request;
+    struct create_mutex_request create_mutex_request;
+    struct release_mutex_request release_mutex_request;
+    struct open_mutex_request open_mutex_request;
+    struct create_semaphore_request create_semaphore_request;
+    struct release_semaphore_request release_semaphore_request;
+    struct open_semaphore_request open_semaphore_request;
+    struct create_file_request create_file_request;
+    struct alloc_file_handle_request alloc_file_handle_request;
+    struct get_handle_fd_request get_handle_fd_request;
+    struct set_file_pointer_request set_file_pointer_request;
+    struct truncate_file_request truncate_file_request;
+    struct set_file_time_request set_file_time_request;
+    struct flush_file_request flush_file_request;
+    struct get_file_info_request get_file_info_request;
+    struct lock_file_request lock_file_request;
+    struct unlock_file_request unlock_file_request;
+    struct create_pipe_request create_pipe_request;
+    struct create_socket_request create_socket_request;
+    struct accept_socket_request accept_socket_request;
+    struct set_socket_event_request set_socket_event_request;
+    struct get_socket_event_request get_socket_event_request;
+    struct enable_socket_event_request enable_socket_event_request;
+    struct alloc_console_request alloc_console_request;
+    struct free_console_request free_console_request;
+    struct get_console_renderer_events_request get_console_renderer_events_request;
+    struct open_console_request open_console_request;
+    struct get_console_mode_request get_console_mode_request;
+    struct set_console_mode_request set_console_mode_request;
+    struct set_console_input_info_request set_console_input_info_request;
+    struct get_console_input_info_request get_console_input_info_request;
+    struct append_console_input_history_request append_console_input_history_request;
+    struct get_console_input_history_request get_console_input_history_request;
+    struct create_console_output_request create_console_output_request;
+    struct set_console_output_info_request set_console_output_info_request;
+    struct get_console_output_info_request get_console_output_info_request;
+    struct write_console_input_request write_console_input_request;
+    struct read_console_input_request read_console_input_request;
+    struct write_console_output_request write_console_output_request;
+    struct fill_console_output_request fill_console_output_request;
+    struct read_console_output_request read_console_output_request;
+    struct move_console_output_request move_console_output_request;
+    struct create_change_notification_request create_change_notification_request;
+    struct create_mapping_request create_mapping_request;
+    struct open_mapping_request open_mapping_request;
+    struct get_mapping_info_request get_mapping_info_request;
+    struct create_device_request create_device_request;
+    struct create_snapshot_request create_snapshot_request;
+    struct next_process_request next_process_request;
+    struct next_thread_request next_thread_request;
+    struct next_module_request next_module_request;
+    struct wait_debug_event_request wait_debug_event_request;
+    struct queue_exception_event_request queue_exception_event_request;
+    struct get_exception_status_request get_exception_status_request;
+    struct output_debug_string_request output_debug_string_request;
+    struct continue_debug_event_request continue_debug_event_request;
+    struct debug_process_request debug_process_request;
+    struct read_process_memory_request read_process_memory_request;
+    struct write_process_memory_request write_process_memory_request;
+    struct create_key_request create_key_request;
+    struct open_key_request open_key_request;
+    struct delete_key_request delete_key_request;
+    struct enum_key_request enum_key_request;
+    struct set_key_value_request set_key_value_request;
+    struct get_key_value_request get_key_value_request;
+    struct enum_key_value_request enum_key_value_request;
+    struct delete_key_value_request delete_key_value_request;
+    struct load_registry_request load_registry_request;
+    struct save_registry_request save_registry_request;
+    struct save_registry_atexit_request save_registry_atexit_request;
+    struct set_registry_levels_request set_registry_levels_request;
+    struct create_timer_request create_timer_request;
+    struct open_timer_request open_timer_request;
+    struct set_timer_request set_timer_request;
+    struct cancel_timer_request cancel_timer_request;
+    struct get_thread_context_request get_thread_context_request;
+    struct set_thread_context_request set_thread_context_request;
+    struct get_selector_entry_request get_selector_entry_request;
+    struct add_atom_request add_atom_request;
+    struct delete_atom_request delete_atom_request;
+    struct find_atom_request find_atom_request;
+    struct get_atom_name_request get_atom_name_request;
+    struct init_atom_table_request init_atom_table_request;
+    struct get_msg_queue_request get_msg_queue_request;
+    struct set_queue_mask_request set_queue_mask_request;
+    struct get_queue_status_request get_queue_status_request;
+    struct wait_input_idle_request wait_input_idle_request;
+    struct send_message_request send_message_request;
+    struct get_message_request get_message_request;
+    struct reply_message_request reply_message_request;
+    struct get_message_reply_request get_message_reply_request;
+    struct set_win_timer_request set_win_timer_request;
+    struct kill_win_timer_request kill_win_timer_request;
+    struct create_serial_request create_serial_request;
+    struct get_serial_info_request get_serial_info_request;
+    struct set_serial_info_request set_serial_info_request;
+    struct create_async_request create_async_request;
+    struct create_named_pipe_request create_named_pipe_request;
+    struct open_named_pipe_request open_named_pipe_request;
+    struct connect_named_pipe_request connect_named_pipe_request;
+    struct wait_named_pipe_request wait_named_pipe_request;
+    struct disconnect_named_pipe_request disconnect_named_pipe_request;
+    struct get_named_pipe_info_request get_named_pipe_info_request;
+    struct create_window_request create_window_request;
+    struct link_window_request link_window_request;
+    struct destroy_window_request destroy_window_request;
+    struct set_window_owner_request set_window_owner_request;
+    struct get_window_info_request get_window_info_request;
+    struct set_window_info_request set_window_info_request;
+    struct get_window_parents_request get_window_parents_request;
+    struct get_window_children_request get_window_children_request;
+    struct get_window_tree_request get_window_tree_request;
+    struct set_window_rectangles_request set_window_rectangles_request;
+    struct get_window_rectangles_request get_window_rectangles_request;
+    struct get_window_text_request get_window_text_request;
+    struct set_window_text_request set_window_text_request;
+    struct inc_window_paint_count_request inc_window_paint_count_request;
+    struct get_windows_offset_request get_windows_offset_request;
+    struct set_window_property_request set_window_property_request;
+    struct remove_window_property_request remove_window_property_request;
+    struct get_window_property_request get_window_property_request;
+    struct get_window_properties_request get_window_properties_request;
+};
+union generic_reply
+{
+    struct request_max_size max_size;
+    struct reply_header reply_header;
+    struct new_process_reply new_process_reply;
+    struct get_new_process_info_reply get_new_process_info_reply;
+    struct new_thread_reply new_thread_reply;
+    struct boot_done_reply boot_done_reply;
+    struct init_process_reply init_process_reply;
+    struct init_process_done_reply init_process_done_reply;
+    struct init_thread_reply init_thread_reply;
+    struct terminate_process_reply terminate_process_reply;
+    struct terminate_thread_reply terminate_thread_reply;
+    struct get_process_info_reply get_process_info_reply;
+    struct set_process_info_reply set_process_info_reply;
+    struct get_thread_info_reply get_thread_info_reply;
+    struct set_thread_info_reply set_thread_info_reply;
+    struct suspend_thread_reply suspend_thread_reply;
+    struct resume_thread_reply resume_thread_reply;
+    struct load_dll_reply load_dll_reply;
+    struct unload_dll_reply unload_dll_reply;
+    struct queue_apc_reply queue_apc_reply;
+    struct get_apc_reply get_apc_reply;
+    struct close_handle_reply close_handle_reply;
+    struct set_handle_info_reply set_handle_info_reply;
+    struct dup_handle_reply dup_handle_reply;
+    struct open_process_reply open_process_reply;
+    struct select_reply select_reply;
+    struct create_event_reply create_event_reply;
+    struct event_op_reply event_op_reply;
+    struct open_event_reply open_event_reply;
+    struct create_mutex_reply create_mutex_reply;
+    struct release_mutex_reply release_mutex_reply;
+    struct open_mutex_reply open_mutex_reply;
+    struct create_semaphore_reply create_semaphore_reply;
+    struct release_semaphore_reply release_semaphore_reply;
+    struct open_semaphore_reply open_semaphore_reply;
+    struct create_file_reply create_file_reply;
+    struct alloc_file_handle_reply alloc_file_handle_reply;
+    struct get_handle_fd_reply get_handle_fd_reply;
+    struct set_file_pointer_reply set_file_pointer_reply;
+    struct truncate_file_reply truncate_file_reply;
+    struct set_file_time_reply set_file_time_reply;
+    struct flush_file_reply flush_file_reply;
+    struct get_file_info_reply get_file_info_reply;
+    struct lock_file_reply lock_file_reply;
+    struct unlock_file_reply unlock_file_reply;
+    struct create_pipe_reply create_pipe_reply;
+    struct create_socket_reply create_socket_reply;
+    struct accept_socket_reply accept_socket_reply;
+    struct set_socket_event_reply set_socket_event_reply;
+    struct get_socket_event_reply get_socket_event_reply;
+    struct enable_socket_event_reply enable_socket_event_reply;
+    struct alloc_console_reply alloc_console_reply;
+    struct free_console_reply free_console_reply;
+    struct get_console_renderer_events_reply get_console_renderer_events_reply;
+    struct open_console_reply open_console_reply;
+    struct get_console_mode_reply get_console_mode_reply;
+    struct set_console_mode_reply set_console_mode_reply;
+    struct set_console_input_info_reply set_console_input_info_reply;
+    struct get_console_input_info_reply get_console_input_info_reply;
+    struct append_console_input_history_reply append_console_input_history_reply;
+    struct get_console_input_history_reply get_console_input_history_reply;
+    struct create_console_output_reply create_console_output_reply;
+    struct set_console_output_info_reply set_console_output_info_reply;
+    struct get_console_output_info_reply get_console_output_info_reply;
+    struct write_console_input_reply write_console_input_reply;
+    struct read_console_input_reply read_console_input_reply;
+    struct write_console_output_reply write_console_output_reply;
+    struct fill_console_output_reply fill_console_output_reply;
+    struct read_console_output_reply read_console_output_reply;
+    struct move_console_output_reply move_console_output_reply;
+    struct create_change_notification_reply create_change_notification_reply;
+    struct create_mapping_reply create_mapping_reply;
+    struct open_mapping_reply open_mapping_reply;
+    struct get_mapping_info_reply get_mapping_info_reply;
+    struct create_device_reply create_device_reply;
+    struct create_snapshot_reply create_snapshot_reply;
+    struct next_process_reply next_process_reply;
+    struct next_thread_reply next_thread_reply;
+    struct next_module_reply next_module_reply;
+    struct wait_debug_event_reply wait_debug_event_reply;
+    struct queue_exception_event_reply queue_exception_event_reply;
+    struct get_exception_status_reply get_exception_status_reply;
+    struct output_debug_string_reply output_debug_string_reply;
+    struct continue_debug_event_reply continue_debug_event_reply;
+    struct debug_process_reply debug_process_reply;
+    struct read_process_memory_reply read_process_memory_reply;
+    struct write_process_memory_reply write_process_memory_reply;
+    struct create_key_reply create_key_reply;
+    struct open_key_reply open_key_reply;
+    struct delete_key_reply delete_key_reply;
+    struct enum_key_reply enum_key_reply;
+    struct set_key_value_reply set_key_value_reply;
+    struct get_key_value_reply get_key_value_reply;
+    struct enum_key_value_reply enum_key_value_reply;
+    struct delete_key_value_reply delete_key_value_reply;
+    struct load_registry_reply load_registry_reply;
+    struct save_registry_reply save_registry_reply;
+    struct save_registry_atexit_reply save_registry_atexit_reply;
+    struct set_registry_levels_reply set_registry_levels_reply;
+    struct create_timer_reply create_timer_reply;
+    struct open_timer_reply open_timer_reply;
+    struct set_timer_reply set_timer_reply;
+    struct cancel_timer_reply cancel_timer_reply;
+    struct get_thread_context_reply get_thread_context_reply;
+    struct set_thread_context_reply set_thread_context_reply;
+    struct get_selector_entry_reply get_selector_entry_reply;
+    struct add_atom_reply add_atom_reply;
+    struct delete_atom_reply delete_atom_reply;
+    struct find_atom_reply find_atom_reply;
+    struct get_atom_name_reply get_atom_name_reply;
+    struct init_atom_table_reply init_atom_table_reply;
+    struct get_msg_queue_reply get_msg_queue_reply;
+    struct set_queue_mask_reply set_queue_mask_reply;
+    struct get_queue_status_reply get_queue_status_reply;
+    struct wait_input_idle_reply wait_input_idle_reply;
+    struct send_message_reply send_message_reply;
+    struct get_message_reply get_message_reply;
+    struct reply_message_reply reply_message_reply;
+    struct get_message_reply_reply get_message_reply_reply;
+    struct set_win_timer_reply set_win_timer_reply;
+    struct kill_win_timer_reply kill_win_timer_reply;
+    struct create_serial_reply create_serial_reply;
+    struct get_serial_info_reply get_serial_info_reply;
+    struct set_serial_info_reply set_serial_info_reply;
+    struct create_async_reply create_async_reply;
+    struct create_named_pipe_reply create_named_pipe_reply;
+    struct open_named_pipe_reply open_named_pipe_reply;
+    struct connect_named_pipe_reply connect_named_pipe_reply;
+    struct wait_named_pipe_reply wait_named_pipe_reply;
+    struct disconnect_named_pipe_reply disconnect_named_pipe_reply;
+    struct get_named_pipe_info_reply get_named_pipe_info_reply;
+    struct create_window_reply create_window_reply;
+    struct link_window_reply link_window_reply;
+    struct destroy_window_reply destroy_window_reply;
+    struct set_window_owner_reply set_window_owner_reply;
+    struct get_window_info_reply get_window_info_reply;
+    struct set_window_info_reply set_window_info_reply;
+    struct get_window_parents_reply get_window_parents_reply;
+    struct get_window_children_reply get_window_children_reply;
+    struct get_window_tree_reply get_window_tree_reply;
+    struct set_window_rectangles_reply set_window_rectangles_reply;
+    struct get_window_rectangles_reply get_window_rectangles_reply;
+    struct get_window_text_reply get_window_text_reply;
+    struct set_window_text_reply set_window_text_reply;
+    struct inc_window_paint_count_reply inc_window_paint_count_reply;
+    struct get_windows_offset_reply get_windows_offset_reply;
+    struct set_window_property_reply set_window_property_reply;
+    struct remove_window_property_reply remove_window_property_reply;
+    struct get_window_property_reply get_window_property_reply;
+    struct get_window_properties_reply get_window_properties_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 65
+#define SERVER_PROTOCOL_VERSION 66
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/loader/module.c b/loader/module.c
index fa6fc0f..c507a4c 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -1693,7 +1693,7 @@
         SERVER_START_REQ( unload_dll )
         {
             req->base = (void *)wm->module;
-            SERVER_CALL();
+            wine_server_call( req );
         }
         SERVER_END_REQ;
         MODULE_FlushModrefs();
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 52629b7..6136a40 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -681,7 +681,7 @@
             req->dbg_offset = nt->FileHeader.PointerToSymbolTable;
             req->dbg_size   = nt->FileHeader.NumberOfSymbols;
             req->name       = &wm->filename;
-            SERVER_CALL();
+            wine_server_call( req );
         }
         SERVER_END_REQ;
     }
diff --git a/memory/atom.c b/memory/atom.c
index ef2feb4..033eb4c 100644
--- a/memory/atom.c
+++ b/memory/atom.c
@@ -409,7 +409,7 @@
     SERVER_START_REQ( init_atom_table )
     {
         req->entries = entries;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -421,19 +421,21 @@
     ATOM atom = 0;
     if (!ATOM_IsIntAtomA( str, &atom ))
     {
-        DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), NULL, 0 );
-        if (len > MAX_ATOM_LEN)
+        WCHAR buffer[MAX_ATOM_LEN];
+
+        DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
+        if (!len)
         {
             SetLastError( ERROR_INVALID_PARAMETER );
             return 0;
         }
-        SERVER_START_VAR_REQ( add_atom, len * sizeof(WCHAR) )
+        SERVER_START_REQ( add_atom )
         {
-            MultiByteToWideChar( CP_ACP, 0, str, strlen(str), server_data_ptr(req), len );
+            wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
             req->local = local;
-            if (!SERVER_CALL_ERR()) atom = req->atom;
+            if (!wine_server_call_err(req)) atom = reply->atom;
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
     }
     TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
     return atom;
@@ -482,13 +484,13 @@
             SetLastError( ERROR_INVALID_PARAMETER );
             return 0;
         }
-        SERVER_START_VAR_REQ( add_atom, len * sizeof(WCHAR) )
+        SERVER_START_REQ( add_atom )
         {
-            memcpy( server_data_ptr(req), str, len * sizeof(WCHAR) );
             req->local = local;
-            if (!SERVER_CALL_ERR()) atom = req->atom;
+            wine_server_add_data( req, str, len * sizeof(WCHAR) );
+            if (!wine_server_call_err(req)) atom = reply->atom;
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
     }
     TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
     return atom;
@@ -523,7 +525,7 @@
         {
             req->atom = atom;
             req->local = local;
-            if (!SERVER_CALL_ERR()) atom = 0;
+            if (!wine_server_call_err( req )) atom = 0;
         }
         SERVER_END_REQ;
     }
@@ -566,19 +568,21 @@
     ATOM atom = 0;
     if (!ATOM_IsIntAtomA( str, &atom ))
     {
-        DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), NULL, 0 );
-        if (len > MAX_ATOM_LEN)
+        WCHAR buffer[MAX_ATOM_LEN];
+
+        DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
+        if (!len)
         {
             SetLastError( ERROR_INVALID_PARAMETER );
             return 0;
         }
-        SERVER_START_VAR_REQ( find_atom, len * sizeof(WCHAR) )
+        SERVER_START_REQ( find_atom )
         {
-            MultiByteToWideChar( CP_ACP, 0, str, strlen(str), server_data_ptr(req), len );
             req->local = local;
-            if (!SERVER_CALL_ERR()) atom = req->atom;
+            wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
+            if (!wine_server_call_err(req)) atom = reply->atom;
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
     }
     TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_a(str), atom );
     return atom;
@@ -626,13 +630,13 @@
             SetLastError( ERROR_INVALID_PARAMETER );
             return 0;
         }
-        SERVER_START_VAR_REQ( find_atom, len * sizeof(WCHAR) )
+        SERVER_START_REQ( find_atom )
         {
-            memcpy( server_data_ptr(req), str, len * sizeof(WCHAR) );
+            wine_server_add_data( req, str, len * sizeof(WCHAR) );
             req->local = local;
-            if (!SERVER_CALL_ERR()) atom = req->atom;
+            if (!wine_server_call_err( req )) atom = reply->atom;
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
     }
     TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugres_w(str), atom );
     return atom;
@@ -679,21 +683,24 @@
     }
     else
     {
+        WCHAR full_name[MAX_ATOM_LEN];
+
         len = 0;
-        SERVER_START_VAR_REQ( get_atom_name, MAX_ATOM_LEN * sizeof(WCHAR) )
+        SERVER_START_REQ( get_atom_name )
         {
             req->atom = atom;
             req->local = local;
-            if (!SERVER_CALL_ERR())
+            wine_server_set_reply( req, full_name, sizeof(full_name) );
+            if (!wine_server_call_err( req ))
             {
-                len = WideCharToMultiByte( CP_ACP, 0, server_data_ptr(req),
-                                           server_data_size(req) / sizeof(WCHAR),
+                len = WideCharToMultiByte( CP_ACP, 0, full_name,
+                                           wine_server_reply_size(reply) / sizeof(WCHAR),
                                            buffer, count - 1, NULL, NULL );
                 if (!len) len = count; /* overflow */
                 else buffer[len] = 0;
             }
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
     }
 
     if (len && count <= len)
@@ -765,20 +772,23 @@
     }
     else
     {
+        WCHAR full_name[MAX_ATOM_LEN];
+
         len = 0;
-        SERVER_START_VAR_REQ( get_atom_name, MAX_ATOM_LEN * sizeof(WCHAR) )
+        SERVER_START_REQ( get_atom_name )
         {
             req->atom = atom;
             req->local = local;
-            if (!SERVER_CALL_ERR())
+            wine_server_set_reply( req, full_name, sizeof(full_name) );
+            if (!wine_server_call_err( req ))
             {
-                len = server_data_size(req) / sizeof(WCHAR);
+                len = wine_server_reply_size(reply) / sizeof(WCHAR);
                 if (count > len) count = len + 1;
-                memcpy( buffer, server_data_ptr(req), (count-1) * sizeof(WCHAR) );
+                memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) );
                 buffer[count-1] = 0;
             }
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
         if (!len) return 0;
     }
     if (count <= len)
diff --git a/memory/registry.c b/memory/registry.c
index 5aecc07..bef72d8 100644
--- a/memory/registry.c
+++ b/memory/registry.c
@@ -606,6 +606,7 @@
 LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
 {
     HANDLE file;
+    WCHAR buffer[MAX_PATH];
     DWORD ret, len, err = GetLastError();
 
     TRACE( "(%x,%s,%s)\n", hkey, debugstr_a(subkey), debugstr_a(filename) );
@@ -613,8 +614,8 @@
     if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
     if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
 
-    len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), NULL, 0 ) * sizeof(WCHAR);
-    if (len > MAX_PATH*sizeof(WCHAR)) return ERROR_INVALID_PARAMETER;
+    if (!(len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), buffer, MAX_PATH )))
+        return ERROR_INVALID_PARAMETER;
 
     if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
                              FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE)
@@ -623,15 +624,14 @@
         goto done;
     }
 
-    SERVER_START_VAR_REQ( load_registry, len )
+    SERVER_START_REQ( load_registry )
     {
         req->hkey  = hkey;
         req->file  = file;
-        MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey),
-                             server_data_ptr(req), len/sizeof(WCHAR) );
-        ret = RtlNtStatusToDosError( SERVER_CALL() );
+        wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
+        ret = RtlNtStatusToDosError( wine_server_call(req) );
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     CloseHandle( file );
 
  done:
@@ -679,7 +679,7 @@
     {
         req->hkey = hkey;
         req->file = handle;
-        ret = RtlNtStatusToDosError( SERVER_CALL() );
+        ret = RtlNtStatusToDosError( wine_server_call( req ) );
     }
     SERVER_END_REQ;
 
diff --git a/memory/selector.c b/memory/selector.c
index c3f9d2a..c3ce313 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -594,18 +594,18 @@
     {
         req->handle = hthread;
         req->entry = sel >> __AHSHIFT;
-        if ((ret = !SERVER_CALL_ERR()))
+        if ((ret = !wine_server_call_err( req )))
         {
-            if (!(req->flags & WINE_LDT_FLAGS_ALLOCATED))
+            if (!(reply->flags & WINE_LDT_FLAGS_ALLOCATED))
             {
                 SetLastError( ERROR_MR_MID_NOT_FOUND );  /* sic */
                 ret = FALSE;
             }
             else
             {
-                wine_ldt_set_base( ldtent, (void *)req->base );
-                wine_ldt_set_limit( ldtent, req->limit );
-                wine_ldt_set_flags( ldtent, req->flags );
+                wine_ldt_set_base( ldtent, (void *)reply->base );
+                wine_ldt_set_limit( ldtent, reply->limit );
+                wine_ldt_set_flags( ldtent, reply->flags );
             }
         }
     }
diff --git a/memory/virtual.c b/memory/virtual.c
index 2234674..f52aab5 100644
--- a/memory/virtual.c
+++ b/memory/virtual.c
@@ -1360,50 +1360,16 @@
                 DWORD size_low,  /* [in] Low-order 32 bits of object size */
                 LPCSTR name      /* [in] Name of file-mapping object */ )
 {
-    HANDLE ret;
-    BYTE vprot;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
+    WCHAR buffer[MAX_PATH];
 
-    /* Check parameters */
+    if (!name) return CreateFileMappingW( hFile, sa, protect, size_high, size_low, NULL );
 
-    TRACE("(%x,%p,%08lx,%08lx%08lx,%s)\n",
-          hFile, sa, protect, size_high, size_low, debugstr_a(name) );
-
-    if (len > MAX_PATH)
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    vprot = VIRTUAL_GetProt( protect );
-    if (protect & SEC_RESERVE)
-    {
-        if (hFile != INVALID_HANDLE_VALUE)
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            return 0;
-        }
-    }
-    else vprot |= VPROT_COMMITTED;
-    if (protect & SEC_NOCACHE) vprot |= VPROT_NOCACHE;
-    if (protect & SEC_IMAGE) vprot |= VPROT_IMAGE;
-
-    /* Create the server object */
-
-    if (hFile == INVALID_HANDLE_VALUE) hFile = 0;
-    SERVER_START_VAR_REQ( create_mapping, len * sizeof(WCHAR) )
-    {
-        req->file_handle = hFile;
-        req->size_high   = size_high;
-        req->size_low    = size_low;
-        req->protect     = vprot;
-        req->inherit     = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return CreateFileMappingW( hFile, sa, protect, size_high, size_low, buffer );
 }
 
 
@@ -1446,19 +1412,19 @@
     /* Create the server object */
 
     if (hFile == INVALID_HANDLE_VALUE) hFile = 0;
-    SERVER_START_VAR_REQ( create_mapping, len * sizeof(WCHAR) )
+    SERVER_START_REQ( create_mapping )
     {
         req->file_handle = hFile;
         req->size_high   = size_high;
         req->size_low    = size_low;
         req->protect     = vprot;
         req->inherit     = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -1476,23 +1442,16 @@
                 BOOL inherit, /* [in] Inherit flag */
                 LPCSTR name )   /* [in] Name of file-mapping object */
 {
-    HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
-    if (len > MAX_PATH)
+    WCHAR buffer[MAX_PATH];
+
+    if (!name) return OpenFileMappingW( access, inherit, NULL );
+
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_mapping, len * sizeof(WCHAR) )
-    {
-        req->access  = access;
-        req->inherit = inherit;
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return OpenFileMappingW( access, inherit, buffer );
 }
 
 
@@ -1504,20 +1463,20 @@
 {
     HANDLE ret;
     DWORD len = name ? strlenW(name) : 0;
-    if (len > MAX_PATH)
+    if (len >= MAX_PATH)
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_mapping, len * sizeof(WCHAR) )
+    SERVER_START_REQ( open_mapping )
     {
         req->access  = access;
         req->inherit = inherit;
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -1580,16 +1539,16 @@
     SERVER_START_REQ( get_mapping_info )
     {
         req->handle = handle;
-        res = SERVER_CALL_ERR();
-        prot        = req->protect;
-        base        = req->base;
-        size_low    = req->size_low;
-        size_high   = req->size_high;
-        header_size = req->header_size;
-        shared_file = req->shared_file;
-        shared_size = req->shared_size;
-        removable   = (req->drive_type == DRIVE_REMOVABLE ||
-                       req->drive_type == DRIVE_CDROM);
+        res = wine_server_call_err( req );
+        prot        = reply->protect;
+        base        = reply->base;
+        size_low    = reply->size_low;
+        size_high   = reply->size_high;
+        header_size = reply->header_size;
+        shared_file = reply->shared_file;
+        shared_size = reply->shared_size;
+        removable   = (reply->drive_type == DRIVE_REMOVABLE ||
+                       reply->drive_type == DRIVE_CDROM);
     }
     SERVER_END_REQ;
     if (res) goto error;
diff --git a/misc/options.c b/misc/options.c
index dad6779..639c9e6 100644
--- a/misc/options.c
+++ b/misc/options.c
@@ -38,10 +38,6 @@
 
 static char *inherit_str;  /* options to pass to child processes */
 
-static int app_argc;       /* argc/argv to pass to application */
-static char **app_argv;
-static WCHAR **app_wargv;
-
 static void out_of_memory(void) WINE_NORETURN;
 static void out_of_memory(void)
 {
@@ -340,55 +336,4 @@
             OPTIONS_Usage();
         }
     }
-
-    /* count the resulting arguments */
-    app_argv = argv;
-    app_argc = 0;
-    while (argv[app_argc]) app_argc++;
-}
-
-
-/***********************************************************************
- *              __wine_get_main_args (NTDLL.@)
- *
- * Return the argc/argv that the application should see.
- * Used by the startup code generated in the .spec.c file.
- */
-int __wine_get_main_args( char ***argv )
-{
-    *argv = app_argv;
-    return app_argc;
-}
-
-
-/***********************************************************************
- *              __wine_get_wmain_args (NTDLL.@)
- *
- * Same as __wine_get_main_args but for Unicode.
- */
-int __wine_get_wmain_args( WCHAR ***argv )
-{
-    if (!app_wargv)
-    {
-        int i;
-        WCHAR *p;
-        DWORD total = 0;
-
-        for (i = 0; i < app_argc; i++)
-            total += MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, NULL, 0 );
-
-        app_wargv = HeapAlloc( GetProcessHeap(), 0,
-                               total * sizeof(WCHAR) + (app_argc + 1) * sizeof(*app_wargv) );
-        p = (WCHAR *)(app_wargv + app_argc + 1);
-        for (i = 0; i < app_argc; i++)
-        {
-            DWORD len = MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, p, total );
-            app_wargv[i] = p;
-            p += len;
-            total -= len;
-        }
-        app_wargv[app_argc] = NULL;
-    }
-    *argv = app_wargv;
-    return app_argc;
 }
diff --git a/misc/registry.c b/misc/registry.c
index 818cd65..4cfed5d 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -1004,7 +1004,7 @@
 	req->current = level;
 	req->saving  = saving;
         req->period  = period;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 }
@@ -1013,19 +1013,15 @@
 static void _save_at_exit(HKEY hkey,LPCSTR path)
 {
     LPCSTR confdir = get_config_dir();
-    size_t len = strlen(confdir) + strlen(path) + 2;
 
-    if (len > REQUEST_MAX_VAR_SIZE) {
-        ERR( "config dir '%s' too long\n", confdir );
-        return;
-    }
-    SERVER_START_VAR_REQ( save_registry_atexit, len )
+    SERVER_START_REQ( save_registry_atexit )
     {
-        sprintf( server_data_ptr(req), "%s/%s", confdir, path );
         req->hkey = hkey;
-        SERVER_CALL();
+        wine_server_add_data( req, confdir, strlen(confdir) );
+        wine_server_add_data( req, path, strlen(path)+1 );
+        wine_server_call( req );
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
 }
 
 /* configure save files and start the periodic saving timer [Internal] */
@@ -1042,9 +1038,9 @@
 
     if (PROFILE_GetWineIniBool("registry","WritetoHomeRegistryFiles",1))
     {
-        _save_at_exit(HKEY_CURRENT_USER,SAVE_LOCAL_REGBRANCH_CURRENT_USER );
-        _save_at_exit(HKEY_LOCAL_MACHINE,SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
-        _save_at_exit(hkey_users_default,SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
+        _save_at_exit(HKEY_CURRENT_USER,"/" SAVE_LOCAL_REGBRANCH_CURRENT_USER );
+        _save_at_exit(HKEY_LOCAL_MACHINE,"/" SAVE_LOCAL_REGBRANCH_LOCAL_MACHINE);
+        _save_at_exit(hkey_users_default,"/" SAVE_LOCAL_REGBRANCH_USER_DEFAULT);
     }
 
 }
@@ -1190,7 +1186,7 @@
                 {
                     req->hkey    = hkey;
                     req->file    = file;
-                    SERVER_CALL();
+                    wine_server_call( req );
                 }
                 SERVER_END_REQ;
                 CloseHandle( file );
diff --git a/msdos/vga.c b/msdos/vga.c
index ae64af2..8175fa1 100644
--- a/msdos/vga.c
+++ b/msdos/vga.c
@@ -352,7 +352,8 @@
                   ch[X].Attributes = *dat++;
               }
               dest.Left=0; dest.Right=Width+1;
-              WriteConsoleOutputA(con, ch, siz, off, &dest);
+              FIXME("output commented out for now, should be moved to winedos.dll\n");
+              /*WriteConsoleOutputA(con, ch, siz, off, &dest);*/
           }
         }
         vga_refresh=1;
diff --git a/programs/wineconsole/wineconsole.c b/programs/wineconsole/wineconsole.c
index 44f400b..879c7a8 100644
--- a/programs/wineconsole/wineconsole.c
+++ b/programs/wineconsole/wineconsole.c
@@ -5,7 +5,8 @@
  */
 
 #include <stdio.h>
-#include <wine/server.h>
+#include "wine/server.h"
+#include "wine/unicode.h"
 #include "winecon_private.h"
 
 static int trace_level = 1;
@@ -35,34 +36,20 @@
  *
  * updates the local copy of cells (band to update)
  */
-void	WINECON_FetchCells(struct inner_data* data, int upd_tp, int upd_bm)
+void WINECON_FetchCells(struct inner_data* data, int upd_tp, int upd_bm)
 {
-    int		step;
-    int		j, nr;
-
-    step = REQUEST_MAX_VAR_SIZE / (data->sb_width * 4);
-
-    for (j = upd_tp; j <= upd_bm; j += step)
+    SERVER_START_REQ( read_console_output )
     {
-	nr = min(step, upd_bm - j + 1);
-	SERVER_START_VAR_REQ( read_console_output, 4 * nr * data->sb_width )
-	{
-	    req->handle       = (handle_t)data->hConOut;
-	    req->x            = 0;
-	    req->y            = j;
-	    req->w            = data->sb_width;
-	    req->h            = nr;
-	    if (!SERVER_CALL_ERR())
-	    {
-		if (data->sb_width != req->eff_w || nr != req->eff_h) 
-		    Trace(0, "pb here... wrong eff_w %d/%d or eff_h %d/%d\n", 
-			  req->eff_w, data->sb_width, req->eff_h, nr);
-		memcpy(&data->cells[j * data->sb_width], server_data_ptr(req), 
-		       4 * nr * data->sb_width);
-	    }
-	}
-	SERVER_END_VAR_REQ;
+        req->handle = (handle_t)data->hConOut;
+        req->x      = 0;
+        req->y      = upd_tp;
+        req->mode   = CHAR_INFO_MODE_TEXTATTR;
+        req->wrap   = TRUE;
+        wine_server_set_reply( req, &data->cells[upd_tp * data->sb_width],
+                               (upd_bm-upd_tp+1) * data->sb_width * sizeof(CHAR_INFO) );
+        wine_server_call( req );
     }
+    SERVER_END_REQ;
     data->fnRefresh(data, upd_tp, upd_bm);
 }
 
@@ -71,19 +58,17 @@
  *
  * Inform server that visible window on sb has changed
  */
-void	WINECON_NotifyWindowChange(struct inner_data* data)
+void WINECON_NotifyWindowChange(struct inner_data* data)
 {
     SERVER_START_REQ( set_console_output_info )
     {
-	req->handle       = (handle_t)data->hConOut;
-	req->win_left     = data->win_pos.X;
-	req->win_top      = data->win_pos.Y;
-	req->win_right    = data->win_pos.X + data->win_width - 1;
-	req->win_bottom   = data->win_pos.Y + data->win_height - 1;
-	req->mask         = SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW;
-	if (!SERVER_CALL_ERR())
-	{
-	}
+        req->handle       = (handle_t)data->hConOut;
+        req->win_left     = data->win_pos.X;
+        req->win_top      = data->win_pos.Y;
+        req->win_right    = data->win_pos.X + data->win_width - 1;
+        req->win_bottom   = data->win_pos.Y + data->win_height - 1;
+        req->mask         = SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW;
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 }
@@ -100,7 +85,7 @@
     SERVER_START_REQ(get_console_input_info)
     {
 	req->handle = (handle_t)hConIn;
-	if (!SERVER_CALL_ERR()) ret = req->history_size;
+	if (!wine_server_call_err( req )) ret = reply->history_size;
     }
     SERVER_END_REQ;
     return ret;
@@ -120,7 +105,7 @@
 	req->handle = (handle_t)hConIn;
 	req->mask = SET_CONSOLE_INPUT_INFO_HISTORY_SIZE;
 	req->history_size = size;
-	ret = !SERVER_CALL_ERR();
+	ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -139,7 +124,7 @@
     SERVER_START_REQ(get_console_input_info)
     {
 	req->handle = (handle_t)hConIn;
-	if (!SERVER_CALL_ERR()) ret = req->history_mode;
+	if (!wine_server_call_err( req )) ret = reply->history_mode;
     }
     SERVER_END_REQ;
     return ret;
@@ -159,7 +144,7 @@
 	req->handle = (handle_t)hConIn;
 	req->mask = SET_CONSOLE_INPUT_INFO_HISTORY_MODE;
 	req->history_mode = mode;
-	ret = !SERVER_CALL_ERR();
+	ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -170,22 +155,23 @@
  *
  *
  */
-BOOL	WINECON_GetConsoleTitle(HANDLE hConIn, WCHAR* buffer, size_t len)
+BOOL WINECON_GetConsoleTitle(HANDLE hConIn, WCHAR* buffer, size_t len)
 {
-    BOOL	ret;
-    DWORD 	size = 0;
+    BOOL ret;
 
-    SERVER_START_VAR_REQ(get_console_input_info, sizeof(buffer))
+    if (len < sizeof(WCHAR)) return FALSE;
+
+    SERVER_START_REQ( get_console_input_info )
     {
-	req->handle = (handle_t)hConIn;
-        if ((ret = !SERVER_CALL_ERR()))
+        req->handle = (handle_t)hConIn;
+        wine_server_set_reply( req, buffer, len - sizeof(WCHAR) );
+        if ((ret = !wine_server_call_err( req )))
         {
-            size = min(len - sizeof(WCHAR), server_data_size(req));
-            memcpy(buffer, server_data_ptr(req), size);
-            buffer[size / sizeof(WCHAR)] = 0;
+            len = wine_server_reply_size( reply );
+            buffer[len / sizeof(WCHAR)] = 0;
         }
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -200,18 +186,14 @@
     int	i, num;
     HANDLE h;
 
-    SERVER_START_VAR_REQ( get_console_renderer_events, sizeof(evts) )
+    SERVER_START_REQ( get_console_renderer_events )
     {
-	req->handle       = (handle_t)data->hSynchro;
-	if (!SERVER_CALL_ERR())
-	{
-	    num = server_data_size(req);
-	    memcpy(evts, server_data_ptr(req), num);
-	    num /= sizeof(evts[0]);
-	}
-	else num = 0;
+        wine_server_set_reply( req, evts, sizeof(evts) );
+        req->handle = (handle_t)data->hSynchro;
+        if (!wine_server_call_err( req )) num = wine_server_reply_size(reply) / sizeof(evts[0]);
+        else num = 0;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     if (!num) {Trace(0, "hmm renderer signaled but no events available\n"); return 1;}
     
     /* FIXME: should do some event compression here (cursor pos, update) */
@@ -230,7 +212,7 @@
 		req->access  = GENERIC_READ | GENERIC_WRITE;
 		req->share   = FILE_SHARE_READ | FILE_SHARE_WRITE;
 		req->inherit = FALSE;
-		h = SERVER_CALL_ERR() ? 0 : (HANDLE)req->handle;
+		h = wine_server_call_err( req ) ? 0 : (HANDLE)reply->handle;
 	    }
 	    SERVER_END_REQ;
 	    Trace(1, " active(%d)", (int)h);
@@ -340,7 +322,6 @@
     struct inner_data*	data = NULL;
     DWORD		ret;
     WCHAR		szTitle[] = {'W','i','n','e',' ','c','o','n','s','o','l','e',0};
-    size_t		len;
 
     data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
     if (!data) return 0;
@@ -355,24 +336,21 @@
         req->access  = GENERIC_READ | GENERIC_WRITE;
         req->inherit = FALSE;
 	req->pid     = pid;
-        ret = !SERVER_CALL_ERR();
-        data->hConIn = (HANDLE)req->handle_in;
-	data->hSynchro = (HANDLE)req->event;
+        ret = !wine_server_call_err( req );
+        data->hConIn = (HANDLE)reply->handle_in;
+	data->hSynchro = (HANDLE)reply->event;
     }
     SERVER_END_REQ;
     if (!ret) goto error;
 
-    len = lstrlenW(szTitle) * sizeof(WCHAR);
-    len = min(len, REQUEST_MAX_VAR_SIZE);
-
-    SERVER_START_VAR_REQ(set_console_input_info, len)
+    SERVER_START_REQ( set_console_input_info )
     {
-	req->handle = (handle_t)data->hConIn;
+        req->handle = (handle_t)data->hConIn;
         req->mask = SET_CONSOLE_INPUT_INFO_TITLE;
-        memcpy(server_data_ptr(req), szTitle, len);
-        ret = !SERVER_CALL_ERR();
+        wine_server_add_data( req, szTitle, strlenW(szTitle) * sizeof(WCHAR) );
+        ret = !wine_server_call_err( req );
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
 
     if (ret) 
     {    
@@ -382,7 +360,7 @@
 	    req->access    = GENERIC_WRITE|GENERIC_READ;
 	    req->share     = FILE_SHARE_READ|FILE_SHARE_WRITE;
 	    req->inherit   = FALSE;
-	    data->hConOut  = (HANDLE)(SERVER_CALL_ERR() ? 0 : req->handle_out);
+	    data->hConOut  = (HANDLE)(wine_server_call_err( req ) ? 0 : reply->handle_out);
 	}
 	SERVER_END_REQ;
 	if (data->hConOut) return data;
diff --git a/scheduler/client.c b/scheduler/client.c
index a8cb4dd..9fe5fd5 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -114,68 +114,59 @@
 
 
 /***********************************************************************
- *           __wine_server_exception_handler (NTDLL.@)
- */
-DWORD __wine_server_exception_handler( PEXCEPTION_RECORD record, EXCEPTION_FRAME *frame,
-                                       CONTEXT *context, EXCEPTION_FRAME **pdispatcher )
-{
-    struct __server_exception_frame *server_frame = (struct __server_exception_frame *)frame;
-    if ((record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
-        NtCurrentTeb()->buffer_pos = server_frame->buffer_pos;
-    return ExceptionContinueSearch;
-}
-
-
-/***********************************************************************
- *           wine_server_alloc_req (NTDLL.@)
- */
-void wine_server_alloc_req( union generic_request *req, size_t size )
-{
-    unsigned int pos = NtCurrentTeb()->buffer_pos;
-
-    assert( size <= REQUEST_MAX_VAR_SIZE );
-
-    if (pos + size > NtCurrentTeb()->buffer_size)
-        server_protocol_error( "buffer overflow %d bytes\n",
-                               pos + size - NtCurrentTeb()->buffer_pos );
-
-    NtCurrentTeb()->buffer_pos = pos + size;
-    req->header.var_offset = pos;
-    req->header.var_size = size;
-}
-
-
-/***********************************************************************
  *           send_request
  *
  * Send a request to the server.
  */
-static void send_request( union generic_request *request )
+static void send_request( const struct __server_request_info *req )
 {
-    int ret;
+    int i, ret;
 
-    if ((ret = write( NtCurrentTeb()->request_fd, request, sizeof(*request) )) == sizeof(*request))
-        return;
+    if (!req->u.req.request_header.request_size)
+    {
+        if ((ret = write( NtCurrentTeb()->request_fd, &req->u.req,
+                          sizeof(req->u.req) )) == sizeof(req->u.req)) return;
+
+    }
+    else
+    {
+        struct iovec vec[__SERVER_MAX_DATA+1];
+
+        vec[0].iov_base = (void *)&req->u.req;
+        vec[0].iov_len = sizeof(req->u.req);
+        for (i = 0; i < req->data_count; i++)
+        {
+            vec[i+1].iov_base = (void *)req->data[i].ptr;
+            vec[i+1].iov_len = req->data[i].size;
+        }
+        if ((ret = writev( NtCurrentTeb()->request_fd, vec, i+1 )) ==
+            req->u.req.request_header.request_size + sizeof(req->u.req)) return;
+    }
+
     if (ret >= 0) server_protocol_error( "partial write %d\n", ret );
     if (errno == EPIPE) SYSDEPS_ExitThread(0);
     server_protocol_perror( "sendmsg" );
 }
 
+
 /***********************************************************************
- *           wait_reply
+ *           read_reply_data
  *
- * Wait for a reply from the server.
+ * Read data from the reply buffer; helper for wait_reply.
  */
-static void wait_reply( union generic_request *req )
+static void read_reply_data( void *buffer, size_t size )
 {
     int ret;
 
     for (;;)
     {
-        if ((ret = read( NtCurrentTeb()->reply_fd, req, sizeof(*req) )) == sizeof(*req))
-            return;
+        if ((ret = read( NtCurrentTeb()->reply_fd, buffer, size )) > 0)
+        {
+            if (!(size -= ret)) return;
+            buffer = (char *)buffer + ret;
+            continue;
+        }
         if (!ret) break;
-        if (ret > 0) server_protocol_error( "partial read %d\n", ret );
         if (errno == EINTR) continue;
         if (errno == EPIPE) break;
         server_protocol_perror("read");
@@ -186,20 +177,34 @@
 
 
 /***********************************************************************
+ *           wait_reply
+ *
+ * Wait for a reply from the server.
+ */
+inline static void wait_reply( struct __server_request_info *req )
+{
+    read_reply_data( &req->u.reply, sizeof(req->u.reply) );
+    if (req->u.reply.reply_header.reply_size)
+        read_reply_data( req->reply_data, req->u.reply.reply_header.reply_size );
+}
+
+
+/***********************************************************************
  *           wine_server_call (NTDLL.@)
  *
  * Perform a server call.
  */
-unsigned int wine_server_call( union generic_request *req, size_t size )
+unsigned int wine_server_call( void *req_ptr )
 {
+    struct __server_request_info * const req = req_ptr;
     sigset_t old_set;
 
-    memset( (char *)req + size, 0, sizeof(*req) - size );
+    memset( (char *)&req->u.req + req->size, 0, sizeof(req->u.req) - req->size );
     sigprocmask( SIG_BLOCK, &block_set, &old_set );
     send_request( req );
     wait_reply( req );
     sigprocmask( SIG_SETMASK, &old_set, NULL );
-    return req->header.error;
+    return req->u.reply.reply_header.error;
 }
 
 
@@ -331,13 +336,13 @@
         req->flags  = 0;
         req->mask   = 0;
         req->fd     = fd;
-        if (!SERVER_CALL())
+        if (!wine_server_call( req ))
         {
-            if (req->cur_fd != fd)
+            if (reply->cur_fd != fd)
             {
                 /* someone was here before us */
                 close( fd );
-                fd = req->cur_fd;
+                fd = reply->cur_fd;
             }
         }
         else
@@ -597,47 +602,6 @@
 
 
 /***********************************************************************
- *           set_request_buffer
- */
-inline static void set_request_buffer(void)
-{
-    char *name;
-    int fd, ret;
-    unsigned int offset, size;
-
-    /* create a temporary file */
-    do
-    {
-        if (!(name = tmpnam(NULL))) server_protocol_perror( "tmpnam" );
-        fd = open( name, O_CREAT | O_EXCL | O_RDWR, 0600 );
-    } while ((fd == -1) && (errno == EEXIST));
-
-    if (fd == -1) server_protocol_perror( "create" );
-    unlink( name );
-
-    wine_server_send_fd( fd );
-
-    SERVER_START_REQ( set_thread_buffer )
-    {
-        req->fd = fd;
-        ret = SERVER_CALL();
-        offset = req->offset;
-        size = req->size;
-    }
-    SERVER_END_REQ;
-    if (ret) server_protocol_error( "set_thread_buffer failed with status %x\n", ret );
-
-    if ((NtCurrentTeb()->buffer = mmap( 0, size, PROT_READ | PROT_WRITE,
-                                        MAP_SHARED, fd, offset )) == (void*)-1)
-        server_protocol_perror( "mmap" );
-
-    close( fd );
-    NtCurrentTeb()->buffer_pos  = 0;
-    NtCurrentTeb()->buffer_size = size;
-}
-
-
-/***********************************************************************
  *           CLIENT_InitThread
  *
  * Send an init thread request. Return 0 if OK.
@@ -670,11 +634,11 @@
         req->entry       = teb->entry_point;
         req->reply_fd    = reply_pipe[1];
         req->wait_fd     = teb->wait_fd[1];
-        ret = SERVER_CALL();
-        teb->pid = req->pid;
-        teb->tid = req->tid;
-        version  = req->version;
-        if (req->boot) boot_thread_id = teb->tid;
+        ret = wine_server_call( req );
+        teb->pid = reply->pid;
+        teb->tid = reply->tid;
+        version  = reply->version;
+        if (reply->boot) boot_thread_id = teb->tid;
         else if (boot_thread_id == teb->tid) boot_thread_id = 0;
         close( reply_pipe[1] );
     }
@@ -688,7 +652,6 @@
                                "Or maybe the wrong wineserver is still running?\n",
                                version, SERVER_PROTOCOL_VERSION,
                                (version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
-    set_request_buffer();
 }
 
 
@@ -702,7 +665,7 @@
     SERVER_START_REQ( boot_done )
     {
         req->debug_level = debug_level;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 }
diff --git a/scheduler/handle.c b/scheduler/handle.c
index ea42da5..a9f7aa9 100644
--- a/scheduler/handle.c
+++ b/scheduler/handle.c
@@ -46,8 +46,8 @@
         req->flags  = 0;
         req->mask   = 0;
         req->fd     = -1;
-        ret = !SERVER_CALL_ERR();
-        if (ret && flags) *flags = req->old_flags;
+        ret = !wine_server_call_err( req );
+        if (ret && flags) *flags = reply->old_flags;
     }
     SERVER_END_REQ;
     return ret;
@@ -66,7 +66,7 @@
         req->flags  = flags;
         req->mask   = mask;
         req->fd     = -1;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -90,11 +90,11 @@
         req->inherit     = inherit;
         req->options     = options;
 
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
         if (ret)
         {
-            if (dest) *dest = req->handle;
-            if (req->fd != -1) close( req->fd );
+            if (dest) *dest = reply->handle;
+            if (reply->fd != -1) close( reply->fd );
         }
     }
     SERVER_END_REQ;
diff --git a/scheduler/pipe.c b/scheduler/pipe.c
index 5816203..1332460 100644
--- a/scheduler/pipe.c
+++ b/scheduler/pipe.c
@@ -20,10 +20,10 @@
     SERVER_START_REQ( create_pipe )
     {
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        if ((ret = !SERVER_CALL_ERR()))
+        if ((ret = !wine_server_call_err( req )))
         {
-            *hReadPipe  = req->handle_read;
-            *hWritePipe = req->handle_write;
+            *hReadPipe  = reply->handle_read;
+            *hWritePipe = reply->handle_write;
         }
     }
     SERVER_END_REQ;
diff --git a/scheduler/process.c b/scheduler/process.c
index 755dd39..3577ee5 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -92,7 +92,9 @@
 #define PDB32_FILE_APIS_OEM 0x0040  /* File APIs are OEM */
 #define PDB32_WIN32S_PROC   0x8000  /* Win32s process */
 
-static char **main_exe_argv;
+static int app_argc;   /* argc/argv seen by the application */
+static char **app_argv;
+static WCHAR **app_wargv;
 static char main_exe_name[MAX_PATH];
 static char *main_exe_name_ptr = main_exe_name;
 static HANDLE main_exe_file;
@@ -229,7 +231,7 @@
 
     /* store the program name */
     argv0 = argv[0];
-    main_exe_argv = argv;
+    app_argv = argv;
 
     /* Fill the initial process structure */
     current_process.exit_code       = STILL_ACTIVE;
@@ -243,26 +245,26 @@
     CLIENT_InitServer();
 
     /* Retrieve startup info from the server */
-    SERVER_START_VAR_REQ( init_process, sizeof(main_exe_name)-1 )
+    SERVER_START_REQ( init_process )
     {
         req->ldt_copy  = &wine_ldt_copy;
         req->ppid      = getppid();
-        if ((ret = !SERVER_CALL_ERR()))
+        wine_server_set_reply( req, main_exe_name, sizeof(main_exe_name)-1 );
+        if ((ret = !wine_server_call_err( req )))
         {
-            size_t len = server_data_size( req );
-            memcpy( main_exe_name, server_data_ptr(req), len );
+            size_t len = wine_server_reply_size( reply );
             main_exe_name[len] = 0;
-            main_exe_file = req->exe_file;
-            create_flags  = req->create_flags;
-            current_startupinfo.dwFlags     = req->start_flags;
-            server_startticks               = req->server_start;
-            current_startupinfo.wShowWindow = req->cmd_show;
-            current_startupinfo.hStdInput   = req->hstdin;
-            current_startupinfo.hStdOutput  = req->hstdout;
-            current_startupinfo.hStdError   = req->hstderr;
+            main_exe_file = reply->exe_file;
+            create_flags  = reply->create_flags;
+            current_startupinfo.dwFlags     = reply->start_flags;
+            server_startticks               = reply->server_start;
+            current_startupinfo.wShowWindow = reply->cmd_show;
+            current_startupinfo.hStdInput   = reply->hstdin;
+            current_startupinfo.hStdOutput  = reply->hstdout;
+            current_startupinfo.hStdError   = reply->hstderr;
         }
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     if (!ret) return FALSE;
 
     /* Create the process heap */
@@ -295,6 +297,8 @@
 
     /* Parse command line arguments */
     OPTIONS_ParseOptions( argv );
+    app_argc = 0;
+    while (argv[app_argc]) app_argc++;
 
     ret = MAIN_MainInit();
 
@@ -345,8 +349,8 @@
         req->name     = &main_exe_name_ptr;
         req->exe_file = main_file;
         req->gui      = !console_app;
-        SERVER_CALL();
-        debugged = req->debugged;
+        wine_server_call( req );
+        debugged = reply->debugged;
     }
     SERVER_END_REQ;
 
@@ -464,19 +468,20 @@
     /* Initialize everything */
     if (!process_init( argv )) exit(1);
 
-    if (open_winelib_app( argv )) goto found; /* try to open argv[0] as a winelib app */
+    if (open_winelib_app( app_argv )) goto found; /* try to open argv[0] as a winelib app */
 
-    main_exe_argv = ++argv;  /* remove argv[0] (wine itself) */
+    app_argv++;  /* remove argv[0] (wine itself) */
+    app_argc--;
 
     if (!main_exe_name[0])
     {
-        if (!argv[0]) OPTIONS_Usage();
+        if (!app_argv[0]) OPTIONS_Usage();
 
         /* open the exe file */
-        if (!SearchPathA( NULL, argv[0], ".exe", sizeof(main_exe_name), main_exe_name, NULL ) &&
-            !SearchPathA( NULL, argv[0], NULL, sizeof(main_exe_name), main_exe_name, NULL ))
+        if (!SearchPathA( NULL, app_argv[0], ".exe", sizeof(main_exe_name), main_exe_name, NULL) &&
+            !SearchPathA( NULL, app_argv[0], NULL, sizeof(main_exe_name), main_exe_name, NULL))
         {
-            MESSAGE( "%s: cannot find '%s'\n", argv0, argv[0] );
+            MESSAGE( "%s: cannot find '%s'\n", argv0, app_argv[0] );
             goto error;
         }
     }
@@ -510,7 +515,7 @@
 
  found:
     /* build command line */
-    if (!ENV_BuildCommandLine( main_exe_argv )) goto error;
+    if (!ENV_BuildCommandLine( app_argv )) goto error;
 
     /* create 32-bit module for main exe */
     if (!(current_process.module = BUILTIN32_LoadExeModule( current_process.module ))) goto error;
@@ -528,6 +533,52 @@
 
 
 /***********************************************************************
+ *              __wine_get_main_args (NTDLL.@)
+ *
+ * Return the argc/argv that the application should see.
+ * Used by the startup code generated in the .spec.c file.
+ */
+int __wine_get_main_args( char ***argv )
+{
+    *argv = app_argv;
+    return app_argc;
+}
+
+
+/***********************************************************************
+ *              __wine_get_wmain_args (NTDLL.@)
+ *
+ * Same as __wine_get_main_args but for Unicode.
+ */
+int __wine_get_wmain_args( WCHAR ***argv )
+{
+    if (!app_wargv)
+    {
+        int i;
+        WCHAR *p;
+        DWORD total = 0;
+
+        for (i = 0; i < app_argc; i++)
+            total += MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, NULL, 0 );
+
+        app_wargv = HeapAlloc( GetProcessHeap(), 0,
+                                    total * sizeof(WCHAR) + (app_argc + 1) * sizeof(*app_wargv) );
+        p = (WCHAR *)(app_wargv + app_argc + 1);
+        for (i = 0; i < app_argc; i++)
+        {
+            DWORD len = MultiByteToWideChar( CP_ACP, 0, app_argv[i], -1, p, total );
+            app_wargv[i] = p;
+            p += len;
+            total -= len;
+        }
+        app_wargv[app_argc] = NULL;
+    }
+    *argv = app_wargv;
+    return app_argc;
+}
+
+
+/***********************************************************************
  *           build_argv
  *
  * Build an argv array from a command-line.
@@ -820,8 +871,10 @@
 
     /* create the process on the server side */
 
-    SERVER_START_VAR_REQ( new_process, MAX_PATH )
+    SERVER_START_REQ( new_process )
     {
+        char buf[MAX_PATH];
+
         req->inherit_all  = inherit;
         req->create_flags = flags;
         req->start_flags  = startup->dwFlags;
@@ -845,17 +898,19 @@
             unixfilename = filename;
             if (DOSFS_GetFullName( filename, TRUE, &full_name ))
                 unixfilename = full_name.long_name;
-            lstrcpynA( server_data_ptr(req), unixfilename, MAX_PATH );
+            wine_server_add_data( req, unixfilename, strlen(unixfilename) );
         }
         else  /* new wine process */
         {
-            if (!GetLongPathNameA( filename, server_data_ptr(req), MAX_PATH ))
-                lstrcpynA( server_data_ptr(req), filename, MAX_PATH );
+            if (GetLongPathNameA( filename, buf, MAX_PATH ))
+                wine_server_add_data( req, buf, strlen(buf) );
+            else
+                wine_server_add_data( req, filename, strlen(filename) );
         }
-        ret = !SERVER_CALL_ERR();
-        process_info = req->info;
+        ret = !wine_server_call_err( req );
+        process_info = reply->info;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     if (!ret) return FALSE;
 
     /* fork and execute */
@@ -876,13 +931,13 @@
             req->info     = process_info;
             req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
             req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle);
-            if ((ret = !SERVER_CALL_ERR()))
+            if ((ret = !wine_server_call_err( req )))
             {
-                info->dwProcessId = (DWORD)req->pid;
-                info->dwThreadId  = (DWORD)req->tid;
-                info->hProcess    = req->phandle;
-                info->hThread     = req->thandle;
-                load_done_evt     = req->event;
+                info->dwProcessId = (DWORD)reply->pid;
+                info->dwThreadId  = (DWORD)reply->tid;
+                info->hProcess    = reply->phandle;
+                info->hThread     = reply->thandle;
+                load_done_evt     = reply->event;
             }
         }
         SERVER_END_REQ;
@@ -924,7 +979,7 @@
         /* send the exit code to the server */
         req->handle    = GetCurrentProcess();
         req->exit_code = status;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
     exit( status );
@@ -1084,7 +1139,7 @@
         req->pid     = (void *)id;
         req->access  = access;
         req->inherit = inherit;
-        if (!SERVER_CALL_ERR()) ret = req->handle;
+        if (!wine_server_call_err( req )) ret = reply->handle;
     }
     SERVER_END_REQ;
     return ret;
@@ -1099,7 +1154,7 @@
     SERVER_START_REQ( get_process_info )
     {
         req->handle = handle;
-        if (!SERVER_CALL_ERR()) ret = (DWORD)req->pid;
+        if (!wine_server_call_err( req )) ret = (DWORD)reply->pid;
     }
     SERVER_END_REQ;
     return ret;
@@ -1116,7 +1171,7 @@
         req->handle   = hprocess;
         req->priority = priorityclass;
         req->mask     = SET_PROCESS_INFO_PRIORITY;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -1132,7 +1187,7 @@
     SERVER_START_REQ( get_process_info )
     {
         req->handle = hprocess;
-        if (!SERVER_CALL_ERR()) ret = req->priority;
+        if (!wine_server_call_err( req )) ret = reply->priority;
     }
     SERVER_END_REQ;
     return ret;
@@ -1150,7 +1205,7 @@
         req->handle   = hProcess;
         req->affinity = affmask;
         req->mask     = SET_PROCESS_INFO_AFFINITY;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -1167,10 +1222,10 @@
     SERVER_START_REQ( get_process_info )
     {
         req->handle = hProcess;
-        if (!SERVER_CALL_ERR())
+        if (!wine_server_call_err( req ))
         {
-            if (lpProcessAffinityMask) *lpProcessAffinityMask = req->process_affinity;
-            if (lpSystemAffinityMask) *lpSystemAffinityMask = req->system_affinity;
+            if (lpProcessAffinityMask) *lpProcessAffinityMask = reply->process_affinity;
+            if (lpSystemAffinityMask) *lpSystemAffinityMask = reply->system_affinity;
             ret = TRUE;
         }
     }
@@ -1289,62 +1344,36 @@
 BOOL WINAPI ReadProcessMemory( HANDLE process, LPCVOID addr, LPVOID buffer, DWORD size,
                                LPDWORD bytes_read )
 {
-    unsigned int offset = (unsigned int)addr % sizeof(int);
-    unsigned int pos = 0, len, max;
-    int res;
+    DWORD res;
 
-    if (bytes_read) *bytes_read = size;
-
-    /* first time, read total length to check for permissions */
-    len = (size + offset + sizeof(int) - 1) / sizeof(int);
-    max = min( REQUEST_MAX_VAR_SIZE, len * sizeof(int) );
-
-    for (;;)
+    SERVER_START_REQ( read_process_memory )
     {
-        SERVER_START_VAR_REQ( read_process_memory, max )
-        {
-            req->handle = process;
-            req->addr   = (char *)addr + pos - offset;
-            req->len    = len;
-            if (!(res = SERVER_CALL_ERR()))
-            {
-                size_t result = server_data_size( req );
-                if (result > size + offset) result = size + offset;
-                memcpy( (char *)buffer + pos, server_data_ptr(req) + offset, result - offset );
-                size -= result - offset;
-                pos += result - offset;
-            }
-        }
-        SERVER_END_VAR_REQ;
-        if (res)
-        {
-            if (bytes_read) *bytes_read = 0;
-            return FALSE;
-        }
-        if (!size) return TRUE;
-        max = min( REQUEST_MAX_VAR_SIZE, size );
-        len = (max + sizeof(int) - 1) / sizeof(int);
-        offset = 0;
+        req->handle = process;
+        req->addr   = (void *)addr;
+        wine_server_set_reply( req, buffer, size );
+        if ((res = wine_server_call_err( req ))) size = 0;
     }
+    SERVER_END_REQ;
+    if (bytes_read) *bytes_read = size;
+    return !res;
 }
 
 
 /***********************************************************************
  *           WriteProcessMemory    		(KERNEL32.@)
  */
-BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPVOID buffer, DWORD size,
+BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPCVOID buffer, DWORD size,
                                 LPDWORD bytes_written )
 {
-    unsigned int first_offset, last_offset;
-    unsigned int pos = 0, len, max, first_mask, last_mask;
-    int res;
+    static const int zero;
+    unsigned int first_offset, last_offset, first_mask, last_mask;
+    DWORD res;
 
     if (!size)
     {
         SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
-    if (bytes_written) *bytes_written = size;
 
     /* compute the mask for the first int */
     first_mask = ~0;
@@ -1356,44 +1385,26 @@
     last_mask = 0;
     memset( &last_mask, 0xff, last_offset ? last_offset : sizeof(int) );
 
-    /* for the first request, use the total length */
-    len = (size + first_offset + sizeof(int) - 1) / sizeof(int);
-    max = min( REQUEST_MAX_VAR_SIZE, len * sizeof(int) );
-
-    for (;;)
+    SERVER_START_REQ( write_process_memory )
     {
-        SERVER_START_VAR_REQ( write_process_memory, max )
-        {
-            req->handle = process;
-            req->addr = (char *)addr - first_offset + pos;
-            req->len = len;
-            req->first_mask = (!pos) ? first_mask : ~0;
-            if (size + first_offset <= max)  /* last round */
-            {
-                req->last_mask = last_mask;
-                max = size + first_offset;
-            }
-            else req->last_mask = ~0;
+        req->handle     = process;
+        req->addr       = (char *)addr - first_offset;
+        req->first_mask = first_mask;
+        req->last_mask  = last_mask;
+        if (first_offset) wine_server_add_data( req, &zero, first_offset );
+        wine_server_add_data( req, buffer, size );
+        if (last_offset) wine_server_add_data( req, &zero, sizeof(int) - last_offset );
 
-            memcpy( (char *)server_data_ptr(req) + first_offset, (char *)buffer + pos,
-                    max - first_offset );
-            if (!(res = SERVER_CALL_ERR()))
-            {
-                pos += max - first_offset;
-                size -= max - first_offset;
-            }
-        }
-        SERVER_END_VAR_REQ;
-        if (res)
-        {
-            if (bytes_written) *bytes_written = 0;
-            return FALSE;
-        }
-        if (!size) return TRUE;
-        first_offset = 0;
-        len = min( size + sizeof(int) - 1, REQUEST_MAX_VAR_SIZE ) / sizeof(int);
-        max = len * sizeof(int);
+        if ((res = wine_server_call_err( req ))) size = 0;
     }
+    SERVER_END_REQ;
+    if (bytes_written) *bytes_written = size;
+    {
+        char dummy[32];
+        DWORD read;
+        ReadProcessMemory( process, addr, dummy, sizeof(dummy), &read );
+    }
+    return !res;
 }
 
 
@@ -1427,8 +1438,8 @@
     SERVER_START_REQ( get_process_info )
     {
         req->handle = hProcess;
-        ret = !SERVER_CALL_ERR();
-        if (ret && lpExitCode) *lpExitCode = req->exit_code;
+        ret = !wine_server_call_err( req );
+        if (ret && lpExitCode) *lpExitCode = reply->exit_code;
     }
     SERVER_END_REQ;
     return ret;
diff --git a/scheduler/synchro.c b/scheduler/synchro.c
index 5bb83ff..5220f0e 100644
--- a/scheduler/synchro.c
+++ b/scheduler/synchro.c
@@ -226,17 +226,17 @@
     for (;;)
     {
         int type = APC_NONE;
-        SERVER_START_VAR_REQ( get_apc, sizeof(args) )
+        SERVER_START_REQ( get_apc )
         {
             req->alertable = alertable;
-            if (!SERVER_CALL())
+            wine_server_set_reply( req, args, sizeof(args) );
+            if (!wine_server_call( req ))
             {
-                type = req->type;
-                proc = req->func;
-                memcpy( args, server_data_ptr(req), server_data_size(req) );
+                type = reply->type;
+                proc = reply->func;
             }
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
 
         switch(type)
         {
@@ -315,7 +315,7 @@
                                        BOOL wait_all, DWORD timeout,
                                        BOOL alertable )
 {
-    int i, ret, cookie;
+    int ret, cookie;
     struct timeval tv;
 
     if (count > MAXIMUM_WAIT_OBJECTS)
@@ -329,23 +329,21 @@
 
     for (;;)
     {
-        SERVER_START_VAR_REQ( select, count * sizeof(int) )
+        SERVER_START_REQ( select )
         {
-            int *data = server_data_ptr( req );
-
             req->flags   = SELECT_INTERRUPTIBLE;
             req->cookie  = &cookie;
             req->sec     = tv.tv_sec;
             req->usec    = tv.tv_usec;
-            for (i = 0; i < count; i++) data[i] = handles[i];
+            wine_server_add_data( req, handles, count * sizeof(HANDLE) );
 
             if (wait_all) req->flags |= SELECT_ALL;
             if (alertable) req->flags |= SELECT_ALERTABLE;
             if (timeout != INFINITE) req->flags |= SELECT_TIMEOUT;
 
-            ret = SERVER_CALL();
+            ret = wine_server_call( req );
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
         if (ret == STATUS_PENDING) ret = wait_reply( &cookie );
         if (ret != STATUS_USER_APC) break;
         call_apcs( alertable );
diff --git a/scheduler/thread.c b/scheduler/thread.c
index e3cf2cd..860df59 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -51,7 +51,7 @@
     {
         req->handle = 0;
         req->tid_in = (void *)id;
-        if (!SERVER_CALL()) ret = req->teb;
+        if (!wine_server_call( req )) ret = reply->teb;
     }
     SERVER_END_REQ;
 
@@ -112,7 +112,6 @@
     close( teb->wait_fd[1] );
     if (teb->stack_sel) FreeSelector16( teb->stack_sel );
     FreeSelector16( teb->teb_sel );
-    if (teb->buffer) munmap( (void *)teb->buffer, teb->buffer_size );
     if (teb->debug_info) HeapFree( GetProcessHeap(), 0, teb->debug_info );
     VirtualFree( teb->stack_base, 0, MEM_RELEASE );
 }
@@ -298,10 +297,10 @@
         req->suspend    = ((flags & CREATE_SUSPENDED) != 0);
         req->inherit    = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
         req->request_fd = request_pipe[0];
-        if (!SERVER_CALL_ERR())
+        if (!wine_server_call_err( req ))
         {
-            handle = req->handle;
-            tid = req->tid;
+            handle = reply->handle;
+            tid = reply->tid;
         }
         close( request_pipe[0] );
     }
@@ -370,8 +369,8 @@
         /* send the exit code to the server */
         req->handle    = GetCurrentThread();
         req->exit_code = code;
-        SERVER_CALL();
-        last = req->last;
+        wine_server_call( req );
+        last = reply->last;
     }
     SERVER_END_REQ;
 
@@ -400,14 +399,14 @@
                               const CONTEXT *context ) /* [in] Address of context structure */
 {
     BOOL ret;
-    SERVER_START_VAR_REQ( set_thread_context, sizeof(*context) )
+    SERVER_START_REQ( set_thread_context )
     {
         req->handle = handle;
         req->flags = context->ContextFlags;
-        memcpy( server_data_ptr(req), context, sizeof(*context) );
-        ret = !SERVER_CALL_ERR();
+        wine_server_add_data( req, context, sizeof(*context) );
+        ret = !wine_server_call_err( req );
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -423,15 +422,15 @@
                               CONTEXT *context ) /* [out] Address of context structure */
 {
     BOOL ret;
-    SERVER_START_VAR_REQ( get_thread_context, sizeof(*context) )
+    SERVER_START_REQ( get_thread_context )
     {
         req->handle = handle;
         req->flags = context->ContextFlags;
-        memcpy( server_data_ptr(req), context, sizeof(*context) );
-        if ((ret = !SERVER_CALL_ERR()))
-            memcpy( context, server_data_ptr(req), sizeof(*context) );
+        wine_server_add_data( req, context, sizeof(*context) );
+        wine_server_set_reply( req, context, sizeof(*context) );
+        ret = !wine_server_call_err( req );
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -451,7 +450,7 @@
     {
         req->handle = hthread;
         req->tid_in = 0;
-        if (!SERVER_CALL_ERR()) ret = req->priority;
+        if (!wine_server_call_err( req )) ret = reply->priority;
     }
     SERVER_END_REQ;
     return ret;
@@ -475,7 +474,7 @@
         req->handle   = hthread;
         req->priority = priority;
         req->mask     = SET_THREAD_INFO_PRIORITY;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -529,7 +528,7 @@
         req->handle   = hThread;
         req->affinity = dwThreadAffinityMask;
         req->mask     = SET_THREAD_INFO_AFFINITY;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
         /* FIXME: should return previous value */
     }
     SERVER_END_REQ;
@@ -571,8 +570,8 @@
     {
         req->handle = hthread;
         req->tid_in = 0;
-        ret = !SERVER_CALL_ERR();
-        if (ret && exitcode) *exitcode = req->exit_code;
+        ret = !wine_server_call_err( req );
+        if (ret && exitcode) *exitcode = reply->exit_code;
     }
     SERVER_END_REQ;
     return ret;
@@ -597,7 +596,7 @@
     SERVER_START_REQ( resume_thread )
     {
         req->handle = hthread;
-        if (!SERVER_CALL_ERR()) ret = req->count;
+        if (!wine_server_call_err( req )) ret = reply->count;
     }
     SERVER_END_REQ;
     return ret;
@@ -618,7 +617,7 @@
     SERVER_START_REQ( suspend_thread )
     {
         req->handle = hthread;
-        if (!SERVER_CALL_ERR()) ret = req->count;
+        if (!wine_server_call_err( req )) ret = reply->count;
     }
     SERVER_END_REQ;
     return ret;
@@ -637,7 +636,7 @@
         req->user   = 1;
         req->func   = func;
         req->param  = (void *)data;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
diff --git a/scheduler/timer.c b/scheduler/timer.c
index 1fec111..2763f93 100644
--- a/scheduler/timer.c
+++ b/scheduler/timer.c
@@ -18,24 +18,16 @@
  */
 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
 {
-    HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
-    if (len >= MAX_PATH)
+    WCHAR buffer[MAX_PATH];
+
+    if (!name) return CreateWaitableTimerW( sa, manual, NULL );
+
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( create_timer, len * sizeof(WCHAR) )
-    {
-        req->manual  = manual;
-        req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return CreateWaitableTimerW( sa, manual, buffer );
 }
 
 
@@ -51,16 +43,16 @@
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( create_timer, len * sizeof(WCHAR) )
+    SERVER_START_REQ( create_timer )
     {
         req->manual  = manual;
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
         SetLastError(0);
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -70,23 +62,16 @@
  */
 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
 {
-    HANDLE ret;
-    DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
-    if (len >= MAX_PATH)
+    WCHAR buffer[MAX_PATH];
+
+    if (!name) return OpenWaitableTimerW( access, inherit, NULL );
+
+    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
     {
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_timer, len * sizeof(WCHAR) )
-    {
-        req->access  = access;
-        req->inherit = inherit;
-        if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
-        SERVER_CALL_ERR();
-        ret = req->handle;
-    }
-    SERVER_END_VAR_REQ;
-    return ret;
+    return OpenWaitableTimerW( access, inherit, buffer );
 }
 
 
@@ -102,15 +87,15 @@
         SetLastError( ERROR_FILENAME_EXCED_RANGE );
         return 0;
     }
-    SERVER_START_VAR_REQ( open_timer, len * sizeof(WCHAR) )
+    SERVER_START_REQ( open_timer )
     {
         req->access  = access;
         req->inherit = inherit;
-        memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
-        SERVER_CALL_ERR();
-        ret = req->handle;
+        wine_server_add_data( req, name, len * sizeof(WCHAR) );
+        wine_server_call_err( req );
+        ret = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -150,7 +135,7 @@
         req->callback = callback;
         req->arg      = arg;
         if (resume) SetLastError( ERROR_NOT_SUPPORTED ); /* set error but can still succeed */
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -166,7 +151,7 @@
     SERVER_START_REQ( cancel_timer )
     {
         req->handle = handle;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
diff --git a/server/async.c b/server/async.c
index bcb5714..5e16000 100644
--- a/server/async.c
+++ b/server/async.c
@@ -28,7 +28,7 @@
     /* FIXME: check if this object is allowed to do overlapped I/O */
 
     /* FIXME: this should be a function pointer */
-    req->timeout = get_serial_async_timeout(obj,req->type,req->count);
+    reply->timeout = get_serial_async_timeout(obj,req->type,req->count);
 
     release_object(obj);
 }
diff --git a/server/atom.c b/server/atom.c
index a0e0e4b..7d0b52c 100644
--- a/server/atom.c
+++ b/server/atom.c
@@ -65,11 +65,14 @@
 static struct atom_table *global_table;
 
 
-/* copy an atom name to a temporary area */
-static const WCHAR *copy_name( const WCHAR *str, size_t len )
+/* copy an atom name from the request to a temporary area */
+static const WCHAR *copy_request_name(void)
 {
     static WCHAR buffer[MAX_ATOM_LEN+1];
 
+    const WCHAR *str = get_req_data();
+    size_t len = get_req_data_size();
+
     if (len > MAX_ATOM_LEN*sizeof(WCHAR))
     {
         set_error( STATUS_INVALID_PARAMETER );
@@ -267,27 +270,6 @@
     return 0;
 }
 
-/* get an atom name and refcount*/
-static size_t get_atom_name( struct atom_table *table, atom_t atom,
-                             WCHAR *str, size_t maxsize, int *count )
-{
-    size_t len = 0;
-    struct atom_entry *entry = get_atom_entry( table, atom );
-    *count = -1;
-    if (entry)
-    {
-        *count = entry->count;
-        len = strlenW( entry->str ) * sizeof(WCHAR);
-        if (len <= maxsize) memcpy( str, entry->str, len );
-        else
-        {
-            set_error( STATUS_BUFFER_OVERFLOW );
-            len = 0;
-        }
-    }
-    return len;
-}
-
 /* increment the ref count of a global atom; used for window properties */
 int grab_global_atom( atom_t atom )
 {
@@ -310,8 +292,8 @@
     if (!*table_ptr) *table_ptr = create_table(0);
     if (*table_ptr)
     {
-        const WCHAR *name = copy_name( get_req_data(req), get_req_data_size(req) );
-        if (name) req->atom = add_atom( *table_ptr, name );
+        const WCHAR *name = copy_request_name();
+        if (name) reply->atom = add_atom( *table_ptr, name );
     }
 }
 
@@ -324,18 +306,26 @@
 /* find a global atom */
 DECL_HANDLER(find_atom)
 {
-    const WCHAR *name = copy_name( get_req_data(req), get_req_data_size(req) );
+    const WCHAR *name = copy_request_name();
     if (name)
-        req->atom = find_atom( req->local ? current->process->atom_table : global_table, name );
+        reply->atom = find_atom( req->local ? current->process->atom_table : global_table, name );
 }
 
 /* get global atom name */
 DECL_HANDLER(get_atom_name)
 {
-    WCHAR *name = get_req_data(req);
-    size_t size = get_atom_name( req->local ? current->process->atom_table : global_table,
-                                 req->atom, name, get_req_data_size(req), &req->count );
-    set_req_data_size( req, size );
+    struct atom_entry *entry;
+    size_t len = 0;
+
+    reply->count = -1;
+    if ((entry = get_atom_entry( req->local ? current->process->atom_table : global_table,
+                                 req->atom )))
+    {
+        reply->count = entry->count;
+        len = strlenW( entry->str ) * sizeof(WCHAR);
+        if (len <= get_reply_max_size()) set_reply_data( entry->str, len );
+        else set_error( STATUS_BUFFER_OVERFLOW );
+    }
 }
 
 /* init the process atom table */
diff --git a/server/change.c b/server/change.c
index 4dd0dcb..1162b6a 100644
--- a/server/change.c
+++ b/server/change.c
@@ -72,11 +72,11 @@
 {
     struct change *change;
 
-    req->handle = 0;
+    reply->handle = 0;
     if ((change = create_change_notification( req->subtree, req->filter )))
     {
-        req->handle = alloc_handle( current->process, change,
-                                    STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE, 0 );
+        reply->handle = alloc_handle( current->process, change,
+                                      STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE, 0 );
         release_object( change );
     }
 }
diff --git a/server/console.c b/server/console.c
index bd6dd39..4ea264e 100644
--- a/server/console.c
+++ b/server/console.c
@@ -13,10 +13,6 @@
 #include <stdio.h>
 #include <unistd.h>
 
-#include "winnt.h"
-#include "winbase.h"
-#include "wincon.h"
-
 #include "handle.h"
 #include "process.h"
 #include "request.h"
@@ -29,7 +25,7 @@
 static int console_input_signaled( struct object *obj, struct thread *thread );
 
 /* common routine */
-static int console_get_file_info( struct object *obj, struct get_file_info_request *req );
+static int console_get_file_info( struct object *obj, struct get_file_info_reply *reply );
 
 static const struct object_ops console_input_ops =
 {
@@ -78,19 +74,21 @@
 struct screen_buffer
 {
     struct object         obj;           /* object header */
-    int                   mode;          /* output mode */
-    struct console_input *input;         /* associated console input */
     struct screen_buffer *next;          /* linked list of all screen buffers */
-    short int             cursor_size;   /* size of cursor (percentage filled) */
-    short int             cursor_visible;/* cursor visibility flag */
-    COORD                 cursor;        /* position of cursor */
-    short int             width;         /* size (w-h) of the screen buffer */
-    short int             height;
-    short int             max_width;     /* size (w-h) of the window given font size */
-    short int             max_height;
-    unsigned             *data;          /* the data for each cell - a width x height matrix */
+    struct screen_buffer *prev;
+    struct console_input *input;         /* associated console input */
+    int                   mode;          /* output mode */
+    int                   cursor_size;   /* size of cursor (percentage filled) */
+    int                   cursor_visible;/* cursor visibility flag */
+    int                   cursor_x;      /* position of cursor */
+    int                   cursor_y;      /* position of cursor */
+    int                   width;         /* size (w-h) of the screen buffer */
+    int                   height;
+    int                   max_width;     /* size (w-h) of the window given font size */
+    int                   max_height;
+    char_info_t          *data;          /* the data for each cell - a width x height matrix */
     unsigned short        attr;          /* default attribute for screen buffer */
-    SMALL_RECT            win;           /* current visible window on the screen buffer *
+    rectangle_t           win;           /* current visible window on the screen buffer *
 					  * as seen in wineconsole */
 };
 
@@ -115,6 +113,8 @@
 
 static struct screen_buffer *screen_buffer_list;
 
+static const char_info_t empty_char_info = { ' ', 0x00f0 };  /* white on black space */
+
 /* dumps the renderer events of a console */
 static void console_input_events_dump( struct object *obj, int verbose )
 {
@@ -132,20 +132,18 @@
     free( evts->events );
 }
 
-/* the rendere events list is signaled when it's not empty */
-static int  console_input_events_signaled( struct object *obj, struct thread *thread )
+/* the renderer events list is signaled when it's not empty */
+static int console_input_events_signaled( struct object *obj, struct thread *thread )
 {
     struct console_input_events *evts = (struct console_input_events *)obj;
     assert( obj->ops == &console_input_events_ops );
-    return evts->num_used ? 1 : 0;
+    return (evts->num_used != 0);
 }
 
 /* add an event to the console's renderer events list */
 static void console_input_events_append( struct console_input_events* evts, 
 					 struct console_renderer_event* evt)
 {
-    if (!evt) return;
-
     /* to be done even when the renderer generates the events ? */
     if (evts->num_used == evts->num_alloc)
     {
@@ -158,25 +156,18 @@
 }
 
 /* retrieves events from the console's renderer events list */
-static size_t  console_input_events_get( struct console_input_events* evts, 
-					 struct console_renderer_event* evt, size_t num )
+static void console_input_events_get( struct console_input_events* evts )
 {
-    if (num % sizeof(*evt) != 0)
-    {
-	set_error( STATUS_INVALID_PARAMETER );
-	return 0;
-    }
-    num /= sizeof(*evt);
-    if (num > evts->num_used)
-	num = evts->num_used;
-    memcpy( evt, evts->events, num * sizeof(*evt) );
+    size_t num = get_reply_max_size() / sizeof(evts->events[0]);
+
+    if (num > evts->num_used) num = evts->num_used;
+    set_reply_data( evts->events, num * sizeof(evts->events[0]) );
     if (num < evts->num_used)
     {
-	memmove( &evts->events[0], &evts->events[num], 
-		 (evts->num_used - num) * sizeof(*evt) );
+        memmove( &evts->events[0], &evts->events[num],
+                 (evts->num_used - num) * sizeof(evts->events[0]) );
     }
     evts->num_used -= num;
-    return num * sizeof(struct console_renderer_event);
 }
 
 static struct console_input_events *create_console_input_events(void)
@@ -216,7 +207,7 @@
     return &console_input->obj;
 }
 
-static struct object *create_console_output( struct console_input *console_input )
+static struct screen_buffer *create_console_output( struct console_input *console_input )
 {
     struct screen_buffer *screen_buffer;
     struct console_renderer_event evt;
@@ -231,23 +222,31 @@
     screen_buffer->height         = 150;
     screen_buffer->max_width      = 80;
     screen_buffer->max_height     = 25;
-    screen_buffer->data           = malloc( 4 * screen_buffer->width * screen_buffer->height );
-    /* fill the buffer with white on black spaces */
-    for (i = 0; i < screen_buffer->width * screen_buffer->height; i++)
-    {
-	screen_buffer->data[i] = 0x00F00020;
-    }
-    screen_buffer->cursor.X	  = 0;
-    screen_buffer->cursor.Y	  = 0;
+    screen_buffer->cursor_x       = 0;
+    screen_buffer->cursor_y       = 0;
     screen_buffer->attr           = 0xF0;
-    screen_buffer->win.Left       = 0;
-    screen_buffer->win.Right      = screen_buffer->max_width - 1;
-    screen_buffer->win.Top        = 0;
-    screen_buffer->win.Bottom     = screen_buffer->max_height - 1;
+    screen_buffer->win.left       = 0;
+    screen_buffer->win.right      = screen_buffer->max_width - 1;
+    screen_buffer->win.top        = 0;
+    screen_buffer->win.bottom     = screen_buffer->max_height - 1;
 
-    screen_buffer->next = screen_buffer_list;
+    if ((screen_buffer->next = screen_buffer_list)) screen_buffer->next->prev = screen_buffer;
+    screen_buffer->prev = NULL;
     screen_buffer_list = screen_buffer;
 
+    if (!(screen_buffer->data = malloc( screen_buffer->width * screen_buffer->height *
+                                        sizeof(*screen_buffer->data) )))
+    {
+        release_object( screen_buffer );
+        return NULL;
+    }
+    /* clear the first row */
+    for (i = 0; i < screen_buffer->width; i++) screen_buffer->data[i] = empty_char_info;
+    /* and copy it to all other rows */
+    for (i = 1; i < screen_buffer->height; i++)
+        memcpy( &screen_buffer->data[i * screen_buffer->width], screen_buffer->data,
+                screen_buffer->width * sizeof(char_info_t) );
+
     if (!console_input->active)
     {
 	console_input->active = (struct screen_buffer*)grab_object( screen_buffer );
@@ -262,10 +261,10 @@
 	console_input_events_append( console_input->evt, &evt );
 
 	evt.event = CONSOLE_RENDERER_DISPLAY_EVENT;
-	evt.u.display.left   = screen_buffer->win.Left;
-	evt.u.display.top    = screen_buffer->win.Top;
-	evt.u.display.width  = screen_buffer->win.Right - screen_buffer->win.Left + 1;
-	evt.u.display.height = screen_buffer->win.Bottom - screen_buffer->win.Top + 1;
+	evt.u.display.left   = screen_buffer->win.left;
+	evt.u.display.top    = screen_buffer->win.top;
+	evt.u.display.width  = screen_buffer->win.right - screen_buffer->win.left + 1;
+	evt.u.display.height = screen_buffer->win.bottom - screen_buffer->win.top + 1;
 	console_input_events_append( console_input->evt, &evt );
 
 	evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
@@ -279,12 +278,11 @@
 	console_input_events_append( console_input->evt, &evt );
 
 	evt.event = CONSOLE_RENDERER_CURSOR_POS_EVENT;
-	evt.u.cursor_pos.x = screen_buffer->cursor.X;
-	evt.u.cursor_pos.y = screen_buffer->cursor.Y;
+	evt.u.cursor_pos.x = screen_buffer->cursor_x;
+	evt.u.cursor_pos.y = screen_buffer->cursor_y;
 	console_input_events_append( console_input->evt, &evt );
     }
-
-    return &screen_buffer->obj;
+    return screen_buffer;
 }
 
 /* free the console for this process */
@@ -411,11 +409,12 @@
 }
 
 /* add input events to a console input queue */
-static int write_console_input( struct console_input* console, int count, INPUT_RECORD *records )
+static int write_console_input( struct console_input* console, int count,
+                                const INPUT_RECORD *records )
 {
     INPUT_RECORD *new_rec;
 
-    assert(count);
+    if (!count) return 0;
     if (!(new_rec = realloc( console->records,
                              (console->recnum + count) * sizeof(INPUT_RECORD) )))
     {
@@ -433,7 +432,7 @@
 }
 
 /* retrieve a pointer to the console input records */
-static int read_console_input( handle_t handle, int count, INPUT_RECORD *rec, int flush )
+static int read_console_input( handle_t handle, int count, int flush )
 {
     struct console_input *console;
 
@@ -450,13 +449,13 @@
     else
     {
         if (count > console->recnum) count = console->recnum;
-        memcpy( rec, console->records, count * sizeof(INPUT_RECORD) );
+        set_reply_data( console->records, count * sizeof(INPUT_RECORD) );
     }
     if (flush)
     {
         int i;
         for (i = count; i < console->recnum; i++)
-            ((INPUT_RECORD*)console->records)[i-count] = ((INPUT_RECORD*)console->records)[i];
+            console->records[i-count] = console->records[i];
         if ((console->recnum -= count) > 0)
         {
             INPUT_RECORD *new_rec = realloc( console->records,
@@ -474,7 +473,7 @@
 }
 
 /* set misc console input information */
-static int set_console_input_info( struct set_console_input_info_request *req, 
+static int set_console_input_info( const struct set_console_input_info_request *req,
 				   const WCHAR *title, size_t len )
 {
     struct console_input *console;
@@ -557,9 +556,61 @@
     return 0;
 }
 
+/* resize a screen buffer */
+static int change_screen_buffer_size( struct screen_buffer *screen_buffer,
+                                      int new_width, int new_height )
+{
+    int i, old_width, old_height, copy_width, copy_height;
+    char_info_t *new_data;
+
+    if (!(new_data = malloc( new_width * new_height * sizeof(*new_data) )))
+    {
+        set_error( STATUS_NO_MEMORY );
+        return 0;
+    }
+    old_width = screen_buffer->width;
+    old_height = screen_buffer->height;
+    copy_width = min( old_width, new_width );
+    copy_height = min( old_height, new_height );
+
+    /* copy all the rows */
+    for (i = 0; i < copy_height; i++)
+    {
+        memcpy( &new_data[i * new_width], &screen_buffer->data[i * old_width],
+                copy_width * sizeof(char_info_t) );
+    }
+
+    /* clear the end of each row */
+    if (new_width > old_width)
+    {
+        /* fill first row */
+        for (i = old_width; i < new_width; i++) new_data[i] = empty_char_info;
+        /* and blast it to the other rows */
+        for (i = 1; i < copy_height; i++)
+            memcpy( &new_data[i * new_width + old_width], &new_data[old_width],
+                    (new_width - old_width) * sizeof(char_info_t) );
+    }
+
+    /* clear remaining rows */
+    if (new_height > old_height)
+    {
+        /* fill first row */
+        for (i = 0; i < new_width; i++) new_data[old_height * new_width + i] = empty_char_info;
+        /* and blast it to the other rows */
+        for (i = old_height+1; i < new_height; i++)
+            memcpy( &new_data[i * new_width], &new_data[old_height * new_width],
+                    new_width * sizeof(char_info_t) );
+    }
+    free( screen_buffer->data );
+    screen_buffer->data = new_data;
+    screen_buffer->width = new_width;
+    screen_buffer->height = new_height;
+    return 1;
+}
+
 /* set misc screen buffer information */
-static int set_console_output_info( struct screen_buffer *screen_buffer, 
-				    struct set_console_output_info_request *req )
+static int set_console_output_info( struct screen_buffer *screen_buffer,
+                                    const struct set_console_output_info_request *req )
 {
     struct console_renderer_event evt;
 
@@ -589,10 +640,10 @@
 	    set_error( STATUS_INVALID_PARAMETER );
 	    return 0;
 	}
-	if (screen_buffer->cursor.X != req->cursor_x || screen_buffer->cursor.Y != req->cursor_y)
+	if (screen_buffer->cursor_x != req->cursor_x || screen_buffer->cursor_y != req->cursor_y)
 	{
-	    screen_buffer->cursor.X       = req->cursor_x;
-	    screen_buffer->cursor.Y       = req->cursor_y;
+	    screen_buffer->cursor_x       = req->cursor_x;
+	    screen_buffer->cursor_y       = req->cursor_y;
 	    evt.event = CONSOLE_RENDERER_CURSOR_POS_EVENT;
 	    evt.u.cursor_pos.x = req->cursor_x;
 	    evt.u.cursor_pos.y = req->cursor_y;
@@ -601,26 +652,9 @@
     }
     if (req->mask & SET_CONSOLE_OUTPUT_INFO_SIZE)
     {
-	int		i, j;
-	/* FIXME: there are also some basic minimum and max size to deal with */
-	unsigned*	new_data = mem_alloc( 4 * req->width * req->height );
+        /* FIXME: there are also some basic minimum and max size to deal with */
+        if (!change_screen_buffer_size( screen_buffer, req->width, req->height )) return 0;
 
-	if (!new_data) return 0;
-
-	/* fill the buffer with either the old buffer content or white on black spaces */
-	for (j = 0; j < req->height; j++)
-	{
-	    for (i = 0; i < req->width; i++)
-	    {
-		new_data[j * req->width + i] = 
-		    (i < screen_buffer->width && j < screen_buffer->height) ?
-		    screen_buffer->data[j * screen_buffer->width + i] : 0x00F00020;
-	    }	
-	}
-	free( screen_buffer->data );
-	screen_buffer->data = new_data;
-	screen_buffer->width = req->width;
-	screen_buffer->height = req->height;
 	evt.event = CONSOLE_RENDERER_SB_RESIZE_EVENT;
 	evt.u.resize.width  = req->width;
 	evt.u.resize.height = req->height;
@@ -650,13 +684,13 @@
 	    set_error( STATUS_INVALID_PARAMETER );
 	    return 0;
 	}
-	if (screen_buffer->win.Left != req->win_left || screen_buffer->win.Top != req->win_top ||
-	    screen_buffer->win.Right != req->win_right || screen_buffer->win.Bottom != req->win_bottom)
+	if (screen_buffer->win.left != req->win_left || screen_buffer->win.top != req->win_top ||
+	    screen_buffer->win.right != req->win_right || screen_buffer->win.bottom != req->win_bottom)
 	{
-	    screen_buffer->win.Left   = req->win_left;
-	    screen_buffer->win.Top    = req->win_top;
-	    screen_buffer->win.Right  = req->win_right;
-	    screen_buffer->win.Bottom = req->win_bottom;
+	    screen_buffer->win.left   = req->win_left;
+	    screen_buffer->win.top    = req->win_top;
+	    screen_buffer->win.right  = req->win_right;
+	    screen_buffer->win.bottom = req->win_bottom;
 	    evt.event = CONSOLE_RENDERER_DISPLAY_EVENT;
 	    evt.u.display.left   = req->win_left;
 	    evt.u.display.top    = req->win_top;
@@ -725,18 +759,16 @@
 }
 
 /* returns a line from the cachde */
-static int console_input_get_hist( struct console_input* console, WCHAR* buf, size_t len, int index )
+static size_t console_input_get_hist( struct console_input *console, int index )
 {
-    int	ret;
+    size_t ret = 0;
 
-    /* FIXME: don't use len yet */
-    if (!console || index >= console->history_index)
+    if (index >= console->history_index) set_error( STATUS_INVALID_PARAMETER );
+    else
     {
-	set_error( STATUS_INVALID_PARAMETER );
-	return 0;
+        ret = strlenW( console->history[index] ) * sizeof(WCHAR);
+        set_reply_data( console->history[index], min( ret, get_reply_max_size() ));
     }
-    ret = strlenW(console->history[index]);
-    memcpy( buf, console->history[index], ret * sizeof(WCHAR) ); /* FIXME should use len */
     return ret;
 }
 
@@ -749,20 +781,20 @@
 	     console->active, console->evt );
 }
 
-static int console_get_file_info( struct object *obj, struct get_file_info_request *req )
+static int console_get_file_info( struct object *obj, struct get_file_info_reply *reply )
 {
-    if (req)
+    if (reply)
     {
-        req->type        = FILE_TYPE_CHAR;
-        req->attr        = 0;
-        req->access_time = 0;
-        req->write_time  = 0;
-        req->size_high   = 0;
-        req->size_low    = 0;
-        req->links       = 0;
-        req->index_high  = 0;
-        req->index_low   = 0;
-        req->serial      = 0;
+        reply->type        = FILE_TYPE_CHAR;
+        reply->attr        = 0;
+        reply->access_time = 0;
+        reply->write_time  = 0;
+        reply->size_high   = 0;
+        reply->size_low    = 0;
+        reply->links       = 0;
+        reply->index_high  = 0;
+        reply->index_low   = 0;
+        reply->serial      = 0;
     }
     return FD_TYPE_CONSOLE;
 }
@@ -803,113 +835,193 @@
 
 static void screen_buffer_destroy( struct object *obj )
 {
-    struct screen_buffer*	screen_buffer = (struct screen_buffer *)obj;
-    struct screen_buffer**	psb;
+    struct screen_buffer *screen_buffer = (struct screen_buffer *)obj;
 
     assert( obj->ops == &screen_buffer_ops );
 
-    for (psb = &screen_buffer_list; *psb; *psb = (*psb)->next)
-    {
-	if (*psb == screen_buffer)
-	{
-	    *psb = screen_buffer->next;
-	    break;
-	}
-    }	
+    if (screen_buffer->next) screen_buffer->next->prev = screen_buffer->prev;
+    if (screen_buffer->prev) screen_buffer->prev->next = screen_buffer->next;
+    else screen_buffer_list = screen_buffer->next;
+
     if (screen_buffer->input && screen_buffer->input->active == screen_buffer)
     {
 	struct screen_buffer*	sb;
 	for (sb = screen_buffer_list; sb && sb->input != screen_buffer->input; sb = sb->next);
 	screen_buffer->input->active = sb;
     }
+    if (screen_buffer->data) free( screen_buffer->data );
 }
 
 /* write data into a screen buffer */
-static int write_console_output( struct screen_buffer *screen_buffer, size_t size, 
-				 const unsigned char* data, int mode, short int x, short int y )
+static int write_console_output( struct screen_buffer *screen_buffer, size_t size,
+                                 const void* data, enum char_info_mode mode,
+                                 int x, int y, int wrap )
 {
-    int 			uniform = mode & WRITE_CONSOLE_MODE_UNIFORM;
-    unsigned		       *ptr;
-    unsigned			i, inc;
-    int				len;
+    int i;
+    char_info_t *end, *dest = screen_buffer->data + y * screen_buffer->width + x;
 
-    mode &= ~WRITE_CONSOLE_MODE_UNIFORM;
+    if (y >= screen_buffer->height) return 0;
 
-    if (mode < 0 || mode > 3)
+    if (wrap)
+        end = screen_buffer->data + screen_buffer->height * screen_buffer->width;
+    else
+        end = screen_buffer->data + (y+1) * screen_buffer->width;
+
+    switch(mode)
     {
-	set_error(STATUS_INVALID_PARAMETER);
-	return 0;
+    case CHAR_INFO_MODE_TEXT:
+        {
+            const WCHAR *ptr = data;
+            for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++) dest->ch = ptr[i];
+        }
+        break;
+    case CHAR_INFO_MODE_ATTR:
+        {
+            const unsigned short *ptr = data;
+            for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++) dest->attr = ptr[i];
+        }
+        break;
+    case CHAR_INFO_MODE_TEXTATTR:
+        {
+            const char_info_t *ptr = data;
+            for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++) *dest = ptr[i];
+        }
+        break;
+    case CHAR_INFO_MODE_TEXTSTDATTR:
+        {
+            const WCHAR *ptr = data;
+            for (i = 0; i < size/sizeof(*ptr) && dest < end; dest++, i++)
+            {
+                dest->ch   = ptr[i];
+                dest->attr = screen_buffer->attr;
+            }
+        }
+        break;
+    default:
+        set_error( STATUS_INVALID_PARAMETER );
+        return 0;
     }
 
-    /* set destination pointer and increment */
-    ptr = screen_buffer->data + (y * screen_buffer->width + x);
-    if (mode == WRITE_CONSOLE_MODE_ATTR) ptr = (unsigned*)((char*)ptr + 2);
-    inc = (mode == WRITE_CONSOLE_MODE_TEXTATTR) ? 4 : 2;
-    len = size / inc;
-
-    /* crop if needed */
-    if (x + len > screen_buffer->width) len = screen_buffer->width - x;
-
-    for (i = 0; i < len; i++)
+    if (i && screen_buffer == screen_buffer->input->active)
     {
-	if (mode == WRITE_CONSOLE_MODE_TEXTSTDATTR)
-	{
-	    memcpy( (char*)ptr + 2, &screen_buffer->attr, 2 );
-	}	
-	memcpy( ptr++, data, inc );
-	if (!uniform) data += inc;
+        struct console_renderer_event evt;
+        evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
+        evt.u.update.top    = y;
+        evt.u.update.bottom = (y * screen_buffer->width + x + i - 1) / screen_buffer->width;
+        console_input_events_append( screen_buffer->input->evt, &evt );
+    }
+    return i;
+}
+
+/* fill a screen buffer with uniform data */
+static int fill_console_output( struct screen_buffer *screen_buffer, char_info_t data,
+                                enum char_info_mode mode, int x, int y, int count, int wrap )
+{
+    int i;
+    char_info_t *end, *dest = screen_buffer->data + y * screen_buffer->width + x;
+
+    if (y >= screen_buffer->height) return 0;
+
+    if (wrap)
+        end = screen_buffer->data + screen_buffer->height * screen_buffer->width;
+    else
+        end = screen_buffer->data + (y+1) * screen_buffer->width;
+
+    if (count > end - dest) count = end - dest;
+
+    switch(mode)
+    {
+    case CHAR_INFO_MODE_TEXT:
+        for (i = 0; i < count; i++) dest[i].ch = data.ch;
+        break;
+    case CHAR_INFO_MODE_ATTR:
+        for (i = 0; i < count; i++) dest[i].attr = data.attr;
+        break;
+    case CHAR_INFO_MODE_TEXTATTR:
+        for (i = 0; i < count; i++) dest[i] = data;
+        break;
+    case CHAR_INFO_MODE_TEXTSTDATTR:
+        for (i = 0; i < count; i++)
+        {
+            dest[i].ch   = data.ch;
+            dest[i].attr = screen_buffer->attr;
+        }
+        break;
+    default:
+        set_error( STATUS_INVALID_PARAMETER );
+        return 0;
     }
 
-    if (len && screen_buffer == screen_buffer->input->active)
+    if (count && screen_buffer == screen_buffer->input->active)
     {
-	int	y2;
-	struct console_renderer_event evt;
-
-	y2 = (y * screen_buffer->width + x + len - 1) / screen_buffer->width;
-
-	evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
-	evt.u.update.top    = y;
-	evt.u.update.bottom = y2;
-	console_input_events_append( screen_buffer->input->evt, &evt );
+        struct console_renderer_event evt;
+        evt.event = CONSOLE_RENDERER_UPDATE_EVENT;
+        evt.u.update.top    = y;
+        evt.u.update.bottom = (y * screen_buffer->width + x + count - 1) / screen_buffer->width;
+        console_input_events_append( screen_buffer->input->evt, &evt );
     }
-    return len;
+    return i;
 }
 
 /* read data from a screen buffer */
-static int read_console_output( struct screen_buffer *screen_buffer, size_t size, void* data, 
-				short int x, short int y, short int w, short int h, 
-				short int* eff_w, short int* eff_h )
+static void read_console_output( struct screen_buffer *screen_buffer, int x, int y,
+                                 enum char_info_mode mode, int wrap )
 {
-    int	j;
+    int i;
+    char_info_t *end, *src = screen_buffer->data + y * screen_buffer->width + x;
 
-    if (size < w * h * 4 || x >= screen_buffer->width || y >= screen_buffer->height)
-    {	
-	set_error(STATUS_INVALID_PARAMETER);
-	return 0;
-    }
+    if (y >= screen_buffer->height) return;
 
-    *eff_w = w;
-    *eff_h = h;
-    if (x + w > screen_buffer->width)  *eff_w = screen_buffer->width  - x;
-    if (y + h > screen_buffer->height) *eff_h = screen_buffer->height - y;
+    if (wrap)
+        end = screen_buffer->data + screen_buffer->height * screen_buffer->width;
+    else
+        end = screen_buffer->data + (y+1) * screen_buffer->width;
 
-    for (j = 0; j < *eff_h; j++)
+    switch(mode)
     {
-	memcpy( (char*)data + 4 * j * w, &screen_buffer->data[(y + j) * screen_buffer->width + x],
-	        *eff_w * 4 );
+    case CHAR_INFO_MODE_TEXT:
+        {
+            WCHAR *data;
+            int count = min( end - src, get_reply_max_size() / sizeof(*data) );
+            if ((data = set_reply_data_size( count * sizeof(*data) )))
+            {
+                for (i = 0; i < count; i++) data[i] = src[i].ch;
+            }
+        }
+        break;
+    case CHAR_INFO_MODE_ATTR:
+        {
+            unsigned short *data;
+            int count = min( end - src, get_reply_max_size() / sizeof(*data) );
+            if ((data = set_reply_data_size( count * sizeof(*data) )))
+            {
+                for (i = 0; i < count; i++) data[i] = src[i].attr;
+            }
+        }
+        break;
+    case CHAR_INFO_MODE_TEXTATTR:
+        {
+            char_info_t *data;
+            int count = min( end - src, get_reply_max_size() / sizeof(*data) );
+            if ((data = set_reply_data_size( count * sizeof(*data) )))
+            {
+                for (i = 0; i < count; i++) data[i] = src[i];
+            }
+        }
+        break;
+    default:
+        set_error( STATUS_INVALID_PARAMETER );
+        break;
     }
-
-    return *eff_w * *eff_h;
 }
 
 /* scroll parts of a screen buffer */
-static void scroll_console_output( handle_t handle, short int xsrc, short int ysrc, 
-				   short int xdst, short int ydst, short int w, short int h )
+static void scroll_console_output( handle_t handle, int xsrc, int ysrc, int xdst, int ydst,
+                                   int w, int h )
 {
     struct screen_buffer *screen_buffer;
     int				j;
-    unsigned*			psrc;
-    unsigned*			pdst;
+    char_info_t *psrc, *pdst;
     struct console_renderer_event evt;
 
     if (!(screen_buffer = (struct screen_buffer *)get_handle_obj( current->process, handle,
@@ -934,7 +1046,7 @@
 
 	for (j = h; j > 0; j--)
 	{
-	    memcpy(pdst, psrc, w * 4);
+	    memcpy(pdst, psrc, w * sizeof(*pdst) );
 	    pdst -= screen_buffer->width;
 	    psrc -= screen_buffer->width;
 	}
@@ -949,7 +1061,7 @@
 	    /* we use memmove here because when psrc and pdst are the same, 
 	     * copies are done on the same row, so the dst and src blocks
 	     * can overlap */
-	    memmove( pdst, psrc, w * 4 );
+	    memmove( pdst, psrc, w * sizeof(*pdst) );
 	    pdst += screen_buffer->width;
 	    psrc += screen_buffer->width;
 	}
@@ -976,35 +1088,35 @@
     process = (req->pid) ? get_process_from_id( req->pid ) :
               (struct process *)grab_object( renderer->parent );
 
-    req->handle_in = 0;
-    req->event = 0;
+    reply->handle_in = 0;
+    reply->event = 0;
     if (!process) return;
     if (process != renderer && process->console)
-    {	
-	set_error( STATUS_ACCESS_DENIED );
-	goto the_end;
+    {
+        set_error( STATUS_ACCESS_DENIED );
+        goto the_end;
     }
 
     if ((console = (struct console_input*)create_console_input( renderer )))
     {
-	if ((in = alloc_handle( renderer, console, req->access, req->inherit )))
-	{
-	    if ((evt = alloc_handle( renderer, console->evt, 
-				     SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, FALSE )))
-	    {
-		if (process != renderer)
-		{
-		    process->console = (struct console_input*)grab_object( console );
-		    console->num_proc++;
-		}
-		req->handle_in = in;
-		req->event = evt;
-		release_object( console );
-		goto the_end;
-	    }
-	    close_handle( renderer, in, NULL );
-	}
-	free_console( process );
+        if ((in = alloc_handle( renderer, console, req->access, req->inherit )))
+        {
+            if ((evt = alloc_handle( renderer, console->evt,
+                                     SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, FALSE )))
+            {
+                if (process != renderer)
+                {
+                    process->console = (struct console_input*)grab_object( console );
+                    console->num_proc++;
+                }
+                reply->handle_in = in;
+                reply->event = evt;
+                release_object( console );
+                goto the_end;
+            }
+            close_handle( renderer, in, NULL );
+        }
+        free_console( process );
     }
  the_end:
     release_object( process );
@@ -1019,14 +1131,12 @@
 /* let the renderer peek the events it's waiting on */
 DECL_HANDLER(get_console_renderer_events)
 {
-    struct console_input_events*	evt;
-    size_t len = 0;
+    struct console_input_events *evt;
 
     evt = (struct console_input_events *)get_handle_obj( current->process, req->handle,
-							 GENERIC_WRITE, &console_input_events_ops );
+                                                         GENERIC_WRITE, &console_input_events_ops );
     if (!evt) return;
-    len = console_input_events_get( evt, get_req_data(req), get_req_data_size(req) );
-    set_req_data_size( req, len );
+    console_input_events_get( evt );
     release_object( evt );
 }
 
@@ -1035,70 +1145,66 @@
 {
     struct object      *obj = NULL;
 
-    req->handle = 0;
+    reply->handle = 0;
     switch (req->from)
     {
-    case 0: 
-	if (current->process->console && current->process->console->renderer)
-	    obj = grab_object( (struct object*)current->process->console );
-	break;
-    case 1: 
-	 if (current->process->console && current->process->console->renderer && 
-	     current->process->console->active)
-	     obj = grab_object( (struct object*)current->process->console->active );
-	break;
+    case 0:
+        if (current->process->console && current->process->console->renderer)
+            obj = grab_object( (struct object*)current->process->console );
+        break;
+    case 1:
+         if (current->process->console && current->process->console->renderer &&
+             current->process->console->active)
+             obj = grab_object( (struct object*)current->process->console->active );
+        break;
     default:
-	if ((obj = get_handle_obj( current->process, (handle_t)req->from,
-				   GENERIC_READ|GENERIC_WRITE, &console_input_ops )))
-	{
-	    struct console_input* console = (struct console_input*)obj;
-	    obj = (console->active) ? grab_object( console->active ) : NULL;
-	    release_object( console );
-	}
-	break;
+        if ((obj = get_handle_obj( current->process, (handle_t)req->from,
+                                   GENERIC_READ|GENERIC_WRITE, &console_input_ops )))
+        {
+            struct console_input* console = (struct console_input*)obj;
+            obj = (console->active) ? grab_object( console->active ) : NULL;
+            release_object( console );
+        }
+        break;
     }
 
     /* FIXME: req->share is not used (as in screen buffer creation)  */
     if (obj)
     {
-	req->handle = alloc_handle( current->process, obj, req->access, req->inherit );
-	release_object( obj );
+        reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
+        release_object( obj );
     }
-    if (!req->handle && !get_error()) set_error( STATUS_ACCESS_DENIED );
+    else if (!get_error()) set_error( STATUS_ACCESS_DENIED );
 }
 
 /* set info about a console input */
 DECL_HANDLER(set_console_input_info)
 {
-    set_console_input_info( req, get_req_data(req), get_req_data_size(req) );
+    set_console_input_info( req, get_req_data(), get_req_data_size() );
 }
 
 /* get info about a console (output only) */
 DECL_HANDLER(get_console_input_info)
 {
-    struct console_input *console = 0;
+    struct console_input *console;
 
-    set_req_data_size( req, 0 );
     if (!(console = console_input_get( req->handle, GENERIC_READ ))) return;
-
     if (console->title)
     {
-	size_t len = strlenW( console->title ) * sizeof(WCHAR);
-	if (len > get_req_data_size(req)) len = get_req_data_size(req);
-	memcpy( get_req_data(req), console->title, len );
-	set_req_data_size( req, len );
+        size_t len = strlenW( console->title ) * sizeof(WCHAR);
+        if (len > get_reply_max_size()) len = get_reply_max_size();
+        set_reply_data( console->title, len );
     }
-    req->history_mode  = console->history_mode;
-    req->history_size  = console->history_size;
-    req->history_index = console->history_index;
-
+    reply->history_mode  = console->history_mode;
+    reply->history_size  = console->history_size;
+    reply->history_index = console->history_index;
     release_object( console );
 }
 
 /* get a console mode (input or output) */
 DECL_HANDLER(get_console_mode)
 {
-    req->mode = get_console_mode( req->handle );
+    reply->mode = get_console_mode( req->handle );
 }
 
 /* set a console mode (input or output) */
@@ -1112,47 +1218,39 @@
 {
     struct console_input *console;
 
-    req->written = 0;
+    reply->written = 0;
     if (!(console = (struct console_input *)get_handle_obj( current->process, req->handle,
                                                             GENERIC_WRITE, &console_input_ops )))
         return;
-
-    req->written = write_console_input( console, get_req_data_size(req) / sizeof(INPUT_RECORD),
-                                        get_req_data(req) );
+    reply->written = write_console_input( console, get_req_data_size() / sizeof(INPUT_RECORD),
+                                          get_req_data() );
     release_object( console );
 }
 
 /* fetch input records from a console input queue */
 DECL_HANDLER(read_console_input)
 {
-    size_t size = get_req_data_size(req) / sizeof(INPUT_RECORD);
-    int res = read_console_input( req->handle, size, get_req_data(req), req->flush );
-    /* if size was 0 we didn't fetch anything */
-    if (size) set_req_data_size( req, res * sizeof(INPUT_RECORD) );
-    req->read = res;
+    int count = get_reply_max_size() / sizeof(INPUT_RECORD);
+    reply->read = read_console_input( req->handle, count, req->flush );
 }
 
 /* appends a string to console's history */
 DECL_HANDLER(append_console_input_history)
 {
-    struct console_input*	console;
+    struct console_input *console;
 
     if (!(console = console_input_get( req->handle, GENERIC_WRITE ))) return;
-    console_input_append_hist( console, get_req_data(req), 
-			       get_req_data_size(req) / sizeof(WCHAR) );
+    console_input_append_hist( console, get_req_data(), get_req_data_size() / sizeof(WCHAR) );
     release_object( console );
 }
 
 /* appends a string to console's history */
 DECL_HANDLER(get_console_input_history)
 {
-    struct console_input*	console;
-    int len;
+    struct console_input *console;
 
     if (!(console = console_input_get( req->handle, GENERIC_WRITE ))) return;
-
-    len = console_input_get_hist( console, get_req_data(req), 0 /* FIXME */, req->index );
-    set_req_data_size( req, len * sizeof(WCHAR));
+    reply->total = console_input_get_hist( console, req->index );
     release_object( console );
 }
 
@@ -1164,14 +1262,14 @@
 
     if (!(console = console_input_get( req->handle_in, GENERIC_WRITE))) return;
 
-    screen_buffer = (struct screen_buffer*)create_console_output( console );
+    screen_buffer = create_console_output( console );
     if (screen_buffer)
     {
-	/* FIXME: should store sharing and test it when opening the CONOUT$ device 
-	 * see file.c on how this could be done
-	 */
-	req->handle_out = alloc_handle( current->process, screen_buffer, req->access, req->inherit );
-	release_object( screen_buffer );
+        /* FIXME: should store sharing and test it when opening the CONOUT$ device 
+         * see file.c on how this could be done */
+        reply->handle_out = alloc_handle( current->process, screen_buffer,
+                                          req->access, req->inherit );
+        release_object( screen_buffer );
     }
     release_object( console );
 }
@@ -1179,79 +1277,84 @@
 /* set info about a console screen buffer */
 DECL_HANDLER(set_console_output_info)
 {
-    struct screen_buffer       *screen_buffer;
+    struct screen_buffer *screen_buffer;
 
-    if (!(screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
-								 GENERIC_WRITE, &screen_buffer_ops )))
-	return;
-
-    set_console_output_info( screen_buffer, req );
-    release_object( screen_buffer );
+    if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
+                                                                GENERIC_WRITE, &screen_buffer_ops)))
+    {
+        set_console_output_info( screen_buffer, req );
+        release_object( screen_buffer );
+    }
 }
 
 /* get info about a console screen buffer */
 DECL_HANDLER(get_console_output_info)
 {
     struct screen_buffer *screen_buffer;
-    size_t len = 0;
 
     if ((screen_buffer = (struct screen_buffer *)get_handle_obj( current->process, req->handle,
-								 GENERIC_READ, &screen_buffer_ops )))
+                                                                 GENERIC_READ, &screen_buffer_ops)))
     {
-        req->cursor_size    = screen_buffer->cursor_size;
-        req->cursor_visible = screen_buffer->cursor_visible;
-	req->cursor_x       = screen_buffer->cursor.X;
-	req->cursor_y       = screen_buffer->cursor.Y;
-	req->width          = screen_buffer->width;
-	req->height         = screen_buffer->height;
-	req->attr           = screen_buffer->attr;
-	req->win_left       = screen_buffer->win.Left;
-	req->win_top        = screen_buffer->win.Top;
-	req->win_right      = screen_buffer->win.Right;
-	req->win_bottom     = screen_buffer->win.Bottom;
-	req->max_width      = screen_buffer->max_width;
-	req->max_height     = screen_buffer->max_height;
-
+        reply->cursor_size    = screen_buffer->cursor_size;
+        reply->cursor_visible = screen_buffer->cursor_visible;
+        reply->cursor_x       = screen_buffer->cursor_x;
+        reply->cursor_y       = screen_buffer->cursor_y;
+        reply->width          = screen_buffer->width;
+        reply->height         = screen_buffer->height;
+        reply->attr           = screen_buffer->attr;
+        reply->win_left       = screen_buffer->win.left;
+        reply->win_top        = screen_buffer->win.top;
+        reply->win_right      = screen_buffer->win.right;
+        reply->win_bottom     = screen_buffer->win.bottom;
+        reply->max_width      = screen_buffer->max_width;
+        reply->max_height     = screen_buffer->max_height;
         release_object( screen_buffer );
     }
-    set_req_data_size( req, len );
 }
 
 /* read data (chars & attrs) from a screen buffer */
 DECL_HANDLER(read_console_output)
 {
-    struct screen_buffer       *screen_buffer;
-    size_t 			size = get_req_data_size(req);
-    int				res;
+    struct screen_buffer *screen_buffer;
 
-    if (!(screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
-								 GENERIC_READ, &screen_buffer_ops )))
-	return;
-
-    res = read_console_output( screen_buffer, size, get_req_data(req), 
-			       req->x, req->y, req->w, req->h, &req->eff_w, &req->eff_h);
-    /* if size was 0 we didn't fetch anything */
-    if (size) set_req_data_size( req, res * 4 );
-    release_object( screen_buffer );
+    if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
+                                                                GENERIC_READ, &screen_buffer_ops )))
+    {
+        read_console_output( screen_buffer, req->x, req->y, req->mode, req->wrap );
+        reply->width  = screen_buffer->width;
+        reply->height = screen_buffer->height;
+        release_object( screen_buffer );
+    }
 }
 
 /* write data (char and/or attrs) to a screen buffer */
 DECL_HANDLER(write_console_output)
 {
-    struct screen_buffer       *screen_buffer;
-    size_t 			size = get_req_data_size(req);
-    int				res;
+    struct screen_buffer *screen_buffer;
 
-    if (!(screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
-								 GENERIC_WRITE, &screen_buffer_ops )))
-	return;
+    if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
+                                                                GENERIC_WRITE, &screen_buffer_ops)))
+    {
+        reply->written = write_console_output( screen_buffer, get_req_data_size(), get_req_data(),
+                                               req->mode, req->x, req->y, req->wrap );
+        reply->width  = screen_buffer->width;
+        reply->height = screen_buffer->height;
+        release_object( screen_buffer );
+    }
+}
 
-    res = write_console_output( screen_buffer, size, get_req_data(req), req->mode, req->x, req->y );
+/* fill a screen buffer with constant data (chars and/or attributes) */
+DECL_HANDLER(fill_console_output)
+{
+    struct screen_buffer *screen_buffer;
 
-    /* if size was 0 we didn't fetch anything */
-    if (size) set_req_data_size( req, res );
-    req->written = res;
-    release_object( screen_buffer );
+    if ((screen_buffer = (struct screen_buffer*)get_handle_obj( current->process, req->handle,
+                                                                GENERIC_WRITE, &screen_buffer_ops)))
+    {
+        reply->written = fill_console_output( screen_buffer, req->data, req->mode,
+                                              req->x, req->y, req->count, req->wrap );
+        release_object( screen_buffer );
+    }
 }
 
 /* move a rect of data in a screen buffer */
diff --git a/server/console.h b/server/console.h
index 88999a1..bde68ec 100644
--- a/server/console.h
+++ b/server/console.h
@@ -7,6 +7,8 @@
 #ifndef __WINE_SERVER_CONSOLE_H
 #define __WINE_SERVER_CONSOLE_H
 
+#include "wincon.h"
+
 struct screen_buffer;
 struct console_input_events;
 
@@ -18,7 +20,7 @@
     int                          mode;          /* input mode */
     struct screen_buffer        *active;        /* active screen buffer */
     int                          recnum;        /* number of input records */
-    void                        *records;       /* input records */
+    INPUT_RECORD                *records;       /* input records */
     struct console_input_events *evt;           /* synchronization event with renderer */
     WCHAR                       *title;         /* console title */
     WCHAR                      **history;       /* lines history */
diff --git a/server/context_i386.c b/server/context_i386.c
index 874d1dd..d72c89d 100644
--- a/server/context_i386.c
+++ b/server/context_i386.c
@@ -144,7 +144,7 @@
 
 
 /* set a thread context */
-static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
 {
     int pid = thread->unix_pid;
     if (flags & CONTEXT_FULL)
@@ -195,7 +195,6 @@
         /* we can use context->FloatSave directly as it is using the */
         /* correct structure (the same as fsave/frstor) */
         if (ptrace( PTRACE_SETFPREGS, pid, 0, &context->FloatSave ) == -1) goto error;
-        context->FloatSave.Cr0NpxState = 0;  /* FIXME */
     }
     return;
  error:
@@ -256,7 +255,7 @@
 
 
 /* set a thread context */
-static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
 {
     int pid = thread->unix_pid;
     if (flags & CONTEXT_FULL)
@@ -303,7 +302,6 @@
         /* we can use context->FloatSave directly as it is using the */
         /* correct structure (the same as fsave/frstor) */
         if (ptrace( PTRACE_SETFPREGS, pid, 0, (int) &context->FloatSave ) == -1) goto error;
-        context->FloatSave.Cr0NpxState = 0;  /* FIXME */
     }
     return;
  error:
@@ -365,7 +363,7 @@
 
 
 /* set a thread context */
-static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
 {
     int pid = thread->unix_pid;
     if (flags & CONTEXT_FULL)
@@ -412,7 +410,6 @@
         /* we can use context->FloatSave directly as it is using the */
         /* correct structure (the same as fsave/frstor) */
         if (ptrace( PTRACE_SETFPREGS, pid, 0, (int) &context->FloatSave ) == -1) goto error;
-        context->FloatSave.Cr0NpxState = 0;  /* FIXME */
     }
     return;
  error:
@@ -425,7 +422,7 @@
 
 
 /* copy a context structure according to the flags */
-static void copy_context( CONTEXT *to, CONTEXT *from, int flags )
+static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
 {
     if (flags & CONTEXT_CONTROL)
     {
@@ -486,27 +483,34 @@
 DECL_HANDLER(get_thread_context)
 {
     struct thread *thread;
+    void *data;
     int flags = req->flags & ~CONTEXT_i386;  /* get rid of CPU id */
 
-    if (get_req_data_size(req) < sizeof(CONTEXT))
+    if (get_reply_max_size() < sizeof(CONTEXT))
     {
         set_error( STATUS_INVALID_PARAMETER );
         return;
     }
-    if ((thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT )))
+    if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
+
+    if ((data = set_reply_data_size( sizeof(CONTEXT) )))
     {
+        /* copy incoming context into reply */
+        memset( data, 0, sizeof(CONTEXT) );
+        memcpy( data, get_req_data(), min( get_req_data_size(), sizeof(CONTEXT) ));
+
         if (thread->context)  /* thread is inside an exception event */
         {
-            copy_context( get_req_data(req), thread->context, flags );
+            copy_context( data, thread->context, flags );
             flags &= CONTEXT_DEBUG_REGISTERS;
         }
         if (flags && suspend_for_ptrace( thread ))
         {
-            get_thread_context( thread, flags, get_req_data(req) );
+            get_thread_context( thread, flags, data );
             resume_thread( thread );
         }
-        release_object( thread );
     }
+    release_object( thread );
 }
 
 
@@ -516,7 +520,7 @@
     struct thread *thread;
     int flags = req->flags & ~CONTEXT_i386;  /* get rid of CPU id */
 
-    if (get_req_data_size(req) < sizeof(CONTEXT))
+    if (get_req_data_size() < sizeof(CONTEXT))
     {
         set_error( STATUS_INVALID_PARAMETER );
         return;
@@ -525,12 +529,12 @@
     {
         if (thread->context)  /* thread is inside an exception event */
         {
-            copy_context( thread->context, get_req_data(req), flags );
+            copy_context( thread->context, get_req_data(), flags );
             flags &= CONTEXT_DEBUG_REGISTERS;
         }
         if (flags && suspend_for_ptrace( thread ))
         {
-            set_thread_context( thread, flags, get_req_data(req) );
+            set_thread_context( thread, flags, get_req_data() );
             resume_thread( thread );
         }
         release_object( thread );
diff --git a/server/context_sparc.c b/server/context_sparc.c
index d8d6b79..d8de535 100644
--- a/server/context_sparc.c
+++ b/server/context_sparc.c
@@ -78,7 +78,7 @@
 
 
 /* set a thread context */
-static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
 {
     /* FIXME */
 }
@@ -89,7 +89,7 @@
 
 
 /* copy a context structure according to the flags */
-static void copy_context( CONTEXT *to, CONTEXT *from, int flags )
+static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
 {
     if (flags & CONTEXT_CONTROL)
     {
@@ -164,27 +164,30 @@
 DECL_HANDLER(get_thread_context)
 {
     struct thread *thread;
+    void *data;
     int flags = req->flags & ~CONTEXT_SPARC;  /* get rid of CPU id */
 
-    if (get_req_data_size(req) < sizeof(CONTEXT))
+    if (get_reply_max_size() < sizeof(CONTEXT))
     {
         set_error( STATUS_INVALID_PARAMETER );
         return;
     }
-    if ((thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT )))
+    if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
+
+    if ((data = set_reply_data_size( sizeof(CONTEXT) )))
     {
         if (thread->context)  /* thread is inside an exception event */
         {
-            copy_context( get_req_data(req), thread->context, flags );
+            copy_context( data, thread->context, flags );
             flags = 0;
         }
         if (flags && suspend_for_ptrace( thread ))
         {
-            get_thread_context( thread, flags, get_req_data(req) );
+            get_thread_context( thread, flags, data );
             resume_thread( thread );
         }
-        release_object( thread );
     }
+    release_object( thread );
 }
 
 
@@ -194,7 +197,7 @@
     struct thread *thread;
     int flags = req->flags & ~CONTEXT_SPARC;  /* get rid of CPU id */
 
-    if (get_req_data_size(req) < sizeof(CONTEXT))
+    if (get_req_data_size() < sizeof(CONTEXT))
     {
         set_error( STATUS_INVALID_PARAMETER );
         return;
@@ -203,12 +206,12 @@
     {
         if (thread->context)  /* thread is inside an exception event */
         {
-            copy_context( thread->context, get_req_data(req), flags );
+            copy_context( thread->context, get_req_data(), flags );
             flags = 0;
         }
         if (flags && suspend_for_ptrace( thread ))
         {
-            set_thread_context( thread, flags, get_req_data(req) );
+            set_thread_context( thread, flags, get_req_data() );
             resume_thread( thread );
         }
         release_object( thread );
diff --git a/server/debugger.c b/server/debugger.c
index 09b4240..d4ea49d 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -353,7 +353,7 @@
 
 /* alloc a debug event for a debugger */
 static struct debug_event *alloc_debug_event( struct thread *thread, int code,
-                                              void *arg, CONTEXT *context )
+                                              void *arg, const CONTEXT *context )
 {
     struct thread *debugger = thread->process->debugger;
     struct debug_event *event;
@@ -498,25 +498,23 @@
         set_error( STATUS_INVALID_HANDLE );
         return;
     }
-    req->wait = 0;
+    reply->wait = 0;
     if ((event = find_event_to_send( debug_ctx )))
     {
-        size_t size = get_req_data_size(req);
+        size_t size = get_reply_max_size();
         event->state = EVENT_SENT;
         event->sender->debug_event = event;
-        req->pid = event->sender->process;
-        req->tid = event->sender;
+        reply->pid = event->sender->process;
+        reply->tid = event->sender;
         if (size > sizeof(debug_event_t)) size = sizeof(debug_event_t);
-        memcpy( get_req_data(req), &event->data, size );
-        set_req_data_size( req, size );
+        set_reply_data( &event->data, size );
     }
     else  /* no event ready */
     {
-        req->pid  = 0;
-        req->tid  = 0;
-        set_req_data_size( req, 0 );
+        reply->pid  = 0;
+        reply->tid  = 0;
         if (req->get_handle)
-            req->wait = alloc_handle( current->process, debug_ctx, SYNCHRONIZE, FALSE );
+            reply->wait = alloc_handle( current->process, debug_ctx, SYNCHRONIZE, FALSE );
     }
 }
 
@@ -562,15 +560,15 @@
 /* queue an exception event */
 DECL_HANDLER(queue_exception_event)
 {
-    req->handle = 0;
+    reply->handle = 0;
     if (current->process->debugger)
     {
         struct debug_event_exception data;
         struct debug_event *event;
-        CONTEXT *context = get_req_data( req );
+        const CONTEXT *context = get_req_data();
         EXCEPTION_RECORD *rec = (EXCEPTION_RECORD *)(context + 1);
 
-        if (get_req_data_size( req ) < sizeof(*rec) + sizeof(*context))
+        if (get_req_data_size() < sizeof(*rec) + sizeof(*context))
         {
             set_error( STATUS_INVALID_PARAMETER );
             return;
@@ -579,7 +577,7 @@
         data.first  = req->first;
         if ((event = alloc_debug_event( current, EXCEPTION_DEBUG_EVENT, &data, context )))
         {
-            if ((req->handle = alloc_handle( current->process, event, SYNCHRONIZE, FALSE )))
+            if ((reply->handle = alloc_handle( current->process, event, SYNCHRONIZE, FALSE )))
             {
                 link_event( event );
                 suspend_process( current->process );
@@ -593,26 +591,24 @@
 DECL_HANDLER(get_exception_status)
 {
     struct debug_event *event;
-    size_t size = 0;
 
-    req->status = 0;
+    reply->status = 0;
     if ((event = (struct debug_event *)get_handle_obj( current->process, req->handle,
                                                        0, &debug_event_ops )))
     {
         if (event->state == EVENT_CONTINUED)
         {
-            req->status = event->status;
+            reply->status = event->status;
             if (current->context == &event->context)
             {
-                size = min( sizeof(CONTEXT), get_req_data_size(req) );
-                memcpy( get_req_data(req), &event->context, size );
+                size_t size = min( sizeof(CONTEXT), get_reply_max_size() );
+                set_reply_data( &event->context, size );
                 current->context = NULL;
             }
         }
         else set_error( STATUS_PENDING );
         release_object( event );
     }
-    set_req_data_size( req, size );
 }
 
 /* send an output string to the debugger */
diff --git a/server/device.c b/server/device.c
index 80c6af5..6c37c19 100644
--- a/server/device.c
+++ b/server/device.c
@@ -29,7 +29,7 @@
 };
 
 static void device_dump( struct object *obj, int verbose );
-static int device_get_info( struct object *obj, struct get_file_info_request *req );
+static int device_get_info( struct object *obj, struct get_file_info_reply *reply );
 
 static const struct object_ops device_ops =
 {
@@ -64,23 +64,23 @@
     fprintf( stderr, "Device id=%08x\n", dev->id );
 }
 
-static int device_get_info( struct object *obj, struct get_file_info_request *req )
+static int device_get_info( struct object *obj, struct get_file_info_reply *reply )
 {
     struct device *dev = (struct device *)obj;
     assert( obj->ops == &device_ops );
 
-    if (req)
+    if (reply)
     {
-        req->type        = FILE_TYPE_UNKNOWN;
-        req->attr        = dev->id;  /* hack! */
-        req->access_time = 0;
-        req->write_time  = 0;
-        req->size_high   = 0;
-        req->size_low    = 0;
-        req->links       = 0;
-        req->index_high  = 0;
-        req->index_low   = 0;
-        req->serial      = 0;
+        reply->type        = FILE_TYPE_UNKNOWN;
+        reply->attr        = dev->id;  /* hack! */
+        reply->access_time = 0;
+        reply->write_time  = 0;
+        reply->size_high   = 0;
+        reply->size_low    = 0;
+        reply->links       = 0;
+        reply->index_high  = 0;
+        reply->index_low   = 0;
+        reply->serial      = 0;
     }
     return FD_TYPE_DEFAULT;
 }
@@ -90,10 +90,10 @@
 {
     struct device *dev;
 
-    req->handle = 0;
+    reply->handle = 0;
     if ((dev = create_device( req->id )))
     {
-        req->handle = alloc_handle( current->process, dev, req->access, req->inherit );
+        reply->handle = alloc_handle( current->process, dev, req->access, req->inherit );
         release_object( dev );
     }
 }
diff --git a/server/event.c b/server/event.c
index b7652fb..7318aef 100644
--- a/server/event.c
+++ b/server/event.c
@@ -115,11 +115,11 @@
 {
     struct event *event;
 
-    req->handle = 0;
-    if ((event = create_event( get_req_data(req), get_req_data_size(req),
+    reply->handle = 0;
+    if ((event = create_event( get_req_data(), get_req_data_size(),
                                req->manual_reset, req->initial_state )))
     {
-        req->handle = alloc_handle( current->process, event, EVENT_ALL_ACCESS, req->inherit );
+        reply->handle = alloc_handle( current->process, event, EVENT_ALL_ACCESS, req->inherit );
         release_object( event );
     }
 }
@@ -127,8 +127,8 @@
 /* open a handle to an event */
 DECL_HANDLER(open_event)
 {
-    req->handle = open_object( get_req_data(req), get_req_data_size(req),
-                               &event_ops, req->access, req->inherit );
+    reply->handle = open_object( get_req_data(), get_req_data_size(),
+                                 &event_ops, req->access, req->inherit );
 }
 
 /* do an event operation */
diff --git a/server/file.c b/server/file.c
index 6dde94c..ae9033c 100644
--- a/server/file.c
+++ b/server/file.c
@@ -49,7 +49,7 @@
 static int file_get_poll_events( struct object *obj );
 static int file_get_fd( struct object *obj );
 static int file_flush( struct object *obj );
-static int file_get_info( struct object *obj, struct get_file_info_request *req );
+static int file_get_info( struct object *obj, struct get_file_info_reply *reply );
 static void file_destroy( struct object *obj );
 
 static const struct object_ops file_ops =
@@ -271,13 +271,13 @@
     return ret;
 }
 
-static int file_get_info( struct object *obj, struct get_file_info_request *req )
+static int file_get_info( struct object *obj, struct get_file_info_reply *reply )
 {
     struct stat st;
     struct file *file = (struct file *)obj;
     assert( obj->ops == &file_ops );
 
-    if (req)
+    if (reply)
     {
         if (fstat( file->obj.fd, &st ) == -1)
         {
@@ -285,27 +285,27 @@
             return FD_TYPE_INVALID;
         }
         if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
-            S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) req->type = FILE_TYPE_CHAR;
-        else req->type = FILE_TYPE_DISK;
-        if (S_ISDIR(st.st_mode)) req->attr = FILE_ATTRIBUTE_DIRECTORY;
-        else req->attr = FILE_ATTRIBUTE_ARCHIVE;
-        if (!(st.st_mode & S_IWUSR)) req->attr |= FILE_ATTRIBUTE_READONLY;
-        req->access_time = st.st_atime;
-        req->write_time  = st.st_mtime;
+            S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) reply->type = FILE_TYPE_CHAR;
+        else reply->type = FILE_TYPE_DISK;
+        if (S_ISDIR(st.st_mode)) reply->attr = FILE_ATTRIBUTE_DIRECTORY;
+        else reply->attr = FILE_ATTRIBUTE_ARCHIVE;
+        if (!(st.st_mode & S_IWUSR)) reply->attr |= FILE_ATTRIBUTE_READONLY;
+        reply->access_time = st.st_atime;
+        reply->write_time  = st.st_mtime;
         if (S_ISDIR(st.st_mode))
         {
-            req->size_high = 0;
-            req->size_low  = 0;
+            reply->size_high = 0;
+            reply->size_low  = 0;
         }
         else
         {
-            req->size_high = st.st_size >> 32;
-            req->size_low  = st.st_size & 0xffffffff;
+            reply->size_high = st.st_size >> 32;
+            reply->size_low  = st.st_size & 0xffffffff;
         }
-        req->links       = st.st_nlink;
-        req->index_high  = st.st_dev;
-        req->index_low   = st.st_ino;
-        req->serial      = 0; /* FIXME */
+        reply->links       = st.st_nlink;
+        reply->index_high  = st.st_dev;
+        reply->index_low   = st.st_ino;
+        reply->serial      = 0; /* FIXME */
     }
     return FD_TYPE_DEFAULT;
 }
@@ -470,11 +470,11 @@
 {
     struct file *file;
 
-    req->handle = 0;
-    if ((file = create_file( get_req_data(req), get_req_data_size(req), req->access,
+    reply->handle = 0;
+    if ((file = create_file( get_req_data(), get_req_data_size(), req->access,
                              req->sharing, req->create, req->attrs, req->drive_type )))
     {
-        req->handle = alloc_handle( current->process, file, req->access, req->inherit );
+        reply->handle = alloc_handle( current->process, file, req->access, req->inherit );
         release_object( file );
     }
 }
@@ -485,7 +485,7 @@
     struct file *file;
     int fd;
 
-    req->handle = 0;
+    reply->handle = 0;
     if ((fd = thread_get_inflight_fd( current, req->fd )) == -1)
     {
         set_error( STATUS_INVALID_HANDLE );
@@ -494,7 +494,7 @@
     if ((file = create_file_for_fd( fd, req->access, FILE_SHARE_READ | FILE_SHARE_WRITE,
                                     0, DRIVE_UNKNOWN )))
     {
-        req->handle = alloc_handle( current->process, file, req->access, req->inherit );
+        reply->handle = alloc_handle( current->process, file, req->access, req->inherit );
         release_object( file );
     }
 }
@@ -504,18 +504,18 @@
 {
     struct object *obj;
 
-    req->fd = -1;
-    req->type = FD_TYPE_INVALID;
+    reply->fd = -1;
+    reply->type = FD_TYPE_INVALID;
     if ((obj = get_handle_obj( current->process, req->handle, req->access, NULL )))
     {
         int fd = get_handle_fd( current->process, req->handle, req->access );
-        if (fd != -1) req->fd = fd;
+        if (fd != -1) reply->fd = fd;
         else if (!get_error())
         {
             if ((fd = obj->ops->get_fd( obj )) != -1)
                 send_client_fd( current->process, fd, req->handle );
         }
-        req->type = obj->ops->get_file_info( obj, NULL );
+        reply->type = obj->ops->get_file_info( obj, NULL );
         release_object( obj );
     }
 }
@@ -526,8 +526,8 @@
     int high = req->high;
     int low  = req->low;
     set_file_pointer( req->handle, &low, &high, req->whence );
-    req->new_low  = low;
-    req->new_high = high;
+    reply->new_low  = low;
+    reply->new_high = high;
 }
 
 /* truncate (or extend) a file */
@@ -561,7 +561,7 @@
 
     if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
     {
-        obj->ops->get_file_info( obj, req );
+        obj->ops->get_file_info( obj, reply );
         release_object( obj );
     }
 }
diff --git a/server/handle.c b/server/handle.c
index ac4235f..f4b004f 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -355,7 +355,6 @@
         if (!(entry = get_handle( process, handle ))) return NULL;
         if ((entry->access & access) != access)
         {
-            fprintf( stderr, "handle %d access %08x denied (%08x)\n", handle, access, entry->access );
             set_error( STATUS_ACCESS_DENIED );
             return NULL;
         }
@@ -377,7 +376,6 @@
     if (!(entry = get_handle( process, handle ))) return -1;
     if ((entry->access & access) != access)
     {
-        fprintf( stderr, "handle %d access %08x denied (%08x)\n", handle, access, entry->access );
         set_error( STATUS_ACCESS_DENIED );
         return -1;
     }
@@ -459,7 +457,7 @@
 /* close a handle */
 DECL_HANDLER(close_handle)
 {
-    close_handle( current->process, req->handle, &req->fd );
+    close_handle( current->process, req->handle, &reply->fd );
 }
 
 /* set a handle information */
@@ -468,8 +466,9 @@
     int fd = req->fd;
 
     if (handle_is_global(req->handle)) fd = -1;  /* no fd cache for global handles */
-    req->old_flags = set_handle_info( current->process, req->handle, req->mask, req->flags, &fd );
-    req->cur_fd = fd;
+    reply->old_flags = set_handle_info( current->process, req->handle,
+                                        req->mask, req->flags, &fd );
+    reply->cur_fd = fd;
 }
 
 /* duplicate a handle */
@@ -477,25 +476,25 @@
 {
     struct process *src, *dst;
 
-    req->handle = 0;
-    req->fd = -1;
+    reply->handle = 0;
+    reply->fd = -1;
     if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE )))
     {
         if (req->options & DUP_HANDLE_MAKE_GLOBAL)
         {
-            req->handle = duplicate_handle( src, req->src_handle, NULL,
-                                            req->access, req->inherit, req->options );
+            reply->handle = duplicate_handle( src, req->src_handle, NULL,
+                                              req->access, req->inherit, req->options );
         }
         else if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE )))
         {
-            req->handle = duplicate_handle( src, req->src_handle, dst,
-                                            req->access, req->inherit, req->options );
+            reply->handle = duplicate_handle( src, req->src_handle, dst,
+                                              req->access, req->inherit, req->options );
             release_object( dst );
         }
         /* close the handle no matter what happened */
         if (req->options & DUP_HANDLE_CLOSE_SOURCE)
         {
-            if (src == current->process) close_handle( src, req->src_handle, &req->fd );
+            if (src == current->process) close_handle( src, req->src_handle, &reply->fd );
             else close_handle( src, req->src_handle, NULL );
         }
         release_object( src );
diff --git a/server/mapping.c b/server/mapping.c
index fd8194a..8f4508b 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -34,7 +34,7 @@
 };
 
 static int mapping_get_fd( struct object *obj );
-static int mapping_get_info( struct object *obj, struct get_file_info_request *req );
+static int mapping_get_info( struct object *obj, struct get_file_info_reply *reply );
 static void mapping_dump( struct object *obj, int verbose );
 static void mapping_destroy( struct object *obj );
 
@@ -263,11 +263,11 @@
         }
         if (!size_high && !size_low)
         {
-            struct get_file_info_request req;
+            struct get_file_info_reply reply;
             struct object *obj = (struct object *)mapping->file;
-            obj->ops->get_file_info( obj, &req );
-            size_high = req.size_high;
-            size_low  = ROUND_SIZE( 0, req.size_low );
+            obj->ops->get_file_info( obj, &reply );
+            size_high = reply.size_high;
+            size_low  = ROUND_SIZE( 0, reply.size_low );
         }
         else if (!grow_file( mapping->file, size_high, size_low )) goto error;
     }
@@ -311,14 +311,14 @@
     return get_mmap_fd( mapping->file );
 }
 
-static int mapping_get_info( struct object *obj, struct get_file_info_request *req )
+static int mapping_get_info( struct object *obj, struct get_file_info_reply *reply )
 {
     struct mapping *mapping = (struct mapping *)obj;
     struct object *file = (struct object *)mapping->file;
 
     assert( obj->ops == &mapping_ops );
     assert( file );
-    return file->ops->get_file_info( file, req );
+    return file->ops->get_file_info( file, reply );
 }
 
 static void mapping_destroy( struct object *obj )
@@ -346,14 +346,14 @@
 {
     struct object *obj;
 
-    req->handle = 0;
+    reply->handle = 0;
     if ((obj = create_mapping( req->size_high, req->size_low,
                                req->protect, req->file_handle,
-                               get_req_data(req), get_req_data_size(req) )))
+                               get_req_data(), get_req_data_size() )))
     {
         int access = FILE_MAP_ALL_ACCESS;
         if (!(req->protect & VPROT_WRITE)) access &= ~FILE_MAP_WRITE;
-        req->handle = alloc_handle( current->process, obj, access, req->inherit );
+        reply->handle = alloc_handle( current->process, obj, access, req->inherit );
         release_object( obj );
     }
 }
@@ -361,8 +361,8 @@
 /* open a handle to a mapping */
 DECL_HANDLER(open_mapping)
 {
-    req->handle = open_object( get_req_data(req), get_req_data_size(req),
-                               &mapping_ops, req->access, req->inherit );
+    reply->handle = open_object( get_req_data(), get_req_data_size(),
+                                 &mapping_ops, req->access, req->inherit );
 }
 
 /* get a mapping information */
@@ -373,17 +373,17 @@
     if ((mapping = (struct mapping *)get_handle_obj( current->process, req->handle,
                                                      0, &mapping_ops )))
     {
-        req->size_high   = mapping->size_high;
-        req->size_low    = mapping->size_low;
-        req->protect     = mapping->protect;
-        req->header_size = mapping->header_size;
-        req->base        = mapping->base;
-        req->shared_file = 0;
-        req->shared_size = mapping->shared_size;
-        req->drive_type  = get_file_drive_type( mapping->file );
+        reply->size_high   = mapping->size_high;
+        reply->size_low    = mapping->size_low;
+        reply->protect     = mapping->protect;
+        reply->header_size = mapping->header_size;
+        reply->base        = mapping->base;
+        reply->shared_file = 0;
+        reply->shared_size = mapping->shared_size;
+        reply->drive_type  = get_file_drive_type( mapping->file );
         if (mapping->shared_file)
-            req->shared_file = alloc_handle( current->process, mapping->shared_file,
-                                             GENERIC_READ|GENERIC_WRITE, 0 );
+            reply->shared_file = alloc_handle( current->process, mapping->shared_file,
+                                               GENERIC_READ|GENERIC_WRITE, 0 );
         release_object( mapping );
     }
 }
diff --git a/server/mutex.c b/server/mutex.c
index 54f9052..ee145d9 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -140,10 +140,10 @@
 {
     struct mutex *mutex;
 
-    req->handle = 0;
-    if ((mutex = create_mutex( get_req_data(req), get_req_data_size(req), req->owned )))
+    reply->handle = 0;
+    if ((mutex = create_mutex( get_req_data(), get_req_data_size(), req->owned )))
     {
-        req->handle = alloc_handle( current->process, mutex, MUTEX_ALL_ACCESS, req->inherit );
+        reply->handle = alloc_handle( current->process, mutex, MUTEX_ALL_ACCESS, req->inherit );
         release_object( mutex );
     }
 }
@@ -151,8 +151,8 @@
 /* open a handle to a mutex */
 DECL_HANDLER(open_mutex)
 {
-    req->handle = open_object( get_req_data(req), get_req_data_size(req),
-                               &mutex_ops, req->access, req->inherit );
+    reply->handle = open_object( get_req_data(), get_req_data_size(),
+                                 &mutex_ops, req->access, req->inherit );
 }
 
 /* release a mutex */
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 57013d9..0635039 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -86,7 +86,7 @@
 static void pipe_user_dump( struct object *obj, int verbose );
 static void pipe_user_destroy( struct object *obj);
 static int pipe_user_get_fd( struct object *obj );
-static int pipe_user_get_info( struct object *obj, struct get_file_info_request *req );
+static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply );
 
 static const struct object_ops pipe_user_ops =
 {
@@ -180,20 +180,20 @@
     return user->obj.fd;
 }
 
-static int pipe_user_get_info( struct object *obj, struct get_file_info_request *req )
+static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply )
 {
-    if (req)
+    if (reply)
     {
-        req->type        = FILE_TYPE_PIPE;
-        req->attr        = 0;
-        req->access_time = 0;
-        req->write_time  = 0;
-        req->size_high   = 0;
-        req->size_low    = 0;
-        req->links       = 0;
-        req->index_high  = 0;
-        req->index_low   = 0;
-        req->serial      = 0;
+        reply->type        = FILE_TYPE_PIPE;
+        reply->attr        = 0;
+        reply->access_time = 0;
+        reply->write_time  = 0;
+        reply->size_high   = 0;
+        reply->size_low    = 0;
+        reply->links       = 0;
+        reply->index_high  = 0;
+        reply->index_low   = 0;
+        reply->serial      = 0;
     }
     return FD_TYPE_DEFAULT;
 }
@@ -265,8 +265,8 @@
     struct named_pipe *pipe;
     struct pipe_user *user;
 
-    req->handle = 0;
-    pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
+    reply->handle = 0;
+    pipe = create_named_pipe( get_req_data(), get_req_data_size() );
     if(!pipe)
         return;
 
@@ -284,7 +284,7 @@
     if(user)
     {
         user->state = ps_idle_server;
-        req->handle = alloc_handle( current->process, user, GENERIC_READ|GENERIC_WRITE, 0 );
+        reply->handle = alloc_handle( current->process, user, GENERIC_READ|GENERIC_WRITE, 0 );
         release_object( user );
     }
 
@@ -295,8 +295,8 @@
 {
     struct named_pipe *pipe;
 
-    req->handle = 0;
-    pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
+    reply->handle = 0;
+    pipe = create_named_pipe( get_req_data(), get_req_data_size() );
     if(!pipe)
         return;
 
@@ -320,7 +320,7 @@
                     partner->other = user;
                     user->state = ps_connected_client;
                     user->other = partner;
-                    req->handle = alloc_handle( current->process, user, req->access, 0 );
+                    reply->handle = alloc_handle( current->process, user, req->access, 0 );
                     release_object(user);
                 }
                 else
@@ -378,7 +378,7 @@
 {
     struct named_pipe *pipe;
 
-    pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
+    pipe = create_named_pipe( get_req_data(), get_req_data_size() );
     if( pipe )
     {
         /* only wait if the pipe already exists */
@@ -448,10 +448,10 @@
     if(!user)
         return;
 
-    req->flags        = user->pipe->pipemode;
-    req->maxinstances = user->pipe->maxinstances;
-    req->insize       = user->pipe->insize;
-    req->outsize      = user->pipe->outsize;
+    reply->flags        = user->pipe->pipemode;
+    reply->maxinstances = user->pipe->maxinstances;
+    reply->insize       = user->pipe->insize;
+    reply->outsize      = user->pipe->outsize;
 
     release_object(user);
 }
diff --git a/server/object.c b/server/object.c
index a6dd908..1077006 100644
--- a/server/object.c
+++ b/server/object.c
@@ -263,7 +263,7 @@
     return 0;
 }
 
-int no_get_file_info( struct object *obj, struct get_file_info_request *info )
+int no_get_file_info( struct object *obj, struct get_file_info_reply *info )
 {
     set_error( STATUS_OBJECT_TYPE_MISMATCH );
     return FD_TYPE_INVALID;
diff --git a/server/object.h b/server/object.h
index 09641d3..c805b51 100644
--- a/server/object.h
+++ b/server/object.h
@@ -47,7 +47,7 @@
     /* flush the object buffers */
     int  (*flush)(struct object *);
     /* get file information */
-    int  (*get_file_info)(struct object *,struct get_file_info_request *);
+    int  (*get_file_info)(struct object *,struct get_file_info_reply *);
     /* destroy on refcount == 0 */
     void (*destroy)(struct object *);
 };
@@ -89,7 +89,7 @@
 extern int no_satisfied( struct object *obj, struct thread *thread );
 extern int no_get_fd( struct object *obj );
 extern int no_flush( struct object *obj );
-extern int no_get_file_info( struct object *obj, struct get_file_info_request *info );
+extern int no_get_file_info( struct object *obj, struct get_file_info_reply *info );
 extern void no_destroy( struct object *obj );
 extern int default_poll_add_queue( struct object *obj, struct wait_queue_entry *entry );
 extern void default_poll_remove_queue( struct object *obj, struct wait_queue_entry *entry );
@@ -103,7 +103,7 @@
 
 extern int add_select_user( struct object *obj );
 extern void remove_select_user( struct object *obj );
-extern void change_select_fd( struct object *obj, int fd );
+extern void change_select_fd( struct object *obj, int fd, int events );
 extern void set_select_events( struct object *obj, int events );
 extern int check_select_events( int fd, int events );
 extern void select_loop(void);
diff --git a/server/pipe.c b/server/pipe.c
index d1b2d42..ddd200b 100644
--- a/server/pipe.c
+++ b/server/pipe.c
@@ -37,7 +37,7 @@
 static void pipe_dump( struct object *obj, int verbose );
 static int pipe_get_poll_events( struct object *obj );
 static int pipe_get_fd( struct object *obj );
-static int pipe_get_info( struct object *obj, struct get_file_info_request *req );
+static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply );
 static void pipe_destroy( struct object *obj );
 
 static const struct object_ops pipe_ops =
@@ -124,20 +124,20 @@
     return pipe->obj.fd;
 }
 
-static int pipe_get_info( struct object *obj, struct get_file_info_request *req )
+static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply )
 {
-    if (req)
+    if (reply)
     {
-        req->type        = FILE_TYPE_PIPE;
-        req->attr        = 0;
-        req->access_time = 0;
-        req->write_time  = 0;
-        req->size_high   = 0;
-        req->size_low    = 0;
-        req->links       = 0;
-        req->index_high  = 0;
-        req->index_low   = 0;
-        req->serial      = 0;
+        reply->type        = FILE_TYPE_PIPE;
+        reply->attr        = 0;
+        reply->access_time = 0;
+        reply->write_time  = 0;
+        reply->size_high   = 0;
+        reply->size_low    = 0;
+        reply->links       = 0;
+        reply->index_high  = 0;
+        reply->index_low   = 0;
+        reply->serial      = 0;
     }
     return FD_TYPE_DEFAULT;
 }
@@ -171,6 +171,6 @@
         release_object( obj[0] );
         release_object( obj[1] );
     }
-    req->handle_read  = hread;
-    req->handle_write = hwrite;
+    reply->handle_read  = hread;
+    reply->handle_write = hwrite;
 }
diff --git a/server/process.c b/server/process.c
index f02f5b7..5a5241d 100644
--- a/server/process.c
+++ b/server/process.c
@@ -98,7 +98,7 @@
 
 /* set the console and stdio handles for a newly created process */
 static int set_process_console( struct process *process, struct process *parent,
-                                struct startup_info *info, struct init_process_request *req )
+                                struct startup_info *info, struct init_process_reply *reply )
 {
     if (process->create_flags & CREATE_NEW_CONSOLE)
     {
@@ -120,35 +120,35 @@
         if (!info->inherit_all && !(info->start_flags & STARTF_USESTDHANDLES))
         {
             /* duplicate the handle from the parent into this process */
-            req->hstdin  = duplicate_handle( parent, info->hstdin, process,
-                                             0, TRUE, DUPLICATE_SAME_ACCESS );
-            req->hstdout = duplicate_handle( parent, info->hstdout, process,
-                                             0, TRUE, DUPLICATE_SAME_ACCESS );
-            req->hstderr = duplicate_handle( parent, info->hstderr, process,
-                                             0, TRUE, DUPLICATE_SAME_ACCESS );
+            reply->hstdin  = duplicate_handle( parent, info->hstdin, process,
+                                               0, TRUE, DUPLICATE_SAME_ACCESS );
+            reply->hstdout = duplicate_handle( parent, info->hstdout, process,
+                                               0, TRUE, DUPLICATE_SAME_ACCESS );
+            reply->hstderr = duplicate_handle( parent, info->hstderr, process,
+                                               0, TRUE, DUPLICATE_SAME_ACCESS );
         }
         else
         {
-            req->hstdin  = info->hstdin;
-            req->hstdout = info->hstdout;
-            req->hstderr = info->hstderr;
+            reply->hstdin  = info->hstdin;
+            reply->hstdout = info->hstdout;
+            reply->hstderr = info->hstderr;
         }
     }
     else
     {
         if (process->console)
         {
-            req->hstdin  = alloc_handle( process, process->console,
-                                         GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
-            req->hstdout = alloc_handle( process, process->console->active,
-                                         GENERIC_READ | GENERIC_WRITE, 1 );
-            req->hstderr = alloc_handle( process, process->console->active,
-                                         GENERIC_READ | GENERIC_WRITE, 1 );
+            reply->hstdin  = alloc_handle( process, process->console,
+                                           GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
+            reply->hstdout = alloc_handle( process, process->console->active,
+                                           GENERIC_READ | GENERIC_WRITE, 1 );
+            reply->hstderr = alloc_handle( process, process->console->active,
+                                           GENERIC_READ | GENERIC_WRITE, 1 );
         }
         else
         {
             /* no parent, let the caller decide what to do */
-            req->hstdin = req->hstdout = req->hstderr = 0;
+            reply->hstdin = reply->hstdout = reply->hstderr = 0;
         }
     }
     /* some handles above may have been invalid; this is not an error */
@@ -216,7 +216,7 @@
 }
 
 /* initialize the current process and fill in the request */
-static void init_process( int ppid, struct init_process_request *req )
+static void init_process( int ppid, struct init_process_reply *reply )
 {
     struct process *process = current->process;
     struct thread *parent_thread = get_thread_from_pid( ppid );
@@ -251,16 +251,16 @@
     if (!process->handles) return;
 
     /* retrieve the main exe file */
-    req->exe_file = 0;
+    reply->exe_file = 0;
     if (parent && info->exe_file)
     {
         process->exe.file = (struct file *)grab_object( info->exe_file );
-        if (!(req->exe_file = alloc_handle( process, process->exe.file, GENERIC_READ, 0 )))
+        if (!(reply->exe_file = alloc_handle( process, process->exe.file, GENERIC_READ, 0 )))
             return;
     }
 
     /* set the process console */
-    if (!set_process_console( process, parent, info, req )) return;
+    if (!set_process_console( process, parent, info, reply )) return;
 
     if (parent)
     {
@@ -277,23 +277,21 @@
     if (info)
     {
         size_t size = strlen(info->filename);
-        if (size > get_req_data_size(req)) size = get_req_data_size(req);
-        req->start_flags = info->start_flags;
-        req->cmd_show    = info->cmd_show;
-        memcpy( get_req_data(req), info->filename, size );
-        set_req_data_size( req, size );
+        if (size > get_reply_max_size()) size = get_reply_max_size();
+        reply->start_flags = info->start_flags;
+        reply->cmd_show    = info->cmd_show;
+        set_reply_data( info->filename, size );
         info->process = (struct process *)grab_object( process );
         info->thread  = (struct thread *)grab_object( current );
         wake_up( &info->obj, 0 );
     }
     else
     {
-        req->start_flags  = STARTF_USESTDHANDLES;
-        req->cmd_show     = 0;
-        set_req_data_size( req, 0 );
+        reply->start_flags  = STARTF_USESTDHANDLES;
+        reply->cmd_show     = 0;
     }
-    req->create_flags = process->create_flags;
-    req->server_start = server_start_ticks;
+    reply->create_flags = process->create_flags;
+    reply->server_start = server_start_ticks;
 }
 
 /* destroy a process when its refcount is 0 */
@@ -577,19 +575,19 @@
 
 
 /* get all information about a process */
-static void get_process_info( struct process *process, struct get_process_info_request *req )
+static void get_process_info( struct process *process, struct get_process_info_reply *reply )
 {
-    req->pid              = process;
-    req->debugged         = (process->debugger != 0);
-    req->exit_code        = process->exit_code;
-    req->priority         = process->priority;
-    req->process_affinity = process->affinity;
-    req->system_affinity  = 1;
+    reply->pid              = process;
+    reply->debugged         = (process->debugger != 0);
+    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 */
 static void set_process_info( struct process *process,
-                              struct set_process_info_request *req )
+                              const struct set_process_info_request *req )
 {
     if (req->mask & SET_PROCESS_INFO_PRIORITY)
         process->priority = req->priority;
@@ -601,62 +599,56 @@
 }
 
 /* read data from a process memory space */
-/* len is the total size (in ints), max is the size we can actually store in the output buffer */
-/* we read the total size in all cases to check for permissions */
-static void read_process_memory( struct process *process, const int *addr,
-                                 size_t len, size_t max, int *dest )
+/* len is the total size (in ints) */
+static int read_process_memory( struct process *process, const int *addr, size_t len, int *dest )
 {
     struct thread *thread = process->thread_list;
 
-    if ((unsigned int)addr % sizeof(int))  /* address must be aligned */
-    {
-        set_error( STATUS_INVALID_PARAMETER );
-        return;
-    }
+    assert( !((unsigned int)addr % sizeof(int)) );  /* address must be aligned */
+
     if (!thread)  /* process is dead */
     {
         set_error( STATUS_ACCESS_DENIED );
-        return;
+        return 0;
     }
     if (suspend_for_ptrace( thread ))
     {
-        while (len > 0 && max)
+        while (len > 0)
         {
-            if (read_thread_int( thread, addr++, dest++ ) == -1) goto done;
-            max--;
+            if (read_thread_int( thread, addr++, dest++ ) == -1) break;
             len--;
         }
-        /* check the rest for read permission */
-        if (len > 0)
-        {
-            int dummy, page = get_page_size() / sizeof(int);
-            while (len >= page)
-            {
-                addr += page;
-                len -= page;
-                if (read_thread_int( thread, addr - 1, &dummy ) == -1) goto done;
-            }
-            if (len && (read_thread_int( thread, addr + len - 1, &dummy ) == -1)) goto done;
-        }
-    done:
         resume_thread( thread );
     }
+    return !len;
+}
+
+/* make sure we can write to the whole address range */
+/* len is the total size (in ints) */
+static int check_process_write_access( struct thread *thread, int *addr, size_t len )
+{
+    int page = get_page_size() / sizeof(int);
+
+    for (;;)
+    {
+        if (write_thread_int( thread, addr, 0, 0 ) == -1) return 0;
+        if (len <= page) break;
+        addr += page;
+        len -= page;
+    }
+    return (write_thread_int( thread, addr + len - 1, 0, 0 ) != -1);
 }
 
 /* write data to a process memory space */
 /* len is the total size (in ints), max is the size we can actually read from the input buffer */
 /* we check the total size for write permissions */
 static void write_process_memory( struct process *process, int *addr, size_t len,
-                                  size_t max, unsigned int first_mask,
-                                  unsigned int last_mask, const int *src )
+                                  unsigned int first_mask, unsigned int last_mask, const int *src )
 {
     struct thread *thread = process->thread_list;
 
-    if (!len || ((unsigned int)addr % sizeof(int)))  /* address must be aligned */
-    {
-        set_error( STATUS_INVALID_PARAMETER );
-        return;
-    }
+    assert( !((unsigned int)addr % sizeof(int) ));  /* address must be aligned */
+
     if (!thread)  /* process is dead */
     {
         set_error( STATUS_ACCESS_DENIED );
@@ -664,39 +656,28 @@
     }
     if (suspend_for_ptrace( thread ))
     {
+        if (!check_process_write_access( thread, addr, len ))
+        {
+            set_error( STATUS_ACCESS_DENIED );
+            return;
+        }
         /* first word is special */
         if (len > 1)
         {
             if (write_thread_int( thread, addr++, *src++, first_mask ) == -1) goto done;
             len--;
-            max--;
         }
         else last_mask &= first_mask;
 
-        while (len > 1 && max)
+        while (len > 1)
         {
             if (write_thread_int( thread, addr++, *src++, ~0 ) == -1) goto done;
-            max--;
             len--;
         }
 
-        if (max)
-        {
-            /* last word is special too */
-            if (write_thread_int( thread, addr, *src, last_mask ) == -1) goto done;
-        }
-        else
-        {
-            /* check the rest for write permission */
-            int page = get_page_size() / sizeof(int);
-            while (len >= page)
-            {
-                addr += page;
-                len -= page;
-                if (write_thread_int( thread, addr - 1, 0, 0 ) == -1) goto done;
-            }
-            if (len && (write_thread_int( thread, addr + len - 1, 0, 0 ) == -1)) goto done;
-        }
+        /* last word is special too */
+        if (write_thread_int( thread, addr, *src, last_mask ) == -1) goto done;
+
     done:
         resume_thread( thread );
     }
@@ -747,7 +728,7 @@
 /* create a new process */
 DECL_HANDLER(new_process)
 {
-    size_t len = get_req_data_size( req );
+    size_t len = get_req_data_size();
     struct startup_info *info;
 
     if (current->info)
@@ -777,10 +758,10 @@
 
     if (!(info->filename = mem_alloc( len + 1 ))) goto done;
 
-    memcpy( info->filename, get_req_data(req), len );
+    memcpy( info->filename, get_req_data(), len );
     info->filename[len] = 0;
     current->info = info;
-    req->info = alloc_handle( current->process, info, SYNCHRONIZE, FALSE );
+    reply->info = alloc_handle( current->process, info, SYNCHRONIZE, FALSE );
 
  done:
     release_object( info );
@@ -791,28 +772,28 @@
 {
     struct startup_info *info;
 
-    req->event = 0;
+    reply->event = 0;
 
     if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
                                                        0, &startup_info_ops )))
     {
-        req->pid = get_process_id( info->process );
-        req->tid = get_thread_id( info->thread );
-        req->phandle = alloc_handle( current->process, info->process,
-                                     PROCESS_ALL_ACCESS, req->pinherit );
-        req->thandle = alloc_handle( current->process, info->thread,
-                                     THREAD_ALL_ACCESS, req->tinherit );
+        reply->pid = get_process_id( info->process );
+        reply->tid = get_thread_id( info->thread );
+        reply->phandle = alloc_handle( current->process, info->process,
+                                       PROCESS_ALL_ACCESS, req->pinherit );
+        reply->thandle = alloc_handle( current->process, info->thread,
+                                       THREAD_ALL_ACCESS, req->tinherit );
         if (info->process->init_event)
-            req->event = alloc_handle( current->process, info->process->init_event,
+            reply->event = alloc_handle( current->process, info->process->init_event,
                                        EVENT_ALL_ACCESS, 0 );
         release_object( info );
     }
     else
     {
-        req->pid     = 0;
-        req->tid     = 0;
-        req->phandle = 0;
-        req->thandle = 0;
+        reply->pid     = 0;
+        reply->tid     = 0;
+        reply->phandle = 0;
+        reply->thandle = 0;
     }
 }
 
@@ -825,7 +806,7 @@
         return;
     }
     current->process->ldt_copy  = req->ldt_copy;
-    init_process( req->ppid, req );
+    init_process( req->ppid, reply );
 }
 
 /* signal the end of the process initialization */
@@ -852,17 +833,17 @@
     process->init_event = NULL;
     if (req->gui) process->idle_event = create_event( NULL, 0, 1, 0 );
     if (current->suspend + current->process->suspend > 0) stop_thread( current );
-    req->debugged = (current->process->debugger != 0);
+    reply->debugged = (current->process->debugger != 0);
 }
 
 /* open a handle to a process */
 DECL_HANDLER(open_process)
 {
     struct process *process = get_process_from_id( req->pid );
-    req->handle = 0;
+    reply->handle = 0;
     if (process)
     {
-        req->handle = alloc_handle( current->process, process, req->access, req->inherit );
+        reply->handle = alloc_handle( current->process, process, req->access, req->inherit );
         release_object( process );
     }
 }
@@ -874,7 +855,7 @@
 
     if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE )))
     {
-        req->self = (current->process == process);
+        reply->self = (current->process == process);
         kill_process( process, current, req->exit_code );
         release_object( process );
     }
@@ -887,7 +868,7 @@
 
     if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
     {
-        get_process_info( process, req );
+        get_process_info( process, reply );
         release_object( process );
     }
 }
@@ -908,13 +889,28 @@
 DECL_HANDLER(read_process_memory)
 {
     struct process *process;
+    size_t len = get_reply_max_size();
 
-    if ((process = get_process_from_handle( req->handle, PROCESS_VM_READ )))
+    if (!(process = get_process_from_handle( req->handle, PROCESS_VM_READ ))) return;
+
+    if (len)
     {
-        size_t maxlen = get_req_data_size(req) / sizeof(int);
-        read_process_memory( process, req->addr, req->len, maxlen, get_req_data(req) );
-        release_object( process );
+        unsigned int start_offset = (unsigned int)req->addr % sizeof(int);
+        unsigned int nb_ints = (len + start_offset + sizeof(int) - 1) / sizeof(int);
+        const int *start = (int *)((char *)req->addr - start_offset);
+        int *buffer = mem_alloc( nb_ints * sizeof(int) );
+        if (buffer)
+        {
+            if (read_process_memory( process, start, nb_ints, buffer ))
+            {
+                /* move start of requested data to start of buffer */
+                if (start_offset) memmove( buffer, (char *)buffer + start_offset, len );
+                set_reply_data_ptr( buffer, len );
+            }
+            else len = 0;
+        }
     }
+    release_object( process );
 }
 
 /* write data to a process address space */
@@ -924,9 +920,14 @@
 
     if ((process = get_process_from_handle( req->handle, PROCESS_VM_WRITE )))
     {
-        size_t maxlen = get_req_data_size(req) / sizeof(int);
-        write_process_memory( process, req->addr, req->len, maxlen,
-                              req->first_mask, req->last_mask, get_req_data(req) );
+        size_t len = get_req_data_size();
+        if ((len % sizeof(int)) || ((unsigned int)req->addr % sizeof(int)))
+            set_error( STATUS_INVALID_PARAMETER );
+        else
+        {
+            if (len) write_process_memory( process, req->addr, len / sizeof(int),
+                                           req->first_mask, req->last_mask, get_req_data() );
+        }
         release_object( process );
     }
 }
@@ -964,12 +965,12 @@
 {
     struct process *process;
 
-    req->event = 0;
+    reply->event = 0;
     if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
     {
         if (process->idle_event && process != current->process && process->queue != current->queue)
-            req->event = alloc_handle( current->process, process->idle_event,
-                                       EVENT_ALL_ACCESS, 0 );
+            reply->event = alloc_handle( current->process, process->idle_event,
+                                         EVENT_ALL_ACCESS, 0 );
         release_object( process );
     }
 }
diff --git a/server/protocol.def b/server/protocol.def
index f631297..6010dac 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -16,17 +16,15 @@
 
 struct request_header
 {
-    int            req;          /* request code */
-    unsigned short var_offset;   /* offset of the variable part of the request */
-    unsigned short var_size;     /* size of the variable part of the request */
-    unsigned int   error;        /* error result */
+    int          req;          /* request code */
+    size_t       request_size; /* request variable part size */
+    size_t       reply_size;   /* reply variable part maximum size */
 };
 
 struct reply_header
 {
-    unsigned int   error;        /* error result */
-    unsigned short var_offset;   /* offset of the variable part of the request */
-    unsigned short var_size;     /* size of the variable part of the request */
+    unsigned int error;        /* error result */
+    size_t       reply_size;   /* reply variable part size */
 };
 
 /* placeholder structure for the maximum allowed request size */
@@ -150,6 +148,13 @@
     int  bottom;
 } rectangle_t;
 
+/* structure for console char/attribute info */
+typedef struct
+{
+    WCHAR          ch;
+    unsigned short attr;
+} char_info_t;
+
 /****************************************************************/
 /* Request declarations */
 
@@ -244,15 +249,6 @@
 @END
 
 
-/* Set the shared buffer for a thread */
-@REQ(set_thread_buffer)
-    int          fd;           /* fd to mmap as shared buffer */
-@REPLY
-    unsigned int offset;       /* offset of buffer in file */
-    unsigned int size;         /* size of buffer */
-@END
-
-
 /* Terminate a process */
 @REQ(terminate_process)
     handle_t     handle;       /* process handle to terminate */
@@ -819,6 +815,7 @@
     handle_t     handle;        /* handle to console input, or 0 for process' console */
     int          index;         /* index to get line from */
 @REPLY
+    int          total;         /* total length of line in Unicode chars */
     VARARG(line,unicode_str);   /* line to add */
 @END
 
@@ -900,32 +897,50 @@
 
 /* write data (chars and/or attributes) in a screen buffer */
 @REQ(write_console_output)
-    handle_t     handle;        /* handle to the console input */
-    int          mode;          /* 0 for text, 1, for attributes, 2 for both */
-                                /* bit3 (4) set if uniform pattern in data */
-    short int    x;             /* position where to start writing */
-    short int    y;
+    handle_t     handle;        /* handle to the console output */
+    int          x;             /* position where to start writing */
+    int          y;
+    int          mode;          /* char info (see below) */
+    int          wrap;          /* wrap around at end of line? */
     VARARG(data,bytes);         /* info to write */
 @REPLY
-    int          written;       /* number of bytes actually written */
+    int          written;       /* number of char infos actually written */
+    int          width;         /* width of screen buffer */
+    int          height;        /* height of screen buffer */
 @END
-#define WRITE_CONSOLE_MODE_TEXT         0x00
-#define WRITE_CONSOLE_MODE_ATTR         0x01
-#define WRITE_CONSOLE_MODE_TEXTATTR     0x02
-#define WRITE_CONSOLE_MODE_TEXTSTDATTR  0x03
-#define WRITE_CONSOLE_MODE_UNIFORM      0x04
+enum char_info_mode
+{
+    CHAR_INFO_MODE_TEXT,        /* characters only */
+    CHAR_INFO_MODE_ATTR,        /* attributes only */
+    CHAR_INFO_MODE_TEXTATTR,    /* both characters and attributes */
+    CHAR_INFO_MODE_TEXTSTDATTR  /* characters but use standard attributes */
+};
 
 
-/* read data (chars and/or attrubutes) from a screen buffer */
-@REQ(read_console_output)
-    handle_t     handle;        /* handle to the console input */
-    short int    x;             /* position (x,y) where to start reading from */
-    short int    y;
-    short int    w;             /* size of area to read from (width x height) */
-    short int    h;
+/* fill a screen buffer with constant data (chars and/or attributes) */
+@REQ(fill_console_output)
+    handle_t     handle;        /* handle to the console output */
+    int          x;             /* position where to start writing */
+    int          y;
+    int          mode;          /* char info mode */
+    int          count;         /* number to write */
+    int          wrap;          /* wrap around at end of line? */
+    char_info_t  data;          /* data to write */
 @REPLY
-    short int    eff_w;         /* effective width read */
-    short int    eff_h;         /* effective height read */
+    int          written;       /* number of char infos actually written */
+@END
+
+
+/* read data (chars and/or attributes) from a screen buffer */
+@REQ(read_console_output)
+    handle_t     handle;        /* handle to the console output */
+    int          x;             /* position (x,y) where to start reading */
+    int          y;
+    int          mode;          /* char info mode */
+    int          wrap;          /* wrap around at end of line? */
+@REPLY
+    int          width;         /* width of screen buffer */
+    int          height;        /* height of screen buffer */
     VARARG(data,bytes);
 @END
 
@@ -1074,8 +1089,8 @@
 
 /* Retrieve the status of an exception event */
 @REQ(get_exception_status)
-@REPLY
     handle_t         handle;   /* handle to the queued event */
+@REPLY
     int              status;   /* event continuation status */
     VARARG(context,context);   /* modified thread context */
 @END
@@ -1106,8 +1121,7 @@
 /* Read data from a process address space */
 @REQ(read_process_memory)
     handle_t     handle;       /* process handle */
-    void*        addr;         /* addr to read from (must be int-aligned) */
-    int          len;          /* number of ints to read */
+    void*        addr;         /* addr to read from */
 @REPLY
     VARARG(data,bytes);        /* result data */
 @END
@@ -1117,10 +1131,9 @@
 @REQ(write_process_memory)
     handle_t     handle;       /* process handle */
     void*        addr;         /* addr to write to (must be int-aligned) */
-    int          len;          /* number of ints to write */
     unsigned int first_mask;   /* mask for first word */
     unsigned int last_mask;    /* mask for last word */
-    VARARG(data,bytes);        /* result data */
+    VARARG(data,bytes);        /* data to write */
 @END
 
 
@@ -1130,8 +1143,9 @@
     unsigned int access;       /* desired access rights */
     unsigned int options;      /* creation options */
     time_t       modif;        /* last modification time */
-    VARARG(name,unicode_len_str);  /* key name */
-    VARARG(class,unicode_str);     /* class name */
+    size_t       namelen;      /* length of key name in bytes */
+    VARARG(name,unicode_str,namelen);  /* key name */
+    VARARG(class,unicode_str);         /* class name */
 @REPLY
     handle_t     hkey;         /* handle to the created key */
     int          created;      /* has it been newly created? */
@@ -1157,7 +1171,7 @@
 @REQ(enum_key)
     handle_t     hkey;         /* handle to registry key */
     int          index;        /* index of subkey (or -1 for current key) */
-    int          full;         /* return the full info? */
+    int          info_class;   /* requested information class */
 @REPLY
     int          subkeys;      /* number of subkeys */
     int          max_subkey;   /* longest subkey name */
@@ -1166,8 +1180,10 @@
     int          max_value;    /* longest value name */
     int          max_data;     /* longest value data */
     time_t       modif;        /* last modification time */
-    VARARG(name,unicode_len_str);  /* key name */
-    VARARG(class,unicode_str);     /* class name */
+    size_t       total;        /* total length needed for full name and class */
+    size_t       namelen;      /* length of key name in bytes */
+    VARARG(name,unicode_str,namelen);  /* key name */
+    VARARG(class,unicode_str);         /* class name */
 @END
 
 
@@ -1175,21 +1191,19 @@
 @REQ(set_key_value)
     handle_t     hkey;         /* handle to registry key */
     int          type;         /* value type */
-    unsigned int total;        /* total value len */
-    unsigned int offset;       /* offset for setting data */
-    VARARG(name,unicode_len_str);  /* value name */
-    VARARG(data,bytes);        /* value data */
+    size_t       namelen;      /* length of value name in bytes */
+    VARARG(name,unicode_str,namelen);  /* value name */
+    VARARG(data,bytes);                /* value data */
 @END
 
 
 /* Retrieve the value of a registry key */
 @REQ(get_key_value)
     handle_t     hkey;         /* handle to registry key */
-    unsigned int offset;       /* offset for getting data */
-    VARARG(name,unicode_len_str);  /* value name */
+    VARARG(name,unicode_str);  /* value name */
 @REPLY
     int          type;         /* value type */
-    int          len;          /* value data len */
+    size_t       total;        /* total length needed for data */
     VARARG(data,bytes);        /* value data */
 @END
 
@@ -1198,12 +1212,13 @@
 @REQ(enum_key_value)
     handle_t     hkey;         /* handle to registry key */
     int          index;        /* value index */
-    unsigned int offset;       /* offset for getting data */
+    int          info_class;   /* requested information class */
 @REPLY
     int          type;         /* value type */
-    int          len;          /* value data len */
-    VARARG(name,unicode_len_str);  /* value name */
-    VARARG(data,bytes);        /* value data */
+    size_t       total;        /* total length needed for full name and data */
+    size_t       namelen;      /* length of value name in bytes */
+    VARARG(name,unicode_str,namelen);  /* value name */
+    VARARG(data,bytes);                /* value data */
 @END
 
 
@@ -1429,6 +1444,7 @@
     int             y;         /* y position */
     unsigned int    time;      /* message time */
     unsigned int    info;      /* extra info */
+    size_t          total;     /* total size of extra data */
     VARARG(data,bytes);        /* message data for sent messages */
 @END
 #define GET_MSG_REMOVE      1  /* remove the message */
@@ -1765,5 +1781,6 @@
 @REQ(get_window_properties)
     user_handle_t  window;        /* handle to the window */
 @REPLY
+    int            total;         /* total number of properties */
     VARARG(props,properties);     /* list of properties */
 @END
diff --git a/server/queue.c b/server/queue.c
index b72f31c..87e85a0 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -330,10 +330,29 @@
 }
 
 /* receive a message, removing it from the sent queue */
-static void receive_message( struct msg_queue *queue, struct message *msg )
+static void receive_message( struct msg_queue *queue, struct message *msg,
+                             struct get_message_reply *reply )
 {
     struct message_result *result = msg->result;
 
+    reply->total = msg->data_size;
+    if (msg->data_size > get_reply_max_size())
+    {
+        set_error( STATUS_BUFFER_OVERFLOW );
+        return;
+    }
+    reply->type   = msg->type;
+    reply->win    = msg->win;
+    reply->msg    = msg->msg;
+    reply->wparam = msg->wparam;
+    reply->lparam = msg->lparam;
+    reply->x      = msg->x;
+    reply->y      = msg->y;
+    reply->time   = msg->time;
+    reply->info   = msg->info;
+
+    if (msg->data) set_reply_data_ptr( msg->data, msg->data_size );
+
     unlink_message( &queue->msg_list[SEND_MESSAGE], msg );
     /* put the result on the receiver result stack */
     if (result)
@@ -341,14 +360,13 @@
         result->recv_next  = queue->recv_result;
         queue->recv_result = result;
     }
-    if (msg->data) free( msg->data );
     free( msg );
     if (!queue->msg_list[SEND_MESSAGE].first) clear_queue_bits( queue, QS_SENDMESSAGE );
 }
 
 /* set the result of the current received message */
 static void reply_message( struct msg_queue *queue, unsigned int result,
-                           unsigned int error, int remove, void *data, size_t len )
+                           unsigned int error, int remove, const void *data, size_t len )
 {
     struct message_result *res = queue->recv_result;
 
@@ -656,8 +674,8 @@
 {
     struct msg_queue *queue = get_current_queue();
 
-    req->handle = 0;
-    if (queue) req->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
+    reply->handle = 0;
+    if (queue) reply->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
 }
 
 
@@ -670,8 +688,8 @@
     {
         queue->wake_mask    = req->wake_mask;
         queue->changed_mask = req->changed_mask;
-        req->wake_bits      = queue->wake_bits;
-        req->changed_bits   = queue->changed_bits;
+        reply->wake_bits    = queue->wake_bits;
+        reply->changed_bits = queue->changed_bits;
         if (is_signaled( queue ))
         {
             /* if skip wait is set, do what would have been done in the subsequent wait */
@@ -688,11 +706,11 @@
     struct msg_queue *queue = current->queue;
     if (queue)
     {
-        req->wake_bits    = queue->wake_bits;
-        req->changed_bits = queue->changed_bits;
+        reply->wake_bits    = queue->wake_bits;
+        reply->changed_bits = queue->changed_bits;
         if (req->clear) queue->changed_bits = 0;
     }
-    else req->wake_bits = req->changed_bits = 0;
+    else reply->wake_bits = reply->changed_bits = 0;
 }
 
 
@@ -731,8 +749,8 @@
         switch(msg->type)
         {
        case MSG_OTHER_PROCESS:
-            msg->data_size = get_req_data_size(req);
-            if (msg->data_size && !(msg->data = memdup( get_req_data(req), msg->data_size )))
+            msg->data_size = get_req_data_size();
+            if (msg->data_size && !(msg->data = memdup( get_req_data(), msg->data_size )))
             {
                 free( msg );
                 break;
@@ -779,31 +797,26 @@
     release_object( thread );
 }
 
-/* store a message contents into the request buffer; helper for get_message */
-inline static void put_req_message( struct get_message_request *req, const struct message *msg )
-{
-    int len = min( get_req_data_size(req), msg->data_size );
-
-    req->type   = msg->type;
-    req->win    = msg->win;
-    req->msg    = msg->msg;
-    req->wparam = msg->wparam;
-    req->lparam = msg->lparam;
-    req->x      = msg->x;
-    req->y      = msg->y;
-    req->time   = msg->time;
-    req->info   = msg->info;
-    if (len) memcpy( get_req_data(req), msg->data, len );
-    set_req_data_size( req, len );
-}
-
 /* return a message to the application, removing it from the queue if needed */
-static void return_message_to_app( struct msg_queue *queue, struct get_message_request *req,
+static void return_message_to_app( struct msg_queue *queue, int flags,
+                                   struct get_message_reply *reply,
                                    struct message *msg, enum message_kind kind )
 {
-    put_req_message( req, msg );
+    assert( !msg->data_size );  /* posted messages can't have data */
+
+    reply->type   = msg->type;
+    reply->win    = msg->win;
+    reply->msg    = msg->msg;
+    reply->wparam = msg->wparam;
+    reply->lparam = msg->lparam;
+    reply->x      = msg->x;
+    reply->y      = msg->y;
+    reply->time   = msg->time;
+    reply->info   = msg->info;
+    reply->total  = 0;
+
     /* raw messages always get removed */
-    if ((msg->type == MSG_HARDWARE_RAW) || (req->flags & GET_MSG_REMOVE))
+    if ((msg->type == MSG_HARDWARE_RAW) || (flags & GET_MSG_REMOVE))
     {
         queue->last_msg = NULL;
         remove_queue_message( queue, msg, kind );
@@ -843,20 +856,14 @@
     struct msg_queue *queue = get_current_queue();
     user_handle_t get_win = get_user_full_handle( req->get_win );
 
-    if (!queue)
-    {
-        set_req_data_size( req, 0 );
-        return;
-    }
+    if (!queue) return;
 
     /* first check for sent messages */
     if ((msg = queue->msg_list[SEND_MESSAGE].first))
     {
-        put_req_message( req, msg );
-        receive_message( queue, msg );
+        receive_message( queue, msg, reply );
         return;
     }
-    set_req_data_size( req, 0 ); /* only sent messages can have data */
     if (req->flags & GET_MSG_SENT_ONLY) goto done;  /* nothing else to check */
 
     /* if requested, remove the last returned but not yet removed message */
@@ -871,7 +878,7 @@
     if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], get_win,
                                       req->get_first, req->get_last )))
     {
-        return_message_to_app( queue, req, msg, POST_MESSAGE );
+        return_message_to_app( queue, req->flags, reply, msg, POST_MESSAGE );
         return;
     }
 
@@ -879,30 +886,30 @@
     if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], get_win,
                                       req->get_first, req->get_last )))
     {
-        return_message_to_app( queue, req, msg, COOKED_HW_MESSAGE );
+        return_message_to_app( queue, req->flags, reply, msg, COOKED_HW_MESSAGE );
         return;
     }
 
     /* then check for any raw hardware message */
     if ((msg = queue->msg_list[RAW_HW_MESSAGE].first))
     {
-        return_message_to_app( queue, req, msg, RAW_HW_MESSAGE );
+        return_message_to_app( queue, req->flags, reply, msg, RAW_HW_MESSAGE );
         return;
     }
 
     /* now check for WM_PAINT */
     if (queue->paint_count &&
         (WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last) &&
-        (req->win = find_window_to_repaint( get_win, current )))
+        (reply->win = find_window_to_repaint( get_win, current )))
     {
-        req->type   = MSG_POSTED;
-        req->msg    = WM_PAINT;
-        req->wparam = 0;
-        req->lparam = 0;
-        req->x      = 0;
-        req->y      = 0;
-        req->time   = get_tick_count();
-        req->info   = 0;
+        reply->type   = MSG_POSTED;
+        reply->msg    = WM_PAINT;
+        reply->wparam = 0;
+        reply->lparam = 0;
+        reply->x      = 0;
+        reply->y      = 0;
+        reply->time   = get_tick_count();
+        reply->info   = 0;
         return;
     }
 
@@ -910,15 +917,15 @@
     if ((timer = find_expired_timer( queue, get_win, req->get_first,
                                      req->get_last, (req->flags & GET_MSG_REMOVE) )))
     {
-        req->type   = MSG_POSTED;
-        req->win    = timer->win;
-        req->msg    = timer->msg;
-        req->wparam = timer->id;
-        req->lparam = timer->lparam;
-        req->x      = 0;
-        req->y      = 0;
-        req->time   = get_tick_count();
-        req->info   = 0;
+        reply->type   = MSG_POSTED;
+        reply->win    = timer->win;
+        reply->msg    = timer->msg;
+        reply->wparam = timer->id;
+        reply->lparam = timer->lparam;
+        reply->x      = 0;
+        reply->y      = 0;
+        reply->time   = get_tick_count();
+        reply->info   = 0;
         return;
     }
 
@@ -932,7 +939,7 @@
 {
     if (current->queue && current->queue->recv_result)
         reply_message( current->queue, req->result, 0, req->remove,
-                       get_req_data(req), get_req_data_size(req) );
+                       get_req_data(), get_req_data_size() );
     else
         set_error( STATUS_ACCESS_DENIED );
 }
@@ -942,26 +949,24 @@
 DECL_HANDLER(get_message_reply)
 {
     struct msg_queue *queue = current->queue;
-    size_t data_len = 0;
 
     if (queue)
     {
         struct message_result *result = queue->send_result;
 
         set_error( STATUS_PENDING );
-        req->result = 0;
+        reply->result = 0;
 
         if (result && (result->replied || req->cancel))
         {
             if (result->replied)
             {
-                req->result = result->result;
+                reply->result = result->result;
                 set_error( result->error );
                 if (result->data)
                 {
-                    data_len = min( result->data_size, get_req_data_size(req) );
-                    memcpy( get_req_data(req), result->data, data_len );
-                    free( result->data );
+                    size_t data_len = min( result->data_size, get_reply_max_size() );
+                    set_reply_data_ptr( result->data, data_len );
                     result->data = NULL;
                     result->data_size = 0;
                 }
@@ -974,7 +979,6 @@
         }
     }
     else set_error( STATUS_ACCESS_DENIED );
-    set_req_data_size( req, data_len );
 }
 
 
diff --git a/server/registry.c b/server/registry.c
index 961f441..f8e82f4 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -29,7 +29,7 @@
 #include "winbase.h"
 #include "winreg.h"
 #include "winnt.h" /* registry definitions */
-
+#include "ntddk.h"
 
 /* a registry key */
 struct key
@@ -285,7 +285,7 @@
     }
 }
 
-/* duplicate a key path from the request buffer */
+/* duplicate a key path */
 /* returns a pointer to a static buffer, so only useable once per request */
 static WCHAR *copy_path( const WCHAR *path, size_t len, int skip_root )
 {
@@ -303,17 +303,17 @@
     return buffer;
 }
 
-/* copy a path from the request buffer, in cases where the length is stored in front of the path */
-static WCHAR *copy_req_path( void *req, size_t *len, int skip_root )
+/* copy a path from the request buffer */
+static WCHAR *copy_req_path( size_t len, int skip_root )
 {
-    const WCHAR *name_ptr = get_req_data(req);
-    if ((*len = sizeof(WCHAR) + *name_ptr++) > get_req_data_size(req))
+    const WCHAR *name_ptr = get_req_data();
+    if (len > get_req_data_size())
     {
         fatal_protocol_error( current, "copy_req_path: invalid length %d/%d\n",
-                              *len, get_req_data_size(req) );
+                              len, get_req_data_size() );
         return NULL;
     }
-    return copy_path( name_ptr, *len - sizeof(WCHAR), skip_root );
+    return copy_path( name_ptr, len, skip_root );
 }
 
 /* return the next token in a given path */
@@ -564,26 +564,39 @@
 }
 
 /* query information about a key or a subkey */
-static size_t enum_key( struct key *key, int index, struct enum_key_request *req )
+static void enum_key( struct key *key, int index, int info_class, struct enum_key_reply *reply )
 {
     int i;
     size_t len, namelen, classlen;
     int max_subkey = 0, max_class = 0;
     int max_value = 0, max_data = 0;
-    WCHAR *data = get_req_data(req);
+    WCHAR *data;
 
     if (index != -1)  /* -1 means use the specified key directly */
     {
         if ((index < 0) || (index > key->last_subkey))
         {
             set_error( STATUS_NO_MORE_ENTRIES );
-            return 0;
+            return;
         }
         key = key->subkeys[index];
     }
 
-    if (req->full)
+    namelen = strlenW(key->name) * sizeof(WCHAR);
+    classlen = key->class ? strlenW(key->class) * sizeof(WCHAR) : 0;
+
+    switch(info_class)
     {
+    case KeyBasicInformation:
+        classlen = 0; /* only return the name */
+        /* fall through */
+    case KeyNodeInformation:
+        reply->max_subkey = 0;
+        reply->max_class  = 0;
+        reply->max_value  = 0;
+        reply->max_data   = 0;
+        break;
+    case KeyFullInformation:
         for (i = 0; i <= key->last_subkey; i++)
         {
             struct key *subkey = key->subkeys[i];
@@ -600,43 +613,37 @@
             len = key->values[i].len;
             if (len > max_data) max_data = len;
         }
-        req->max_subkey = max_subkey;
-        req->max_class  = max_class;
-        req->max_value  = max_value;
-        req->max_data   = max_data;
+        reply->max_subkey = max_subkey;
+        reply->max_class  = max_class;
+        reply->max_value  = max_value;
+        reply->max_data   = max_data;
+        namelen = 0;  /* only return the class */
+        break;
+    default:
+        set_error( STATUS_INVALID_PARAMETER );
+        return;
     }
-    else
+    reply->subkeys = key->last_subkey + 1;
+    reply->values  = key->last_value + 1;
+    reply->modif   = key->modif;
+    reply->total   = namelen + classlen;
+
+    len = min( reply->total, get_reply_max_size() );
+    if (len && (data = set_reply_data_size( len )))
     {
-        req->max_subkey = 0;
-        req->max_class  = 0;
-        req->max_value  = 0;
-        req->max_data   = 0;
+        if (len > namelen)
+        {
+            reply->namelen = namelen;
+            memcpy( data, key->name, namelen );
+            memcpy( (char *)data + namelen, key->class, len - namelen );
+        }
+        else
+        {
+            reply->namelen = len;
+            memcpy( data, key->name, len );
+        }
     }
-    req->subkeys = key->last_subkey + 1;
-    req->values  = key->last_value + 1;
-    req->modif   = key->modif;
-
-    namelen = strlenW(key->name) * sizeof(WCHAR);
-    classlen = key->class ? strlenW(key->class) * sizeof(WCHAR) : 0;
-
-    len = namelen + classlen + sizeof(WCHAR);
-    if (len > get_req_data_size(req))
-    {
-        len = get_req_data_size(req);
-        if (len < sizeof(WCHAR)) return 0;
-    }
-
-    *data++ = namelen;
-    len -= sizeof(WCHAR);
-    if (len > namelen)
-    {
-        memcpy( data, key->name, namelen );
-        memcpy( (char *)data + namelen, key->class, min(classlen,len-namelen) );
-    }
-    else memcpy( data, key->name, len );
-
     if (debug_level > 1) dump_operation( key, NULL, "Enum" );
-    return len + sizeof(WCHAR);
 }
 
 /* delete a key and its values */
@@ -743,43 +750,13 @@
 }
 
 /* set a key value */
-static void set_value( struct key *key, WCHAR *name, int type, unsigned int total_len,
-                       unsigned int offset, unsigned int data_len, const void *data )
+static void set_value( struct key *key, WCHAR *name, int type, const void *data, size_t len )
 {
     struct key_value *value;
     void *ptr = NULL;
 
-    if (data_len + offset > total_len)
-    {
-        set_error( STATUS_INVALID_PARAMETER );
-        return;
-    }
-
-    if (offset)  /* adding data to an existing value */
-    {
-        int index;
-        if (!(value = find_value( key, name, &index )))
-        {
-            set_error( STATUS_OBJECT_NAME_NOT_FOUND );
-            return;
-        }
-        if (value->len != total_len)
-        {
-            set_error( STATUS_INVALID_PARAMETER );
-            return;
-        }
-        memcpy( (char *)value->data + offset, data, data_len );
-        if (debug_level > 1) dump_operation( key, value, "Set" );
-        return;
-    }
-
     /* first copy the data */
-    if (total_len)
-    {
-        if (!(ptr = mem_alloc( total_len ))) return;
-        memcpy( ptr, data, data_len );
-        if (data_len < total_len) memset( (char *)ptr + data_len, 0, total_len - data_len );
-    }
+    if (len && !(ptr = memdup( data, len ))) return;
 
     if (!(value = insert_value( key, name )))
     {
@@ -788,30 +765,23 @@
     }
     if (value->data) free( value->data ); /* already existing, free previous data */
     value->type  = type;
-    value->len   = total_len;
+    value->len   = len;
     value->data  = ptr;
     touch_key( key );
     if (debug_level > 1) dump_operation( key, value, "Set" );
 }
 
 /* get a key value */
-static size_t get_value( struct key *key, const WCHAR *name, unsigned int offset,
-                         unsigned int maxlen, int *type, int *len, void *data )
+static void get_value( struct key *key, const WCHAR *name, int *type, int *len )
 {
     struct key_value *value;
     int index;
-    size_t ret = 0;
 
     if ((value = find_value( key, name, &index )))
     {
         *type = value->type;
         *len  = value->len;
-        if (value->data && offset < value->len)
-        {
-            if (maxlen > value->len - offset) maxlen = value->len - offset;
-            memcpy( data, (char *)value->data + offset, maxlen );
-            ret = maxlen;
-        }
+        if (value->data) set_reply_data( value->data, min( value->len, get_reply_max_size() ));
         if (debug_level > 1) dump_operation( key, value, "Get" );
     }
     else
@@ -819,54 +789,57 @@
         *type = -1;
         set_error( STATUS_OBJECT_NAME_NOT_FOUND );
     }
-    return ret;
 }
 
 /* enumerate a key value */
-static size_t enum_value( struct key *key, int i, unsigned int offset,
-                          unsigned int maxlen, int *type, int *len, void *data )
+static void enum_value( struct key *key, int i, int info_class, struct enum_key_value_reply *reply )
 {
     struct key_value *value;
-    size_t ret = 0;
 
     if (i < 0 || i > key->last_value) set_error( STATUS_NO_MORE_ENTRIES );
     else
     {
-        WCHAR *name_ptr = data;
+        void *data;
+        size_t namelen, maxlen;
+
         value = &key->values[i];
-        *type = value->type;
-        *len  = value->len;
+        reply->type = value->type;
+        namelen = strlenW( value->name ) * sizeof(WCHAR);
 
-        if (maxlen >= sizeof(WCHAR))
+        switch(info_class)
         {
-            size_t name_len = 0;
+        case KeyValueBasicInformation:
+            reply->total = namelen;
+            break;
+        case KeyValueFullInformation:
+            reply->total = namelen + value->len;
+            break;
+        case KeyValuePartialInformation:
+            reply->total = value->len;
+            namelen = 0;
+            break;
+        default:
+            set_error( STATUS_INVALID_PARAMETER );
+            return;
+        }
 
-            /* copy the name only the first time (offset==0),
-             * otherwise store an empty name in the buffer
-             */
-            maxlen -= sizeof(WCHAR);
-            ret += sizeof(WCHAR);
-            if (!offset)
+        maxlen = min( reply->total, get_reply_max_size() );
+        if (maxlen && ((data = set_reply_data_size( maxlen ))))
+        {
+            if (maxlen > namelen)
             {
-                name_len = strlenW( value->name ) * sizeof(WCHAR);
-                if (name_len > maxlen) name_len = maxlen;
+                reply->namelen = namelen;
+                memcpy( data, value->name, namelen );
+                memcpy( (char *)data + namelen, value->data, maxlen - namelen );
             }
-            *name_ptr++ = name_len;
-            memcpy( name_ptr, value->name, name_len );
-            maxlen -= name_len;
-            ret += name_len;
-            data = (char *)name_ptr + name_len;
-
-            if (value->data && offset < value->len)
+            else
             {
-                if (maxlen > value->len - offset) maxlen = value->len - offset;
-                memcpy( data, (char *)value->data + offset, maxlen );
-                ret += maxlen;
+                reply->namelen = maxlen;
+                memcpy( data, value->name, maxlen );
             }
         }
         if (debug_level > 1) dump_operation( key, value, "Enum" );
     }
-    return ret;
 }
 
 /* delete a value */
@@ -1585,31 +1558,30 @@
     struct key *key = NULL, *parent;
     unsigned int access = req->access;
     WCHAR *name, *class;
-    size_t len;
 
     if (access & MAXIMUM_ALLOWED) access = KEY_ALL_ACCESS;  /* FIXME: needs general solution */
-    req->hkey = 0;
-    if (!(name = copy_req_path( req, &len, !req->parent ))) return;
+    reply->hkey = 0;
+    if (!(name = copy_req_path( req->namelen, !req->parent ))) return;
     if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ )))
     {
-        if (len == get_req_data_size(req))  /* no class specified */
+        if (req->namelen == get_req_data_size())  /* no class specified */
         {
-            key = create_key( parent, name, NULL, req->options, req->modif, &req->created );
+            key = create_key( parent, name, NULL, req->options, req->modif, &reply->created );
         }
         else
         {
-            const WCHAR *class_ptr = (WCHAR *)((char *)get_req_data(req) + len);
+            const WCHAR *class_ptr = (WCHAR *)((char *)get_req_data() + req->namelen);
 
-            if ((class = req_strdupW( req, class_ptr, get_req_data_size(req) - len )))
+            if ((class = req_strdupW( req, class_ptr, get_req_data_size() - req->namelen )))
             {
                 key = create_key( parent, name, class, req->options,
-                                  req->modif, &req->created );
+                                  req->modif, &reply->created );
                 free( class );
             }
         }
         if (key)
         {
-            req->hkey = alloc_handle( current->process, key, access, 0 );
+            reply->hkey = alloc_handle( current->process, key, access, 0 );
             release_object( key );
         }
         release_object( parent );
@@ -1623,13 +1595,13 @@
     unsigned int access = req->access;
 
     if (access & MAXIMUM_ALLOWED) access = KEY_ALL_ACCESS;  /* FIXME: needs general solution */
-    req->hkey = 0;
+    reply->hkey = 0;
     if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ )))
     {
-        WCHAR *name = copy_path( get_req_data(req), get_req_data_size(req), !req->parent );
+        WCHAR *name = copy_path( get_req_data(), get_req_data_size(), !req->parent );
         if (name && (key = open_key( parent, name )))
         {
-            req->hkey = alloc_handle( current->process, key, access, 0 );
+            reply->hkey = alloc_handle( current->process, key, access, 0 );
             release_object( key );
         }
         release_object( parent );
@@ -1652,15 +1624,13 @@
 DECL_HANDLER(enum_key)
 {
     struct key *key;
-    size_t len = 0;
 
     if ((key = get_hkey_obj( req->hkey,
                              req->index == -1 ? KEY_QUERY_VALUE : KEY_ENUMERATE_SUB_KEYS )))
     {
-        len = enum_key( key, req->index, req );
+        enum_key( key, req->index, req->info_class, reply );
         release_object( key );
     }
-    set_req_data_size( req, len );
 }
 
 /* set a value of a registry key */
@@ -1668,15 +1638,14 @@
 {
     struct key *key;
     WCHAR *name;
-    size_t len;
 
-    if (!(name = copy_req_path( req, &len, 0 ))) return;
+    if (!(name = copy_req_path( req->namelen, 0 ))) return;
     if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE )))
     {
-        size_t datalen = get_req_data_size(req) - len;
-        const char *data = (char *)get_req_data(req) + len;
+        size_t datalen = get_req_data_size() - req->namelen;
+        const char *data = (char *)get_req_data() + req->namelen;
 
-        set_value( key, name, req->type, req->total, req->offset, datalen, data );
+        set_value( key, name, req->type, data, datalen );
         release_object( key );
     }
 }
@@ -1686,33 +1655,26 @@
 {
     struct key *key;
     WCHAR *name;
-    size_t len = 0, tmp;
 
-    req->len = 0;
-    if (!(name = copy_req_path( req, &tmp, 0 ))) return;
+    reply->total = 0;
+    if (!(name = copy_path( get_req_data(), get_req_data_size(), 0 ))) return;
     if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE )))
     {
-        len = get_value( key, name, req->offset, get_req_data_size(req),
-                         &req->type, &req->len, get_req_data(req) );
+        get_value( key, name, &reply->type, &reply->total );
         release_object( key );
     }
-    set_req_data_size( req, len );
 }
 
 /* enumerate the value of a registry key */
 DECL_HANDLER(enum_key_value)
 {
     struct key *key;
-    size_t len = 0;
 
-    req->len = 0;
     if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE )))
     {
-        len = enum_value( key, req->index, req->offset, get_req_data_size(req),
-                          &req->type, &req->len, get_req_data(req) );
+        enum_value( key, req->index, req->info_class, reply );
         release_object( key );
     }
-    set_req_data_size( req, len );
 }
 
 /* delete a value of a registry key */
@@ -1723,7 +1685,7 @@
 
     if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE )))
     {
-        if ((name = req_strdupW( req, get_req_data(req), get_req_data_size(req) )))
+        if ((name = req_strdupW( req, get_req_data(), get_req_data_size() )))
         {
             delete_value( key, name );
             free( name );
@@ -1786,7 +1748,7 @@
 
     if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS )))
     {
-        register_branch_for_saving( key, get_req_data(req), get_req_data_size(req) );
+        register_branch_for_saving( key, get_req_data(), get_req_data_size() );
         release_object( key );
     }
 }
diff --git a/server/request.c b/server/request.c
index ba420a0..9f2b8ad 100644
--- a/server/request.c
+++ b/server/request.c
@@ -142,31 +142,105 @@
     exit(1);
 }
 
-/* call a request handler */
-static inline void call_req_handler( struct thread *thread, union generic_request *request )
+/* allocate the reply data */
+void *set_reply_data_size( size_t size )
 {
-    enum request req = request->header.req;
+    assert( size <= get_reply_max_size() );
+    if (size && !(current->reply_data = mem_alloc( size ))) size = 0;
+    current->reply_size = size;
+    return current->reply_data;
+}
 
-    current = thread;
-    clear_error();
+/* write the remaining part of the reply */
+void write_reply( struct thread *thread )
+{
+    int ret;
 
-    if (debug_level) trace_request( thread, request );
-
-    if (request->header.var_size)
+    if ((ret = write( thread->reply_fd,
+                      (char *)thread->reply_data + thread->reply_size - thread->reply_towrite,
+                      thread->reply_towrite )) >= 0)
     {
-        if ((unsigned int)request->header.var_offset +
-                          request->header.var_size > MAX_REQUEST_LENGTH)
+        if (!(thread->reply_towrite -= ret))
         {
-            fatal_protocol_error( current, "bad request offset/size %d/%d\n",
-                                  request->header.var_offset, request->header.var_size );
+            free( thread->reply_data );
+            thread->reply_data = NULL;
+            /* sent everything, can go back to waiting for requests */
+            change_select_fd( &thread->obj, thread->request_fd, POLLIN );
+        }
+        return;
+    }
+    if (errno == EPIPE)
+        kill_thread( thread, 0 );  /* normal death */
+    else if (errno != EWOULDBLOCK && errno != EAGAIN)
+        fatal_protocol_perror( thread, "reply write" );
+}
+
+/* send a reply to the current thread */
+static void send_reply( union generic_reply *reply )
+{
+    int ret;
+
+    if (!current->reply_size)
+    {
+        if ((ret = write( current->reply_fd, reply, sizeof(*reply) )) != sizeof(*reply)) goto error;
+    }
+    else
+    {
+        struct iovec vec[2];
+
+        vec[0].iov_base = reply;
+        vec[0].iov_len  = sizeof(*reply);
+        vec[1].iov_base = current->reply_data;
+        vec[1].iov_len  = current->reply_size;
+
+        if ((ret = writev( current->reply_fd, vec, 2 )) < sizeof(*reply)) goto error;
+
+        if ((current->reply_towrite = current->reply_size - (ret - sizeof(*reply))))
+        {
+            /* couldn't write it all, wait for POLLOUT */
+            change_select_fd( &current->obj, current->reply_fd, POLLOUT );
             return;
         }
     }
+    if (current->reply_data)
+    {
+        free( current->reply_data );
+        current->reply_data = NULL;
+    }
+    return;
+
+ error:
+    if (ret >= 0)
+        fatal_protocol_error( current, "partial write %d\n", ret );
+    else if (errno == EPIPE)
+        kill_thread( current, 0 );  /* normal death */
+    else
+        fatal_protocol_perror( current, "reply write" );
+}
+
+/* call a request handler */
+static void call_req_handler( struct thread *thread )
+{
+    union generic_reply reply;
+    enum request req = thread->req.request_header.req;
+
+    current = thread;
+    current->reply_size = 0;
+    clear_error();
+    memset( &reply, 0, sizeof(reply) );
+
+    if (debug_level) trace_request();
 
     if (req < REQ_NB_REQUESTS)
     {
-        req_handlers[req]( request );
-        if (current) send_reply( current, request );
+        req_handlers[req]( &current->req, &reply );
+        if (current)
+        {
+            reply.reply_header.error = current->error;
+            reply.reply_header.reply_size = current->reply_size;
+            if (debug_level) trace_reply( req, &reply );
+            send_reply( &reply );
+        }
         current = NULL;
         return;
     }
@@ -176,14 +250,39 @@
 /* read a request from a thread */
 void read_request( struct thread *thread )
 {
-    union generic_request req;
     int ret;
 
-    if ((ret = read( thread->obj.fd, &req, sizeof(req) )) == sizeof(req))
+    if (!thread->req_toread)  /* no pending request */
     {
-        call_req_handler( thread, &req );
-        return;
+        if ((ret = read( thread->obj.fd, &thread->req,
+                         sizeof(thread->req) )) != sizeof(thread->req)) goto error;
+        if (!(thread->req_toread = thread->req.request_header.request_size))
+        {
+            /* no data, handle request at once */
+            call_req_handler( thread );
+            return;
+        }
+        if (!(thread->req_data = malloc( thread->req_toread )))
+            fatal_protocol_error( thread, "no memory for %d bytes request\n", thread->req_toread );
     }
+
+    /* read the variable sized data */
+    for (;;)
+    {
+        ret = read( thread->obj.fd, ((char *)thread->req_data +
+                                     thread->req.request_header.request_size - thread->req_toread),
+                    thread->req_toread );
+        if (ret <= 0) break;
+        if (!(thread->req_toread -= ret))
+        {
+            call_req_handler( thread );
+            free( thread->req_data );
+            thread->req_data = NULL;
+            return;
+        }
+    }
+
+error:
     if (!ret)  /* closed pipe */
         kill_thread( thread, 0 );
     else if (ret > 0)
@@ -192,26 +291,6 @@
         fatal_protocol_perror( thread, "read" );
 }
 
-/* send a reply to a thread */
-void send_reply( struct thread *thread, union generic_request *request )
-{
-    int ret;
-
-    if (debug_level) trace_reply( thread, request );
-
-    request->header.error = thread->error;
-
-    if ((ret = write( thread->reply_fd, request, sizeof(*request) )) != sizeof(*request))
-    {
-        if (ret >= 0)
-            fatal_protocol_error( thread, "partial write %d\n", ret );
-        else if (errno == EPIPE)
-            kill_thread( thread, 0 );  /* normal death */
-        else
-            fatal_protocol_perror( thread, "reply write" );
-    }
-}
-
 /* receive a file descriptor on the process socket */
 int receive_fd( struct process *process )
 {
@@ -439,6 +518,7 @@
 
     /* make sure no request is larger than the maximum size */
     assert( sizeof(union generic_request) == sizeof(struct request_max_size) );
+    assert( sizeof(union generic_reply) == sizeof(struct request_max_size) );
 
     create_server_dir();
     if ((fd = socket( AF_UNIX, SOCK_STREAM, 0 )) == -1) fatal_perror( "socket" );
diff --git a/server/request.h b/server/request.h
index 5866641..b1409aa 100644
--- a/server/request.h
+++ b/server/request.h
@@ -7,6 +7,8 @@
 #ifndef __WINE_SERVER_REQUEST_H
 #define __WINE_SERVER_REQUEST_H
 
+#include <assert.h>
+
 #include "thread.h"
 #include "wine/server_protocol.h"
 
@@ -14,7 +16,8 @@
 #define MAX_REQUEST_LENGTH  8192
 
 /* request handler definition */
-#define DECL_HANDLER(name) void req_##name( struct name##_request *req )
+#define DECL_HANDLER(name) \
+    void req_##name( const struct name##_request *req, struct name##_reply *reply )
 
 /* request functions */
 
@@ -33,36 +36,54 @@
 #endif
 
 extern const char *get_config_dir(void);
+extern void *set_reply_data_size( size_t size );
 extern int receive_fd( struct process *process );
 extern int send_client_fd( struct process *process, int fd, handle_t handle );
 extern void read_request( struct thread *thread );
-extern void send_reply( struct thread *thread, union generic_request *request );
+extern void write_reply( struct thread *thread );
 extern unsigned int get_tick_count(void);
 extern void open_master_socket(void);
 extern void close_master_socket(void);
 extern void lock_master_socket( int locked );
 
-extern void trace_request( struct thread *thread, const union generic_request *request );
-extern void trace_reply( struct thread *thread, const union generic_request *request );
+extern void trace_request(void);
+extern void trace_reply( enum request req, const union generic_reply *reply );
 
 /* get the request vararg data */
-inline static void *get_req_data( const void *req )
+inline static const void *get_req_data(void)
 {
-    return (char *)current->buffer + ((struct request_header *)req)->var_offset;
+    return current->req_data;
 }
 
 /* get the request vararg size */
-inline static size_t get_req_data_size( const void *req )
+inline static size_t get_req_data_size(void)
 {
-    return ((struct request_header *)req)->var_size;
+    return current->req.request_header.request_size;
 }
 
-/* set the request vararg size */
-inline static void set_req_data_size( const void *req, size_t size )
+/* get the reply maximum vararg size */
+inline static size_t get_reply_max_size(void)
 {
-    ((struct request_header *)req)->var_size = size;
+    return current->req.request_header.reply_size;
 }
 
+/* allocate and fill the reply data */
+inline static void *set_reply_data( const void *data, size_t size )
+{
+    void *ret = set_reply_data_size( size );
+    if (ret) memcpy( ret, data, size );
+    return ret;
+}
+
+/* set the reply data pointer directly (will be freed by request code) */
+inline static void set_reply_data_ptr( void *data, size_t size )
+{
+    assert( size <= get_reply_max_size() );
+    current->reply_size = size;
+    current->reply_data = data;
+}
+
+
 /* Everything below this line is generated automatically by tools/make_requests */
 /* ### make_requests begin ### */
 
@@ -73,7 +94,6 @@
 DECL_HANDLER(init_process);
 DECL_HANDLER(init_process_done);
 DECL_HANDLER(init_thread);
-DECL_HANDLER(set_thread_buffer);
 DECL_HANDLER(terminate_process);
 DECL_HANDLER(terminate_thread);
 DECL_HANDLER(get_process_info);
@@ -132,6 +152,7 @@
 DECL_HANDLER(write_console_input);
 DECL_HANDLER(read_console_input);
 DECL_HANDLER(write_console_output);
+DECL_HANDLER(fill_console_output);
 DECL_HANDLER(read_console_output);
 DECL_HANDLER(move_console_output);
 DECL_HANDLER(create_change_notification);
@@ -217,7 +238,7 @@
 
 #ifdef WANT_REQUEST_HANDLERS
 
-typedef void (*req_handler)( void *req );
+typedef void (*req_handler)( const void *req, void *reply );
 static const req_handler req_handlers[REQ_NB_REQUESTS] =
 {
     (req_handler)req_new_process,
@@ -227,7 +248,6 @@
     (req_handler)req_init_process,
     (req_handler)req_init_process_done,
     (req_handler)req_init_thread,
-    (req_handler)req_set_thread_buffer,
     (req_handler)req_terminate_process,
     (req_handler)req_terminate_thread,
     (req_handler)req_get_process_info,
@@ -286,6 +306,7 @@
     (req_handler)req_write_console_input,
     (req_handler)req_read_console_input,
     (req_handler)req_write_console_output,
+    (req_handler)req_fill_console_output,
     (req_handler)req_read_console_output,
     (req_handler)req_move_console_output,
     (req_handler)req_create_change_notification,
diff --git a/server/select.c b/server/select.c
index 2e0b7a8..a51feaa 100644
--- a/server/select.c
+++ b/server/select.c
@@ -97,13 +97,13 @@
     active_users--;
 }
 
-/* change the fd of an object (the old fd is closed) */
-void change_select_fd( struct object *obj, int fd )
+/* change the fd and events of an object */
+void change_select_fd( struct object *obj, int fd, int events )
 {
     int user = obj->select;
     assert( poll_users[user] == obj );
     pollfd[user].fd = fd;
-    close( obj->fd );
+    pollfd[user].events = events;
     obj->fd = fd;
 }
 
diff --git a/server/semaphore.c b/server/semaphore.c
index 4844414..022fc73 100644
--- a/server/semaphore.c
+++ b/server/semaphore.c
@@ -123,11 +123,11 @@
 {
     struct semaphore *sem;
 
-    req->handle = 0;
-    if ((sem = create_semaphore( get_req_data(req), get_req_data_size(req),
+    reply->handle = 0;
+    if ((sem = create_semaphore( get_req_data(), get_req_data_size(),
                                  req->initial, req->max )))
     {
-        req->handle = alloc_handle( current->process, sem, SEMAPHORE_ALL_ACCESS, req->inherit );
+        reply->handle = alloc_handle( current->process, sem, SEMAPHORE_ALL_ACCESS, req->inherit );
         release_object( sem );
     }
 }
@@ -135,12 +135,12 @@
 /* open a handle to a semaphore */
 DECL_HANDLER(open_semaphore)
 {
-    req->handle = open_object( get_req_data(req), get_req_data_size(req),
-                               &semaphore_ops, req->access, req->inherit );
+    reply->handle = open_object( get_req_data(), get_req_data_size(),
+                                 &semaphore_ops, req->access, req->inherit );
 }
 
 /* release a semaphore */
 DECL_HANDLER(release_semaphore)
 {
-    req->prev_count = release_semaphore( req->handle, req->count );
+    reply->prev_count = release_semaphore( req->handle, req->count );
 }
diff --git a/server/serial.c b/server/serial.c
index c16ccd7..da682bf 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -37,7 +37,7 @@
 
 static void serial_dump( struct object *obj, int verbose );
 static int serial_get_fd( struct object *obj );
-static int serial_get_info( struct object *obj, struct get_file_info_request *req );
+static int serial_get_info( struct object *obj, struct get_file_info_reply *reply );
 static int serial_get_poll_events( struct object *obj );
 
 struct serial
@@ -165,23 +165,23 @@
     return serial->obj.fd;
 }
 
-static int serial_get_info( struct object *obj, struct get_file_info_request *req )
+static int serial_get_info( struct object *obj, struct get_file_info_reply *reply )
 {
     struct serial *serial = (struct serial *) obj;
     assert( obj->ops == &serial_ops );
 
-    if (req)
+    if (reply)
     {
-        req->type        = FILE_TYPE_CHAR;
-        req->attr        = 0;
-        req->access_time = 0;
-        req->write_time  = 0;
-        req->size_high   = 0;
-        req->size_low    = 0;
-        req->links       = 0;
-        req->index_high  = 0;
-        req->index_low   = 0;
-        req->serial      = 0;
+        reply->type        = FILE_TYPE_CHAR;
+        reply->attr        = 0;
+        reply->access_time = 0;
+        reply->write_time  = 0;
+        reply->size_high   = 0;
+        reply->size_low    = 0;
+        reply->links       = 0;
+        reply->index_high  = 0;
+        reply->index_low   = 0;
+        reply->serial      = 0;
     }
 
     if(serial->attrib & FILE_FLAG_OVERLAPPED)
@@ -215,10 +215,10 @@
 {
     struct serial *serial;
 
-    req->handle = 0;
-    if ((serial = create_serial( get_req_data(req), get_req_data_size(req), req->access, req->attributes )))
+    reply->handle = 0;
+    if ((serial = create_serial( get_req_data(), get_req_data_size(), req->access, req->attributes )))
     {
-        req->handle = alloc_handle( current->process, serial, req->access, req->inherit );
+        reply->handle = alloc_handle( current->process, serial, req->access, req->inherit );
         release_object( serial );
     }
 }
@@ -230,17 +230,17 @@
     if ((serial = get_serial_obj( current->process, req->handle, 0 )))
     {
         /* timeouts */
-        req->readinterval = serial->readinterval;
-        req->readconst    = serial->readconst;
-        req->readmult     = serial->readmult;
-        req->writeconst   = serial->writeconst;
-        req->writemult    = serial->writemult;
+        reply->readinterval = serial->readinterval;
+        reply->readconst    = serial->readconst;
+        reply->readmult     = serial->readmult;
+        reply->writeconst   = serial->writeconst;
+        reply->writemult    = serial->writemult;
 
         /* event mask */
-        req->eventmask    = serial->eventmask;
+        reply->eventmask    = serial->eventmask;
 
         /* comm port error status */
-        req->commerror    = serial->commerror;
+        reply->commerror    = serial->commerror;
 
         release_object( serial );
     }
diff --git a/server/snapshot.c b/server/snapshot.c
index 48654fa..1d73873 100644
--- a/server/snapshot.c
+++ b/server/snapshot.c
@@ -94,7 +94,7 @@
 }
 
 /* get the next process in the snapshot */
-static int snapshot_next_process( struct snapshot *snapshot, struct next_process_request *req )
+static int snapshot_next_process( struct snapshot *snapshot, struct next_process_reply *reply )
 {
     struct process_snapshot *ptr;
 
@@ -103,22 +103,21 @@
         set_error( STATUS_INVALID_PARAMETER );  /* FIXME */
         return 0;
     }
-    if (req->reset) snapshot->process_pos = 0;
-    else if (snapshot->process_pos >= snapshot->process_count)
+    if (snapshot->process_pos >= snapshot->process_count)
     {
         set_error( STATUS_NO_MORE_FILES );
         return 0;
     }
     ptr = &snapshot->processes[snapshot->process_pos++];
-    req->count    = ptr->count;
-    req->pid      = get_process_id( ptr->process );
-    req->threads  = ptr->threads;
-    req->priority = ptr->priority;
+    reply->count    = ptr->count;
+    reply->pid      = get_process_id( ptr->process );
+    reply->threads  = ptr->threads;
+    reply->priority = ptr->priority;
     return 1;
 }
 
 /* get the next thread in the snapshot */
-static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_request *req )
+static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_reply *reply )
 {
     struct thread_snapshot *ptr;
 
@@ -127,23 +126,22 @@
         set_error( STATUS_INVALID_PARAMETER );  /* FIXME */
         return 0;
     }
-    if (req->reset) snapshot->thread_pos = 0;
-    else if (snapshot->thread_pos >= snapshot->thread_count)
+    if (snapshot->thread_pos >= snapshot->thread_count)
     {
         set_error( STATUS_NO_MORE_FILES );
         return 0;
     }
     ptr = &snapshot->threads[snapshot->thread_pos++];
-    req->count     = ptr->count;
-    req->pid       = get_process_id( ptr->thread->process );
-    req->tid       = get_thread_id( ptr->thread );
-    req->base_pri  = ptr->priority;
-    req->delta_pri = 0;  /* FIXME */
+    reply->count     = ptr->count;
+    reply->pid       = get_process_id( ptr->thread->process );
+    reply->tid       = get_thread_id( ptr->thread );
+    reply->base_pri  = ptr->priority;
+    reply->delta_pri = 0;  /* FIXME */
     return 1;
 }
 
 /* get the next module in the snapshot */
-static int snapshot_next_module( struct snapshot *snapshot, struct next_module_request *req )
+static int snapshot_next_module( struct snapshot *snapshot, struct next_module_reply *reply )
 {
     struct module_snapshot *ptr;
 
@@ -152,15 +150,14 @@
         set_error( STATUS_INVALID_PARAMETER );  /* FIXME */
         return 0;
     }
-    if (req->reset) snapshot->module_pos = 0;
-    else if (snapshot->module_pos >= snapshot->module_count)
+    if (snapshot->module_pos >= snapshot->module_count)
     {
         set_error( STATUS_NO_MORE_FILES );
         return 0;
     }
     ptr = &snapshot->modules[snapshot->module_pos++];
-    req->pid  = get_process_id( snapshot->process );
-    req->base = ptr->base;
+    reply->pid  = get_process_id( snapshot->process );
+    reply->base = ptr->base;
     return 1;
 }
 
@@ -198,10 +195,10 @@
 {
     struct snapshot *snapshot;
 
-    req->handle = 0;
+    reply->handle = 0;
     if ((snapshot = create_snapshot( req->pid, req->flags )))
     {
-        req->handle = alloc_handle( current->process, snapshot, 0, req->inherit );
+        reply->handle = alloc_handle( current->process, snapshot, 0, req->inherit );
         release_object( snapshot );
     }
 }
@@ -214,7 +211,8 @@
     if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
                                                        0, &snapshot_ops )))
     {
-        snapshot_next_process( snapshot, req );
+        if (req->reset) snapshot->process_pos = 0;
+        snapshot_next_process( snapshot, reply );
         release_object( snapshot );
     }
 }
@@ -227,7 +225,8 @@
     if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
                                                        0, &snapshot_ops )))
     {
-        snapshot_next_thread( snapshot, req );
+        if (req->reset) snapshot->thread_pos = 0;
+        snapshot_next_thread( snapshot, reply );
         release_object( snapshot );
     }
 }
@@ -240,7 +239,8 @@
     if ((snapshot = (struct snapshot *)get_handle_obj( current->process, req->handle,
                                                        0, &snapshot_ops )))
     {
-        snapshot_next_module( snapshot, req );
+        if (req->reset) snapshot->module_pos = 0;
+        snapshot_next_module( snapshot, reply );
         release_object( snapshot );
     }
 }
diff --git a/server/sock.c b/server/sock.c
index 0781055..a18dc6e 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -59,7 +59,7 @@
 static int sock_get_poll_events( struct object *obj );
 static void sock_poll_event( struct object *obj, int event );
 static int sock_get_fd( struct object *obj );
-static int sock_get_info( struct object *obj, struct get_file_info_request *req );
+static int sock_get_info( struct object *obj, struct get_file_info_reply *reply );
 static void sock_destroy( struct object *obj );
 static int sock_get_error( int err );
 static void sock_set_error(void);
@@ -272,20 +272,20 @@
     return sock->obj.fd;
 }
 
-static int sock_get_info( struct object *obj, struct get_file_info_request *req )
+static int sock_get_info( struct object *obj, struct get_file_info_reply *reply )
 {
-    if (req)
+    if (reply)
     {
-        req->type        = FILE_TYPE_PIPE;
-        req->attr        = 0;
-        req->access_time = 0;
-        req->write_time  = 0;
-        req->size_high   = 0;
-        req->size_low    = 0;
-        req->links       = 0;
-        req->index_high  = 0;
-        req->index_low   = 0;
-        req->serial      = 0;
+        reply->type        = FILE_TYPE_PIPE;
+        reply->attr        = 0;
+        reply->access_time = 0;
+        reply->write_time  = 0;
+        reply->size_high   = 0;
+        reply->size_low    = 0;
+        reply->links       = 0;
+        reply->index_high  = 0;
+        reply->index_low   = 0;
+        reply->serial      = 0;
     }
     return FD_TYPE_DEFAULT;
 }
@@ -461,10 +461,10 @@
 {
     struct object *obj;
 
-    req->handle = 0;
+    reply->handle = 0;
     if ((obj = create_socket( req->family, req->type, req->protocol )) != NULL)
     {
-        req->handle = alloc_handle( current->process, obj, req->access, req->inherit );
+        reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
         release_object( obj );
     }
 }
@@ -474,10 +474,10 @@
 {
     struct object *obj;
 
-    req->handle = 0;
+    reply->handle = 0;
     if ((obj = accept_socket( req->lhandle )) != NULL)
     {
-        req->handle = alloc_handle( current->process, obj, req->access, req->inherit );
+        reply->handle = alloc_handle( current->process, obj, req->access, req->inherit );
         release_object( obj );
     }
 }
@@ -525,34 +525,31 @@
 DECL_HANDLER(get_socket_event)
 {
     struct sock *sock;
-    size_t size;
 
     sock=(struct sock*)get_handle_obj(current->process,req->handle,GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops);
     if (!sock)
     {
-	req->mask  = 0;
-	req->pmask = 0;
-	req->state = 0;
-	set_error(WSAENOTSOCK);
-	return;
+        reply->mask  = 0;
+        reply->pmask = 0;
+        reply->state = 0;
+        set_error( WSAENOTSOCK );
+        return;
     }
-    req->mask    = sock->mask;
-    req->pmask   = sock->pmask;
-    req->state   = sock->state;
-    size = min( get_req_data_size(req), sizeof(sock->errors) );
-    memcpy( get_req_data(req), sock->errors, size );
-    set_req_data_size( req, size );
+    reply->mask  = sock->mask;
+    reply->pmask = sock->pmask;
+    reply->state = sock->state;
+    set_reply_data( sock->errors, min( get_reply_max_size(), sizeof(sock->errors) ));
 
     if (req->service)
     {
-        if (req->s_event)
+        handle_t s_event = req->s_event;
+        if (s_event)
         {
             struct event *sevent = get_event_obj(current->process, req->s_event, 0);
-            if (sevent == sock->event)
-                req->s_event = 0;
+            if (sevent == sock->event) s_event = 0;
             release_object( sevent );
         }
-        if (!req->s_event)
+        if (!s_event)
         {
             if (req->c_event)
             {
diff --git a/server/thread.c b/server/thread.c
index 8382229..c568750 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -14,9 +14,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
 #include <sys/types.h>
 #include <unistd.h>
 #include <stdarg.h>
@@ -104,7 +101,10 @@
     thread->user_apc.head   = NULL;
     thread->user_apc.tail   = NULL;
     thread->error           = 0;
-    thread->request_fd      = NULL;
+    thread->req_data        = NULL;
+    thread->req_toread      = 0;
+    thread->reply_data      = NULL;
+    thread->reply_towrite   = 0;
     thread->reply_fd        = -1;
     thread->wait_fd         = -1;
     thread->state           = RUNNING;
@@ -115,7 +115,6 @@
     thread->priority        = THREAD_PRIORITY_NORMAL;
     thread->affinity        = 1;
     thread->suspend         = 0;
-    thread->buffer          = (void *)-1;
 
     for (i = 0; i < MAX_INFLIGHT_FDS; i++)
         thread->inflight[i].server = thread->inflight[i].client = -1;
@@ -131,6 +130,7 @@
     init_thread_structure( thread );
 
     thread->process = (struct process *)grab_object( process );
+    thread->request_fd = fd;
     if (!current) current = thread;
 
     if (!booting_thread)  /* first thread ever */
@@ -142,7 +142,6 @@
     if ((thread->next = first_thread) != NULL) thread->next->prev = thread;
     first_thread = thread;
 
-    fcntl( fd, F_SETFL, O_NONBLOCK );
     set_select_events( &thread->obj, POLLIN );  /* start listening to events */
     add_process_thread( thread->process, thread );
     return thread;
@@ -156,6 +155,7 @@
 
     if (event & (POLLERR | POLLHUP)) kill_thread( thread, 0 );
     else if (event & POLLIN) read_request( thread );
+    else if (event & POLLOUT) write_reply( thread );
 }
 
 /* cleanup everything that is no longer needed by a dead thread */
@@ -166,10 +166,11 @@
     struct thread_apc *apc;
 
     while ((apc = thread_dequeue_apc( thread, 0 ))) free( apc );
-    if (thread->buffer != (void *)-1) munmap( thread->buffer, MAX_REQUEST_LENGTH );
+    if (thread->req_data) free( thread->req_data );
+    if (thread->reply_data) free( thread->reply_data );
+    if (thread->request_fd != -1) close( thread->request_fd );
     if (thread->reply_fd != -1) close( thread->reply_fd );
     if (thread->wait_fd != -1) close( thread->wait_fd );
-    if (thread->request_fd) release_object( thread->request_fd );
     if (thread->queue)
     {
         if (thread->process->queue == thread->queue)
@@ -189,10 +190,11 @@
             thread->inflight[i].client = thread->inflight[i].server = -1;
         }
     }
-    thread->buffer = (void *)-1;
+    thread->req_data = NULL;
+    thread->reply_data = NULL;
+    thread->request_fd = -1;
     thread->reply_fd = -1;
     thread->wait_fd = -1;
-    thread->request_fd = NULL;
 }
 
 /* destroy a thread when its refcount is 0 */
@@ -255,7 +257,7 @@
 
 /* set all information about a thread */
 static void set_thread_info( struct thread *thread,
-                             struct set_thread_info_request *req )
+                             const struct set_thread_info_request *req )
 {
     if (req->mask & SET_THREAD_INFO_PRIORITY)
         thread->priority = req->priority;
@@ -467,7 +469,8 @@
 }
 
 /* select on a list of handles */
-static void select_on( int count, void *cookie, handle_t *handles, int flags, int sec, int usec )
+static void select_on( int count, void *cookie, const handle_t *handles,
+                       int flags, int sec, int usec )
 {
     int ret, i;
     struct object *objects[MAXIMUM_WAIT_OBJECTS];
@@ -700,6 +703,8 @@
     remove_process_thread( thread->process, thread );
     wake_up( &thread->obj, 0 );
     detach_thread( thread, violent_death ? SIGTERM : 0 );
+    if (thread->request_fd == thread->obj.fd) thread->request_fd = -1;
+    if (thread->reply_fd == thread->obj.fd) thread->reply_fd = -1;
     remove_select_user( &thread->obj );
     cleanup_thread( thread );
     release_object( thread );
@@ -746,8 +751,9 @@
     struct thread *thread;
     int request_fd = thread_get_inflight_fd( current, req->request_fd );
 
-    if (request_fd == -1)
+    if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1)
     {
+        if (request_fd != -1) close( request_fd );
         set_error( STATUS_INVALID_HANDLE );
         return;
     }
@@ -755,9 +761,9 @@
     if ((thread = create_thread( request_fd, current->process )))
     {
         if (req->suspend) thread->suspend++;
-        req->tid = thread;
-        if ((req->handle = alloc_handle( current->process, thread,
-                                         THREAD_ALL_ACCESS, req->inherit )))
+        reply->tid = thread;
+        if ((reply->handle = alloc_handle( current->process, thread,
+                                           THREAD_ALL_ACCESS, req->inherit )))
         {
             /* thread object will be released when the thread gets killed */
             return;
@@ -778,7 +784,7 @@
         fatal_protocol_error( current, "init_thread: already running\n" );
         goto error;
     }
-    if (reply_fd == -1)
+    if (reply_fd == -1 || fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1)
     {
         fatal_protocol_error( current, "bad reply fd\n" );
         goto error;
@@ -798,10 +804,10 @@
     if (current->process->running_threads > 1)
         generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
 
-    req->pid     = get_process_id( current->process );
-    req->tid     = get_thread_id( current );
-    req->boot    = (current == booting_thread);
-    req->version = SERVER_PROTOCOL_VERSION;
+    reply->pid     = get_process_id( current->process );
+    reply->tid     = get_thread_id( current );
+    reply->boot    = (current == booting_thread);
+    reply->version = SERVER_PROTOCOL_VERSION;
     return;
 
  error:
@@ -809,52 +815,21 @@
     if (wait_fd != -1) close( wait_fd );
 }
 
-/* set the shared buffer for a thread */
-DECL_HANDLER(set_thread_buffer)
-{
-    const unsigned int size = MAX_REQUEST_LENGTH;
-    const unsigned int offset = 0;
-    int fd = thread_get_inflight_fd( current, req->fd );
-
-    req->size = size;
-    req->offset = offset;
-
-    if (fd != -1)
-    {
-        static const char zero;
-
-        /* grow the file to the requested size */
-        if (lseek( fd, size - 1, SEEK_SET ) != -1 && write( fd, &zero, 1 ) == 1)
-        {
-            void *buffer = mmap( 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset );
-            if (buffer == (void *)-1) file_set_error();
-            else
-            {
-                if (current->buffer != (void *)-1) munmap( current->buffer, size );
-                current->buffer = buffer;
-            }
-        }
-        else file_set_error();
-        close( fd );
-    }
-    else set_error( STATUS_INVALID_HANDLE );
-}
-
 /* terminate a thread */
 DECL_HANDLER(terminate_thread)
 {
     struct thread *thread;
 
-    req->self = 0;
-    req->last = 0;
+    reply->self = 0;
+    reply->last = 0;
     if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
     {
         thread->exit_code = req->exit_code;
         if (thread != current) kill_thread( thread, 1 );
         else
         {
-            req->self = 1;
-            req->last = (thread->process->running_threads == 1);
+            reply->self = 1;
+            reply->last = (thread->process->running_threads == 1);
         }
         release_object( thread );
     }
@@ -871,10 +846,10 @@
 
     if (thread)
     {
-        req->tid       = get_thread_id( thread );
-        req->teb       = thread->teb;
-        req->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
-        req->priority  = thread->priority;
+        reply->tid       = get_thread_id( thread );
+        reply->teb       = thread->teb;
+        reply->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STILL_ACTIVE;
+        reply->priority  = thread->priority;
         release_object( thread );
     }
 }
@@ -898,7 +873,7 @@
 
     if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
     {
-        req->count = suspend_thread( thread, 1 );
+        reply->count = suspend_thread( thread, 1 );
         release_object( thread );
     }
 }
@@ -910,7 +885,7 @@
 
     if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
     {
-        req->count = resume_thread( thread );
+        reply->count = resume_thread( thread );
         release_object( thread );
     }
 }
@@ -918,8 +893,8 @@
 /* select on a handle list */
 DECL_HANDLER(select)
 {
-    int count = get_req_data_size(req) / sizeof(int);
-    select_on( count, req->cookie, get_req_data(req), req->flags, req->sec, req->usec );
+    int count = get_req_data_size() / sizeof(int);
+    select_on( count, req->cookie, get_req_data(), req->flags, req->sec, req->usec );
 }
 
 /* queue an APC for a thread */
@@ -944,9 +919,8 @@
         if (!(apc = thread_dequeue_apc( current, !req->alertable )))
         {
             /* no more APCs */
-            req->func    = NULL;
-            req->type    = APC_NONE;
-            set_req_data_size( req, 0 );
+            reply->func = NULL;
+            reply->type = APC_NONE;
             return;
         }
         /* Optimization: ignore APCs that have a NULL func; they are only used
@@ -956,11 +930,10 @@
         free( apc );
     }
     size = apc->nb_args * sizeof(apc->args[0]);
-    if (size > get_req_data_size(req)) size = get_req_data_size(req);
-    req->func = apc->func;
-    req->type = apc->type;
-    memcpy( get_req_data(req), apc->args, size );
-    set_req_data_size( req, size );
+    if (size > get_reply_max_size()) size = get_reply_max_size();
+    reply->func = apc->func;
+    reply->type = apc->type;
+    set_reply_data( apc->args, size );
     free( apc );
 }
 
@@ -970,7 +943,7 @@
     struct thread *thread;
     if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
     {
-        get_selector_entry( thread, req->entry, &req->base, &req->limit, &req->flags );
+        get_selector_entry( thread, req->entry, &reply->base, &reply->limit, &reply->flags );
         release_object( thread );
     }
 }
diff --git a/server/thread.h b/server/thread.h
index 8e88a9d..d6e7779 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -42,35 +42,40 @@
 
 struct thread
 {
-    struct object       obj;       /* object header */
-    struct thread      *next;      /* system-wide thread list */
-    struct thread      *prev;
-    struct thread      *proc_next; /* per-process thread list */
-    struct thread      *proc_prev;
-    struct process     *process;
-    struct mutex       *mutex;       /* list of currently owned mutexes */
-    struct debug_ctx   *debug_ctx;   /* debugger context if this thread is a debugger */
-    struct debug_event *debug_event; /* debug event being sent to debugger */
-    struct msg_queue   *queue;       /* message queue */
-    struct startup_info*info;        /* startup info for child process */
-    struct thread_wait *wait;        /* current wait condition if sleeping */
-    struct apc_queue    system_apc;  /* queue of system async procedure calls */
-    struct apc_queue    user_apc;    /* queue of user async procedure calls */
-    struct inflight_fd  inflight[MAX_INFLIGHT_FDS];  /* fds currently in flight */
-    unsigned int        error;       /* current error code */
-    struct object      *request_fd;  /* fd for receiving client requests */
-    int                 reply_fd;    /* fd to send a reply to a client */
-    int                 wait_fd;     /* fd to use to wake a sleeping client */
-    enum run_state      state;     /* running state */
-    int                 attached;  /* is thread attached with ptrace? */
-    int                 exit_code; /* thread exit code */
-    int                 unix_pid;  /* Unix pid of client */
-    CONTEXT            *context;   /* current context if in an exception handler */
-    void               *teb;       /* TEB address (in client address space) */
-    int                 priority;  /* priority level */
-    int                 affinity;  /* affinity mask */
-    int                 suspend;   /* suspend count */
-    void               *buffer;    /* buffer for communication with the client */
+    struct object          obj;           /* object header */
+    struct thread         *next;          /* system-wide thread list */
+    struct thread         *prev;
+    struct thread         *proc_next;     /* per-process thread list */
+    struct thread         *proc_prev;
+    struct process        *process;
+    struct mutex          *mutex;         /* list of currently owned mutexes */
+    struct debug_ctx      *debug_ctx;     /* debugger context if this thread is a debugger */
+    struct debug_event    *debug_event;   /* debug event being sent to debugger */
+    struct msg_queue      *queue;         /* message queue */
+    struct startup_info   *info;          /* startup info for child process */
+    struct thread_wait    *wait;          /* current wait condition if sleeping */
+    struct apc_queue       system_apc;    /* queue of system async procedure calls */
+    struct apc_queue       user_apc;      /* queue of user async procedure calls */
+    struct inflight_fd     inflight[MAX_INFLIGHT_FDS];  /* fds currently in flight */
+    unsigned int           error;         /* current error code */
+    union generic_request  req;           /* current request */
+    void                  *req_data;      /* variable-size data for request */
+    unsigned int           req_toread;    /* amount of data still to read in request */
+    void                  *reply_data;    /* variable-size data for reply */
+    unsigned int           reply_size;    /* size of reply data */
+    unsigned int           reply_towrite; /* amount of data still to write in reply */
+    int                    request_fd;    /* fd for receiving client requests */
+    int                    reply_fd;      /* fd to send a reply to a client */
+    int                    wait_fd;       /* fd to use to wake a sleeping client */
+    enum run_state         state;         /* running state */
+    int                    attached;      /* is thread attached with ptrace? */
+    int                    exit_code;     /* thread exit code */
+    int                    unix_pid;      /* Unix pid of client */
+    CONTEXT               *context;       /* current context if in an exception handler */
+    void                  *teb;           /* TEB address (in client address space) */
+    int                    priority;      /* priority level */
+    int                    affinity;      /* affinity mask */
+    int                    suspend;       /* suspend count */
 };
 
 struct thread_snapshot
diff --git a/server/timer.c b/server/timer.c
index a76ce41..fd9604a 100644
--- a/server/timer.c
+++ b/server/timer.c
@@ -174,10 +174,10 @@
 {
     struct timer *timer;
 
-    req->handle = 0;
-    if ((timer = create_timer( get_req_data(req), get_req_data_size(req), req->manual )))
+    reply->handle = 0;
+    if ((timer = create_timer( get_req_data(), get_req_data_size(), req->manual )))
     {
-        req->handle = alloc_handle( current->process, timer, TIMER_ALL_ACCESS, req->inherit );
+        reply->handle = alloc_handle( current->process, timer, TIMER_ALL_ACCESS, req->inherit );
         release_object( timer );
     }
 }
@@ -185,8 +185,8 @@
 /* open a handle to a timer */
 DECL_HANDLER(open_timer)
 {
-    req->handle = open_object( get_req_data(req), get_req_data_size(req),
-                               &timer_ops, req->access, req->inherit );
+    reply->handle = open_object( get_req_data(), get_req_data_size(),
+                                 &timer_ops, req->access, req->inherit );
 }
 
 /* set a waitable timer */
diff --git a/server/trace.c b/server/trace.c
index df4617a..f5098cb 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -18,17 +18,15 @@
 #include "unicode.h"
 
 static int cur_pos;
+static const void *cur_data;
+static int cur_size;
 
 /* utility functions */
 
-static const void *get_data( const void *req )
+inline static void remove_data( size_t size )
 {
-    return (char *)get_req_data(req) + cur_pos;
-}
-
-static size_t get_size( const void *req )
-{
-    return get_req_data_size(req) - cur_pos;
+    cur_data = (const char *)cur_data + size;
+    cur_size -= size;
 }
 
 static void dump_uints( const int *ptr, int len )
@@ -42,12 +40,19 @@
     fputc( '}', stderr );
 }
 
-static void dump_rectangle( const void *req, const rectangle_t *rect )
+static void dump_rectangle( const rectangle_t *rect )
 {
     fprintf( stderr, "{%d,%d;%d,%d}",
              rect->left, rect->top, rect->right, rect->bottom );
 }
 
+static void dump_char_info( const char_info_t *info )
+{
+    fprintf( stderr, "{'" );
+    dump_strW( &info->ch, 1, stderr, "\'\'" );
+    fprintf( stderr, "',%04x}", info->attr );
+}
+
 static void dump_context( const CONTEXT *context )
 {
 #ifdef __i386__
@@ -80,10 +85,10 @@
     fputc( '}', stderr );
 }
 
-static size_t dump_varargs_ints( const void *req )
+static void dump_varargs_ints( size_t size )
 {
-    const int *data = get_data(req);
-    size_t len = get_size(req) / sizeof(*data);
+    const int *data = cur_data;
+    size_t len = size / sizeof(*data);
 
     fputc( '{', stderr );
     while (len > 0)
@@ -92,13 +97,13 @@
         if (--len) fputc( ',', stderr );
     }
     fputc( '}', stderr );
-    return get_size(req);
+    remove_data( size );
 }
 
-static size_t dump_varargs_handles( const void *req )
+static void dump_varargs_handles( size_t size )
 {
-    const handle_t *data = get_data(req);
-    size_t len = get_size(req) / sizeof(*data);
+    const handle_t *data = cur_data;
+    size_t len = size / sizeof(*data);
 
     fputc( '{', stderr );
     while (len > 0)
@@ -107,13 +112,13 @@
         if (--len) fputc( ',', stderr );
     }
     fputc( '}', stderr );
-    return get_size(req);
+    remove_data( size );
 }
 
-static size_t dump_varargs_ptrs( const void *req )
+static void dump_varargs_ptrs( size_t size )
 {
-    void * const *data = get_data(req);
-    size_t len = get_size(req) / sizeof(*data);
+    void * const *data = cur_data;
+    size_t len = size / sizeof(*data);
 
     fputc( '{', stderr );
     while (len > 0)
@@ -122,13 +127,13 @@
         if (--len) fputc( ',', stderr );
     }
     fputc( '}', stderr );
-    return get_size(req);
+    remove_data( size );
 }
 
-static size_t dump_varargs_user_handles( const void *req )
+static void dump_varargs_user_handles( size_t size )
 {
-    const user_handle_t *data = get_data(req);
-    size_t len = get_size(req) / sizeof(*data);
+    const user_handle_t *data = cur_data;
+    size_t len = size / sizeof(*data);
 
     fputc( '{', stderr );
     while (len > 0)
@@ -137,13 +142,13 @@
         if (--len) fputc( ',', stderr );
     }
     fputc( '}', stderr );
-    return get_size(req);
+    remove_data( size );
 }
 
-static size_t dump_varargs_bytes( const void *req )
+static void dump_varargs_bytes( size_t size )
 {
-    const unsigned char *data = get_data(req);
-    size_t len = get_size(req);
+    const unsigned char *data = cur_data;
+    size_t len = size;
 
     fputc( '{', stderr );
     while (len > 0)
@@ -152,59 +157,48 @@
         if (--len) fputc( ',', stderr );
     }
     fputc( '}', stderr );
-    return get_size(req);
+    remove_data( size );
 }
 
-static size_t dump_varargs_string( const void *req )
+static void dump_varargs_string( size_t size )
 {
-    fprintf( stderr, "\"%.*s\"", (int)get_size(req), (char *)get_data(req) );
-    return get_size(req);
+    fprintf( stderr, "\"%.*s\"", (int)size, (char *)cur_data );
+    remove_data( size );
 }
 
-static size_t dump_varargs_unicode_len_str( const void *req )
-{
-    const WCHAR *str = get_data(req);
-    int len = *str++ + sizeof(WCHAR);
-    len = min( len, get_size(req) );
-    fprintf( stderr, "L\"" );
-    if (len >= sizeof(WCHAR)) dump_strW( str, (len / sizeof(WCHAR)) - 1, stderr, "\"\"" );
-    fputc( '\"', stderr );
-    return len;
-}
-
-static size_t dump_varargs_unicode_str( const void *req )
+static void dump_varargs_unicode_str( size_t size )
 {
     fprintf( stderr, "L\"" );
-    dump_strW( get_data(req), get_size(req) / sizeof(WCHAR), stderr, "\"\"" );
+    dump_strW( cur_data, size / sizeof(WCHAR), stderr, "\"\"" );
     fputc( '\"', stderr );
-    return get_size(req);
+    remove_data( size );
 }
 
-static size_t dump_varargs_context( const void *req )
+static void dump_varargs_context( size_t size )
 {
-    dump_context( get_data(req) );
-    return get_size(req);
+    dump_context( cur_data );
+    remove_data( size );
 }
 
-static size_t dump_varargs_exc_event( const void *req )
+static void dump_varargs_exc_event( size_t size )
 {
-    const CONTEXT *ptr = get_data(req);
+    const CONTEXT *ptr = cur_data;
     fprintf( stderr, "{context=" );
     dump_context( ptr );
     fprintf( stderr, ",rec=" );
     dump_exc_record( (EXCEPTION_RECORD *)(ptr + 1) );
     fputc( '}', stderr );
-    return get_size(req);
+    remove_data( size );
 }
 
-static size_t dump_varargs_debug_event( const void *req )
+static void dump_varargs_debug_event( size_t size )
 {
-    const debug_event_t *event = get_data(req);
+    const debug_event_t *event = cur_data;
 
-    if (!get_size(req))
+    if (!size)
     {
         fprintf( stderr, "{}" );
-        return 0;
+        return;
     }
     switch(event->code)
     {
@@ -258,13 +252,13 @@
         fprintf( stderr, "{code=??? (%d)}", event->code );
         break;
     }
-    return get_size(req);
+    remove_data( size );
 }
 
-static size_t dump_varargs_input_records( const void *req )
+static void dump_varargs_input_records( size_t size )
 {
-    const INPUT_RECORD *rec = get_data(req);
-    size_t len = get_size(req) / sizeof(*rec);
+    const INPUT_RECORD *rec = cur_data;
+    size_t len = size / sizeof(*rec);
 
     fputc( '{', stderr );
     while (len > 0)
@@ -274,13 +268,13 @@
         if (--len) fputc( ',', stderr );
     }
     fputc( '}', stderr );
-    return get_size(req);
+    remove_data( size );
 }
 
-static size_t dump_varargs_properties( const void *req )
+static void dump_varargs_properties( size_t size )
 {
-    const property_data_t *prop = get_data(req);
-    size_t len = get_size(req) / sizeof(*prop);
+    const property_data_t *prop = cur_data;
+    size_t len = size / sizeof(*prop);
 
     fputc( '{', stderr );
     while (len > 0)
@@ -291,7 +285,7 @@
         if (--len) fputc( ',', stderr );
     }
     fputc( '}', stderr );
-    return get_size(req);
+    remove_data( size );
 }
 
 typedef void (*dump_func)( const void *req );
@@ -310,10 +304,10 @@
     fprintf( stderr, " hstderr=%d,", req->hstderr );
     fprintf( stderr, " cmd_show=%d,", req->cmd_show );
     fprintf( stderr, " filename=" );
-    cur_pos += dump_varargs_string( req );
+    dump_varargs_string( cur_size );
 }
 
-static void dump_new_process_reply( const struct new_process_request *req )
+static void dump_new_process_reply( const struct new_process_reply *req )
 {
     fprintf( stderr, " info=%d", req->info );
 }
@@ -325,7 +319,7 @@
     fprintf( stderr, " tinherit=%d", req->tinherit );
 }
 
-static void dump_get_new_process_info_reply( const struct get_new_process_info_request *req )
+static void dump_get_new_process_info_reply( const struct get_new_process_info_reply *req )
 {
     fprintf( stderr, " pid=%p,", req->pid );
     fprintf( stderr, " phandle=%d,", req->phandle );
@@ -341,7 +335,7 @@
     fprintf( stderr, " request_fd=%d", req->request_fd );
 }
 
-static void dump_new_thread_reply( const struct new_thread_request *req )
+static void dump_new_thread_reply( const struct new_thread_reply *req )
 {
     fprintf( stderr, " tid=%p,", req->tid );
     fprintf( stderr, " handle=%d", req->handle );
@@ -358,7 +352,7 @@
     fprintf( stderr, " ppid=%d", req->ppid );
 }
 
-static void dump_init_process_reply( const struct init_process_request *req )
+static void dump_init_process_reply( const struct init_process_reply *req )
 {
     fprintf( stderr, " create_flags=%d,", req->create_flags );
     fprintf( stderr, " start_flags=%d,", req->start_flags );
@@ -369,7 +363,7 @@
     fprintf( stderr, " hstderr=%d,", req->hstderr );
     fprintf( stderr, " cmd_show=%d,", req->cmd_show );
     fprintf( stderr, " filename=" );
-    cur_pos += dump_varargs_string( req );
+    dump_varargs_string( cur_size );
 }
 
 static void dump_init_process_done_request( const struct init_process_done_request *req )
@@ -381,7 +375,7 @@
     fprintf( stderr, " gui=%d", req->gui );
 }
 
-static void dump_init_process_done_reply( const struct init_process_done_request *req )
+static void dump_init_process_done_reply( const struct init_process_done_reply *req )
 {
     fprintf( stderr, " debugged=%d", req->debugged );
 }
@@ -395,7 +389,7 @@
     fprintf( stderr, " wait_fd=%d", req->wait_fd );
 }
 
-static void dump_init_thread_reply( const struct init_thread_request *req )
+static void dump_init_thread_reply( const struct init_thread_reply *req )
 {
     fprintf( stderr, " pid=%p,", req->pid );
     fprintf( stderr, " tid=%p,", req->tid );
@@ -403,24 +397,13 @@
     fprintf( stderr, " version=%d", req->version );
 }
 
-static void dump_set_thread_buffer_request( const struct set_thread_buffer_request *req )
-{
-    fprintf( stderr, " fd=%d", req->fd );
-}
-
-static void dump_set_thread_buffer_reply( const struct set_thread_buffer_request *req )
-{
-    fprintf( stderr, " offset=%08x,", req->offset );
-    fprintf( stderr, " size=%08x", req->size );
-}
-
 static void dump_terminate_process_request( const struct terminate_process_request *req )
 {
     fprintf( stderr, " handle=%d,", req->handle );
     fprintf( stderr, " exit_code=%d", req->exit_code );
 }
 
-static void dump_terminate_process_reply( const struct terminate_process_request *req )
+static void dump_terminate_process_reply( const struct terminate_process_reply *req )
 {
     fprintf( stderr, " self=%d", req->self );
 }
@@ -431,7 +414,7 @@
     fprintf( stderr, " exit_code=%d", req->exit_code );
 }
 
-static void dump_terminate_thread_reply( const struct terminate_thread_request *req )
+static void dump_terminate_thread_reply( const struct terminate_thread_reply *req )
 {
     fprintf( stderr, " self=%d,", req->self );
     fprintf( stderr, " last=%d", req->last );
@@ -442,7 +425,7 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_get_process_info_reply( const struct get_process_info_request *req )
+static void dump_get_process_info_reply( const struct get_process_info_reply *req )
 {
     fprintf( stderr, " pid=%p,", req->pid );
     fprintf( stderr, " debugged=%d,", req->debugged );
@@ -466,7 +449,7 @@
     fprintf( stderr, " tid_in=%p", req->tid_in );
 }
 
-static void dump_get_thread_info_reply( const struct get_thread_info_request *req )
+static void dump_get_thread_info_reply( const struct get_thread_info_reply *req )
 {
     fprintf( stderr, " tid=%p,", req->tid );
     fprintf( stderr, " teb=%p,", req->teb );
@@ -487,7 +470,7 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_suspend_thread_reply( const struct suspend_thread_request *req )
+static void dump_suspend_thread_reply( const struct suspend_thread_reply *req )
 {
     fprintf( stderr, " count=%d", req->count );
 }
@@ -497,7 +480,7 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_resume_thread_reply( const struct resume_thread_request *req )
+static void dump_resume_thread_reply( const struct resume_thread_reply *req )
 {
     fprintf( stderr, " count=%d", req->count );
 }
@@ -529,12 +512,12 @@
     fprintf( stderr, " alertable=%d", req->alertable );
 }
 
-static void dump_get_apc_reply( const struct get_apc_request *req )
+static void dump_get_apc_reply( const struct get_apc_reply *req )
 {
     fprintf( stderr, " func=%p,", req->func );
     fprintf( stderr, " type=%d,", req->type );
     fprintf( stderr, " args=" );
-    cur_pos += dump_varargs_ptrs( req );
+    dump_varargs_ptrs( cur_size );
 }
 
 static void dump_close_handle_request( const struct close_handle_request *req )
@@ -542,7 +525,7 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_close_handle_reply( const struct close_handle_request *req )
+static void dump_close_handle_reply( const struct close_handle_reply *req )
 {
     fprintf( stderr, " fd=%d", req->fd );
 }
@@ -555,7 +538,7 @@
     fprintf( stderr, " fd=%d", req->fd );
 }
 
-static void dump_set_handle_info_reply( const struct set_handle_info_request *req )
+static void dump_set_handle_info_reply( const struct set_handle_info_reply *req )
 {
     fprintf( stderr, " old_flags=%d,", req->old_flags );
     fprintf( stderr, " cur_fd=%d", req->cur_fd );
@@ -571,7 +554,7 @@
     fprintf( stderr, " options=%d", req->options );
 }
 
-static void dump_dup_handle_reply( const struct dup_handle_request *req )
+static void dump_dup_handle_reply( const struct dup_handle_reply *req )
 {
     fprintf( stderr, " handle=%d,", req->handle );
     fprintf( stderr, " fd=%d", req->fd );
@@ -584,7 +567,7 @@
     fprintf( stderr, " inherit=%d", req->inherit );
 }
 
-static void dump_open_process_reply( const struct open_process_request *req )
+static void dump_open_process_reply( const struct open_process_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -596,7 +579,7 @@
     fprintf( stderr, " sec=%d,", req->sec );
     fprintf( stderr, " usec=%d,", req->usec );
     fprintf( stderr, " handles=" );
-    cur_pos += dump_varargs_handles( req );
+    dump_varargs_handles( cur_size );
 }
 
 static void dump_create_event_request( const struct create_event_request *req )
@@ -605,10 +588,10 @@
     fprintf( stderr, " initial_state=%d,", req->initial_state );
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_create_event_reply( const struct create_event_request *req )
+static void dump_create_event_reply( const struct create_event_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -624,10 +607,10 @@
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_open_event_reply( const struct open_event_request *req )
+static void dump_open_event_reply( const struct open_event_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -637,10 +620,10 @@
     fprintf( stderr, " owned=%d,", req->owned );
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_create_mutex_reply( const struct create_mutex_request *req )
+static void dump_create_mutex_reply( const struct create_mutex_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -655,10 +638,10 @@
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_open_mutex_reply( const struct open_mutex_request *req )
+static void dump_open_mutex_reply( const struct open_mutex_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -669,10 +652,10 @@
     fprintf( stderr, " max=%08x,", req->max );
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_create_semaphore_reply( const struct create_semaphore_request *req )
+static void dump_create_semaphore_reply( const struct create_semaphore_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -683,7 +666,7 @@
     fprintf( stderr, " count=%08x", req->count );
 }
 
-static void dump_release_semaphore_reply( const struct release_semaphore_request *req )
+static void dump_release_semaphore_reply( const struct release_semaphore_reply *req )
 {
     fprintf( stderr, " prev_count=%08x", req->prev_count );
 }
@@ -693,10 +676,10 @@
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_open_semaphore_reply( const struct open_semaphore_request *req )
+static void dump_open_semaphore_reply( const struct open_semaphore_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -710,10 +693,10 @@
     fprintf( stderr, " attrs=%08x,", req->attrs );
     fprintf( stderr, " drive_type=%d,", req->drive_type );
     fprintf( stderr, " filename=" );
-    cur_pos += dump_varargs_string( req );
+    dump_varargs_string( cur_size );
 }
 
-static void dump_create_file_reply( const struct create_file_request *req )
+static void dump_create_file_reply( const struct create_file_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -725,7 +708,7 @@
     fprintf( stderr, " fd=%d", req->fd );
 }
 
-static void dump_alloc_file_handle_reply( const struct alloc_file_handle_request *req )
+static void dump_alloc_file_handle_reply( const struct alloc_file_handle_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -736,7 +719,7 @@
     fprintf( stderr, " access=%08x", req->access );
 }
 
-static void dump_get_handle_fd_reply( const struct get_handle_fd_request *req )
+static void dump_get_handle_fd_reply( const struct get_handle_fd_reply *req )
 {
     fprintf( stderr, " fd=%d,", req->fd );
     fprintf( stderr, " type=%d", req->type );
@@ -750,7 +733,7 @@
     fprintf( stderr, " whence=%d", req->whence );
 }
 
-static void dump_set_file_pointer_reply( const struct set_file_pointer_request *req )
+static void dump_set_file_pointer_reply( const struct set_file_pointer_reply *req )
 {
     fprintf( stderr, " new_low=%d,", req->new_low );
     fprintf( stderr, " new_high=%d", req->new_high );
@@ -778,7 +761,7 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_get_file_info_reply( const struct get_file_info_request *req )
+static void dump_get_file_info_reply( const struct get_file_info_reply *req )
 {
     fprintf( stderr, " type=%d,", req->type );
     fprintf( stderr, " attr=%d,", req->attr );
@@ -815,7 +798,7 @@
     fprintf( stderr, " inherit=%d", req->inherit );
 }
 
-static void dump_create_pipe_reply( const struct create_pipe_request *req )
+static void dump_create_pipe_reply( const struct create_pipe_reply *req )
 {
     fprintf( stderr, " handle_read=%d,", req->handle_read );
     fprintf( stderr, " handle_write=%d", req->handle_write );
@@ -830,7 +813,7 @@
     fprintf( stderr, " protocol=%d", req->protocol );
 }
 
-static void dump_create_socket_reply( const struct create_socket_request *req )
+static void dump_create_socket_reply( const struct create_socket_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -842,7 +825,7 @@
     fprintf( stderr, " inherit=%d", req->inherit );
 }
 
-static void dump_accept_socket_reply( const struct accept_socket_request *req )
+static void dump_accept_socket_reply( const struct accept_socket_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -862,13 +845,13 @@
     fprintf( stderr, " c_event=%d", req->c_event );
 }
 
-static void dump_get_socket_event_reply( const struct get_socket_event_request *req )
+static void dump_get_socket_event_reply( const struct get_socket_event_reply *req )
 {
     fprintf( stderr, " mask=%08x,", req->mask );
     fprintf( stderr, " pmask=%08x,", req->pmask );
     fprintf( stderr, " state=%08x,", req->state );
     fprintf( stderr, " errors=" );
-    cur_pos += dump_varargs_ints( req );
+    dump_varargs_ints( cur_size );
 }
 
 static void dump_enable_socket_event_request( const struct enable_socket_event_request *req )
@@ -886,7 +869,7 @@
     fprintf( stderr, " pid=%p", req->pid );
 }
 
-static void dump_alloc_console_reply( const struct alloc_console_request *req )
+static void dump_alloc_console_reply( const struct alloc_console_reply *req )
 {
     fprintf( stderr, " handle_in=%d,", req->handle_in );
     fprintf( stderr, " event=%d", req->event );
@@ -901,10 +884,10 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_get_console_renderer_events_reply( const struct get_console_renderer_events_request *req )
+static void dump_get_console_renderer_events_reply( const struct get_console_renderer_events_reply *req )
 {
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_open_console_request( const struct open_console_request *req )
@@ -915,7 +898,7 @@
     fprintf( stderr, " share=%d", req->share );
 }
 
-static void dump_open_console_reply( const struct open_console_request *req )
+static void dump_open_console_reply( const struct open_console_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -925,7 +908,7 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_get_console_mode_reply( const struct get_console_mode_request *req )
+static void dump_get_console_mode_reply( const struct get_console_mode_reply *req )
 {
     fprintf( stderr, " mode=%d", req->mode );
 }
@@ -944,7 +927,7 @@
     fprintf( stderr, " history_mode=%d,", req->history_mode );
     fprintf( stderr, " history_size=%d,", req->history_size );
     fprintf( stderr, " title=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
 static void dump_get_console_input_info_request( const struct get_console_input_info_request *req )
@@ -952,20 +935,20 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_get_console_input_info_reply( const struct get_console_input_info_request *req )
+static void dump_get_console_input_info_reply( const struct get_console_input_info_reply *req )
 {
     fprintf( stderr, " history_mode=%d,", req->history_mode );
     fprintf( stderr, " history_size=%d,", req->history_size );
     fprintf( stderr, " history_index=%d,", req->history_index );
     fprintf( stderr, " title=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
 static void dump_append_console_input_history_request( const struct append_console_input_history_request *req )
 {
     fprintf( stderr, " handle=%d,", req->handle );
     fprintf( stderr, " line=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
 static void dump_get_console_input_history_request( const struct get_console_input_history_request *req )
@@ -974,10 +957,11 @@
     fprintf( stderr, " index=%d", req->index );
 }
 
-static void dump_get_console_input_history_reply( const struct get_console_input_history_request *req )
+static void dump_get_console_input_history_reply( const struct get_console_input_history_reply *req )
 {
+    fprintf( stderr, " total=%d,", req->total );
     fprintf( stderr, " line=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
 static void dump_create_console_output_request( const struct create_console_output_request *req )
@@ -988,7 +972,7 @@
     fprintf( stderr, " inherit=%d", req->inherit );
 }
 
-static void dump_create_console_output_reply( const struct create_console_output_request *req )
+static void dump_create_console_output_reply( const struct create_console_output_reply *req )
 {
     fprintf( stderr, " handle_out=%d", req->handle_out );
 }
@@ -1017,7 +1001,7 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_get_console_output_info_reply( const struct get_console_output_info_request *req )
+static void dump_get_console_output_info_reply( const struct get_console_output_info_reply *req )
 {
     fprintf( stderr, " cursor_size=%d,", req->cursor_size );
     fprintf( stderr, " cursor_visible=%d,", req->cursor_visible );
@@ -1038,10 +1022,10 @@
 {
     fprintf( stderr, " handle=%d,", req->handle );
     fprintf( stderr, " rec=" );
-    cur_pos += dump_varargs_input_records( req );
+    dump_varargs_input_records( cur_size );
 }
 
-static void dump_write_console_input_reply( const struct write_console_input_request *req )
+static void dump_write_console_input_reply( const struct write_console_input_reply *req )
 {
     fprintf( stderr, " written=%d", req->written );
 }
@@ -1052,24 +1036,44 @@
     fprintf( stderr, " flush=%d", req->flush );
 }
 
-static void dump_read_console_input_reply( const struct read_console_input_request *req )
+static void dump_read_console_input_reply( const struct read_console_input_reply *req )
 {
     fprintf( stderr, " read=%d,", req->read );
     fprintf( stderr, " rec=" );
-    cur_pos += dump_varargs_input_records( req );
+    dump_varargs_input_records( cur_size );
 }
 
 static void dump_write_console_output_request( const struct write_console_output_request *req )
 {
     fprintf( stderr, " handle=%d,", req->handle );
-    fprintf( stderr, " mode=%d,", req->mode );
     fprintf( stderr, " x=%d,", req->x );
     fprintf( stderr, " y=%d,", req->y );
+    fprintf( stderr, " mode=%d,", req->mode );
+    fprintf( stderr, " wrap=%d,", req->wrap );
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
-static void dump_write_console_output_reply( const struct write_console_output_request *req )
+static void dump_write_console_output_reply( const struct write_console_output_reply *req )
+{
+    fprintf( stderr, " written=%d,", req->written );
+    fprintf( stderr, " width=%d,", req->width );
+    fprintf( stderr, " height=%d", req->height );
+}
+
+static void dump_fill_console_output_request( const struct fill_console_output_request *req )
+{
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " x=%d,", req->x );
+    fprintf( stderr, " y=%d,", req->y );
+    fprintf( stderr, " mode=%d,", req->mode );
+    fprintf( stderr, " count=%d,", req->count );
+    fprintf( stderr, " wrap=%d,", req->wrap );
+    fprintf( stderr, " data=" );
+    dump_char_info( &req->data );
+}
+
+static void dump_fill_console_output_reply( const struct fill_console_output_reply *req )
 {
     fprintf( stderr, " written=%d", req->written );
 }
@@ -1079,16 +1083,16 @@
     fprintf( stderr, " handle=%d,", req->handle );
     fprintf( stderr, " x=%d,", req->x );
     fprintf( stderr, " y=%d,", req->y );
-    fprintf( stderr, " w=%d,", req->w );
-    fprintf( stderr, " h=%d", req->h );
+    fprintf( stderr, " mode=%d,", req->mode );
+    fprintf( stderr, " wrap=%d", req->wrap );
 }
 
-static void dump_read_console_output_reply( const struct read_console_output_request *req )
+static void dump_read_console_output_reply( const struct read_console_output_reply *req )
 {
-    fprintf( stderr, " eff_w=%d,", req->eff_w );
-    fprintf( stderr, " eff_h=%d,", req->eff_h );
+    fprintf( stderr, " width=%d,", req->width );
+    fprintf( stderr, " height=%d,", req->height );
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_move_console_output_request( const struct move_console_output_request *req )
@@ -1108,7 +1112,7 @@
     fprintf( stderr, " filter=%d", req->filter );
 }
 
-static void dump_create_change_notification_reply( const struct create_change_notification_request *req )
+static void dump_create_change_notification_reply( const struct create_change_notification_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1121,10 +1125,10 @@
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " file_handle=%d,", req->file_handle );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_create_mapping_reply( const struct create_mapping_request *req )
+static void dump_create_mapping_reply( const struct create_mapping_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1134,10 +1138,10 @@
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_open_mapping_reply( const struct open_mapping_request *req )
+static void dump_open_mapping_reply( const struct open_mapping_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1147,7 +1151,7 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_get_mapping_info_reply( const struct get_mapping_info_request *req )
+static void dump_get_mapping_info_reply( const struct get_mapping_info_reply *req )
 {
     fprintf( stderr, " size_high=%d,", req->size_high );
     fprintf( stderr, " size_low=%d,", req->size_low );
@@ -1166,7 +1170,7 @@
     fprintf( stderr, " id=%d", req->id );
 }
 
-static void dump_create_device_reply( const struct create_device_request *req )
+static void dump_create_device_reply( const struct create_device_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1178,7 +1182,7 @@
     fprintf( stderr, " pid=%p", req->pid );
 }
 
-static void dump_create_snapshot_reply( const struct create_snapshot_request *req )
+static void dump_create_snapshot_reply( const struct create_snapshot_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1189,7 +1193,7 @@
     fprintf( stderr, " reset=%d", req->reset );
 }
 
-static void dump_next_process_reply( const struct next_process_request *req )
+static void dump_next_process_reply( const struct next_process_reply *req )
 {
     fprintf( stderr, " count=%d,", req->count );
     fprintf( stderr, " pid=%p,", req->pid );
@@ -1203,7 +1207,7 @@
     fprintf( stderr, " reset=%d", req->reset );
 }
 
-static void dump_next_thread_reply( const struct next_thread_request *req )
+static void dump_next_thread_reply( const struct next_thread_reply *req )
 {
     fprintf( stderr, " count=%d,", req->count );
     fprintf( stderr, " pid=%p,", req->pid );
@@ -1218,7 +1222,7 @@
     fprintf( stderr, " reset=%d", req->reset );
 }
 
-static void dump_next_module_reply( const struct next_module_request *req )
+static void dump_next_module_reply( const struct next_module_reply *req )
 {
     fprintf( stderr, " pid=%p,", req->pid );
     fprintf( stderr, " base=%p", req->base );
@@ -1229,37 +1233,37 @@
     fprintf( stderr, " get_handle=%d", req->get_handle );
 }
 
-static void dump_wait_debug_event_reply( const struct wait_debug_event_request *req )
+static void dump_wait_debug_event_reply( const struct wait_debug_event_reply *req )
 {
     fprintf( stderr, " pid=%p,", req->pid );
     fprintf( stderr, " tid=%p,", req->tid );
     fprintf( stderr, " wait=%d,", req->wait );
     fprintf( stderr, " event=" );
-    cur_pos += dump_varargs_debug_event( req );
+    dump_varargs_debug_event( cur_size );
 }
 
 static void dump_queue_exception_event_request( const struct queue_exception_event_request *req )
 {
     fprintf( stderr, " first=%d,", req->first );
     fprintf( stderr, " record=" );
-    cur_pos += dump_varargs_exc_event( req );
+    dump_varargs_exc_event( cur_size );
 }
 
-static void dump_queue_exception_event_reply( const struct queue_exception_event_request *req )
+static void dump_queue_exception_event_reply( const struct queue_exception_event_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
 
 static void dump_get_exception_status_request( const struct get_exception_status_request *req )
 {
+    fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_get_exception_status_reply( const struct get_exception_status_request *req )
+static void dump_get_exception_status_reply( const struct get_exception_status_reply *req )
 {
-    fprintf( stderr, " handle=%d,", req->handle );
     fprintf( stderr, " status=%d,", req->status );
     fprintf( stderr, " context=" );
-    cur_pos += dump_varargs_context( req );
+    dump_varargs_context( cur_size );
 }
 
 static void dump_output_debug_string_request( const struct output_debug_string_request *req )
@@ -1284,25 +1288,23 @@
 static void dump_read_process_memory_request( const struct read_process_memory_request *req )
 {
     fprintf( stderr, " handle=%d,", req->handle );
-    fprintf( stderr, " addr=%p,", req->addr );
-    fprintf( stderr, " len=%d", req->len );
+    fprintf( stderr, " addr=%p", req->addr );
 }
 
-static void dump_read_process_memory_reply( const struct read_process_memory_request *req )
+static void dump_read_process_memory_reply( const struct read_process_memory_reply *req )
 {
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_write_process_memory_request( const struct write_process_memory_request *req )
 {
     fprintf( stderr, " handle=%d,", req->handle );
     fprintf( stderr, " addr=%p,", req->addr );
-    fprintf( stderr, " len=%d,", req->len );
     fprintf( stderr, " first_mask=%08x,", req->first_mask );
     fprintf( stderr, " last_mask=%08x,", req->last_mask );
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_create_key_request( const struct create_key_request *req )
@@ -1311,14 +1313,15 @@
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " options=%08x,", req->options );
     fprintf( stderr, " modif=%ld,", req->modif );
+    fprintf( stderr, " namelen=%d,", req->namelen );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_len_str( req );
+    dump_varargs_unicode_str( min(cur_size,req->namelen) );
     fputc( ',', stderr );
     fprintf( stderr, " class=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_create_key_reply( const struct create_key_request *req )
+static void dump_create_key_reply( const struct create_key_reply *req )
 {
     fprintf( stderr, " hkey=%d,", req->hkey );
     fprintf( stderr, " created=%d", req->created );
@@ -1329,10 +1332,10 @@
     fprintf( stderr, " parent=%d,", req->parent );
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_open_key_reply( const struct open_key_request *req )
+static void dump_open_key_reply( const struct open_key_reply *req )
 {
     fprintf( stderr, " hkey=%d", req->hkey );
 }
@@ -1346,10 +1349,10 @@
 {
     fprintf( stderr, " hkey=%d,", req->hkey );
     fprintf( stderr, " index=%d,", req->index );
-    fprintf( stderr, " full=%d", req->full );
+    fprintf( stderr, " info_class=%d", req->info_class );
 }
 
-static void dump_enum_key_reply( const struct enum_key_request *req )
+static void dump_enum_key_reply( const struct enum_key_reply *req )
 {
     fprintf( stderr, " subkeys=%d,", req->subkeys );
     fprintf( stderr, " max_subkey=%d,", req->max_subkey );
@@ -1358,65 +1361,66 @@
     fprintf( stderr, " max_value=%d,", req->max_value );
     fprintf( stderr, " max_data=%d,", req->max_data );
     fprintf( stderr, " modif=%ld,", req->modif );
+    fprintf( stderr, " total=%d,", req->total );
+    fprintf( stderr, " namelen=%d,", req->namelen );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_len_str( req );
+    dump_varargs_unicode_str( min(cur_size,req->namelen) );
     fputc( ',', stderr );
     fprintf( stderr, " class=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
 static void dump_set_key_value_request( const struct set_key_value_request *req )
 {
     fprintf( stderr, " hkey=%d,", req->hkey );
     fprintf( stderr, " type=%d,", req->type );
-    fprintf( stderr, " total=%08x,", req->total );
-    fprintf( stderr, " offset=%08x,", req->offset );
+    fprintf( stderr, " namelen=%d,", req->namelen );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_len_str( req );
+    dump_varargs_unicode_str( min(cur_size,req->namelen) );
     fputc( ',', stderr );
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_get_key_value_request( const struct get_key_value_request *req )
 {
     fprintf( stderr, " hkey=%d,", req->hkey );
-    fprintf( stderr, " offset=%08x,", req->offset );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_len_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_get_key_value_reply( const struct get_key_value_request *req )
+static void dump_get_key_value_reply( const struct get_key_value_reply *req )
 {
     fprintf( stderr, " type=%d,", req->type );
-    fprintf( stderr, " len=%d,", req->len );
+    fprintf( stderr, " total=%d,", req->total );
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_enum_key_value_request( const struct enum_key_value_request *req )
 {
     fprintf( stderr, " hkey=%d,", req->hkey );
     fprintf( stderr, " index=%d,", req->index );
-    fprintf( stderr, " offset=%08x", req->offset );
+    fprintf( stderr, " info_class=%d", req->info_class );
 }
 
-static void dump_enum_key_value_reply( const struct enum_key_value_request *req )
+static void dump_enum_key_value_reply( const struct enum_key_value_reply *req )
 {
     fprintf( stderr, " type=%d,", req->type );
-    fprintf( stderr, " len=%d,", req->len );
+    fprintf( stderr, " total=%d,", req->total );
+    fprintf( stderr, " namelen=%d,", req->namelen );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_len_str( req );
+    dump_varargs_unicode_str( min(cur_size,req->namelen) );
     fputc( ',', stderr );
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_delete_key_value_request( const struct delete_key_value_request *req )
 {
     fprintf( stderr, " hkey=%d,", req->hkey );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
 static void dump_load_registry_request( const struct load_registry_request *req )
@@ -1424,7 +1428,7 @@
     fprintf( stderr, " hkey=%d,", req->hkey );
     fprintf( stderr, " file=%d,", req->file );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
 static void dump_save_registry_request( const struct save_registry_request *req )
@@ -1437,7 +1441,7 @@
 {
     fprintf( stderr, " hkey=%d,", req->hkey );
     fprintf( stderr, " file=" );
-    cur_pos += dump_varargs_string( req );
+    dump_varargs_string( cur_size );
 }
 
 static void dump_set_registry_levels_request( const struct set_registry_levels_request *req )
@@ -1452,10 +1456,10 @@
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " manual=%d,", req->manual );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_create_timer_reply( const struct create_timer_request *req )
+static void dump_create_timer_reply( const struct create_timer_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1465,10 +1469,10 @@
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " inherit=%d,", req->inherit );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_open_timer_reply( const struct open_timer_request *req )
+static void dump_open_timer_reply( const struct open_timer_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1494,10 +1498,10 @@
     fprintf( stderr, " flags=%08x", req->flags );
 }
 
-static void dump_get_thread_context_reply( const struct get_thread_context_request *req )
+static void dump_get_thread_context_reply( const struct get_thread_context_reply *req )
 {
     fprintf( stderr, " context=" );
-    cur_pos += dump_varargs_context( req );
+    dump_varargs_context( cur_size );
 }
 
 static void dump_set_thread_context_request( const struct set_thread_context_request *req )
@@ -1505,7 +1509,7 @@
     fprintf( stderr, " handle=%d,", req->handle );
     fprintf( stderr, " flags=%08x,", req->flags );
     fprintf( stderr, " context=" );
-    cur_pos += dump_varargs_context( req );
+    dump_varargs_context( cur_size );
 }
 
 static void dump_get_selector_entry_request( const struct get_selector_entry_request *req )
@@ -1514,7 +1518,7 @@
     fprintf( stderr, " entry=%d", req->entry );
 }
 
-static void dump_get_selector_entry_reply( const struct get_selector_entry_request *req )
+static void dump_get_selector_entry_reply( const struct get_selector_entry_reply *req )
 {
     fprintf( stderr, " base=%08x,", req->base );
     fprintf( stderr, " limit=%08x,", req->limit );
@@ -1525,10 +1529,10 @@
 {
     fprintf( stderr, " local=%d,", req->local );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_add_atom_reply( const struct add_atom_request *req )
+static void dump_add_atom_reply( const struct add_atom_reply *req )
 {
     fprintf( stderr, " atom=%04x", req->atom );
 }
@@ -1543,10 +1547,10 @@
 {
     fprintf( stderr, " local=%d,", req->local );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
-static void dump_find_atom_reply( const struct find_atom_request *req )
+static void dump_find_atom_reply( const struct find_atom_reply *req )
 {
     fprintf( stderr, " atom=%04x", req->atom );
 }
@@ -1557,11 +1561,11 @@
     fprintf( stderr, " local=%d", req->local );
 }
 
-static void dump_get_atom_name_reply( const struct get_atom_name_request *req )
+static void dump_get_atom_name_reply( const struct get_atom_name_reply *req )
 {
     fprintf( stderr, " count=%d,", req->count );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
 static void dump_init_atom_table_request( const struct init_atom_table_request *req )
@@ -1573,7 +1577,7 @@
 {
 }
 
-static void dump_get_msg_queue_reply( const struct get_msg_queue_request *req )
+static void dump_get_msg_queue_reply( const struct get_msg_queue_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1585,7 +1589,7 @@
     fprintf( stderr, " skip_wait=%d", req->skip_wait );
 }
 
-static void dump_set_queue_mask_reply( const struct set_queue_mask_request *req )
+static void dump_set_queue_mask_reply( const struct set_queue_mask_reply *req )
 {
     fprintf( stderr, " wake_bits=%08x,", req->wake_bits );
     fprintf( stderr, " changed_bits=%08x", req->changed_bits );
@@ -1596,7 +1600,7 @@
     fprintf( stderr, " clear=%d", req->clear );
 }
 
-static void dump_get_queue_status_reply( const struct get_queue_status_request *req )
+static void dump_get_queue_status_reply( const struct get_queue_status_reply *req )
 {
     fprintf( stderr, " wake_bits=%08x,", req->wake_bits );
     fprintf( stderr, " changed_bits=%08x", req->changed_bits );
@@ -1608,7 +1612,7 @@
     fprintf( stderr, " timeout=%d", req->timeout );
 }
 
-static void dump_wait_input_idle_reply( const struct wait_input_idle_request *req )
+static void dump_wait_input_idle_reply( const struct wait_input_idle_reply *req )
 {
     fprintf( stderr, " event=%d", req->event );
 }
@@ -1627,7 +1631,7 @@
     fprintf( stderr, " info=%08x,", req->info );
     fprintf( stderr, " timeout=%d,", req->timeout );
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_get_message_request( const struct get_message_request *req )
@@ -1638,7 +1642,7 @@
     fprintf( stderr, " get_last=%08x", req->get_last );
 }
 
-static void dump_get_message_reply( const struct get_message_request *req )
+static void dump_get_message_reply( const struct get_message_reply *req )
 {
     fprintf( stderr, " type=%d,", req->type );
     fprintf( stderr, " win=%08x,", req->win );
@@ -1649,8 +1653,9 @@
     fprintf( stderr, " y=%d,", req->y );
     fprintf( stderr, " time=%08x,", req->time );
     fprintf( stderr, " info=%08x,", req->info );
+    fprintf( stderr, " total=%d,", req->total );
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_reply_message_request( const struct reply_message_request *req )
@@ -1658,7 +1663,7 @@
     fprintf( stderr, " result=%08x,", req->result );
     fprintf( stderr, " remove=%d,", req->remove );
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_get_message_reply_request( const struct get_message_reply_request *req )
@@ -1666,11 +1671,11 @@
     fprintf( stderr, " cancel=%d", req->cancel );
 }
 
-static void dump_get_message_reply_reply( const struct get_message_reply_request *req )
+static void dump_get_message_reply_reply( const struct get_message_reply_reply *req )
 {
     fprintf( stderr, " result=%08x,", req->result );
     fprintf( stderr, " data=" );
-    cur_pos += dump_varargs_bytes( req );
+    dump_varargs_bytes( cur_size );
 }
 
 static void dump_set_win_timer_request( const struct set_win_timer_request *req )
@@ -1696,10 +1701,10 @@
     fprintf( stderr, " attributes=%08x,", req->attributes );
     fprintf( stderr, " sharing=%08x,", req->sharing );
     fprintf( stderr, " name=" );
-    cur_pos += dump_varargs_string( req );
+    dump_varargs_string( cur_size );
 }
 
-static void dump_create_serial_reply( const struct create_serial_request *req )
+static void dump_create_serial_reply( const struct create_serial_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1709,7 +1714,7 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_get_serial_info_reply( const struct get_serial_info_request *req )
+static void dump_get_serial_info_reply( const struct get_serial_info_reply *req )
 {
     fprintf( stderr, " readinterval=%08x,", req->readinterval );
     fprintf( stderr, " readconst=%08x,", req->readconst );
@@ -1740,7 +1745,7 @@
     fprintf( stderr, " type=%d", req->type );
 }
 
-static void dump_create_async_reply( const struct create_async_request *req )
+static void dump_create_async_reply( const struct create_async_reply *req )
 {
     fprintf( stderr, " timeout=%d", req->timeout );
 }
@@ -1754,10 +1759,10 @@
     fprintf( stderr, " insize=%08x,", req->insize );
     fprintf( stderr, " timeout=%08x,", req->timeout );
     fprintf( stderr, " filename=" );
-    cur_pos += dump_varargs_string( req );
+    dump_varargs_string( cur_size );
 }
 
-static void dump_create_named_pipe_reply( const struct create_named_pipe_request *req )
+static void dump_create_named_pipe_reply( const struct create_named_pipe_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1766,10 +1771,10 @@
 {
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " filename=" );
-    cur_pos += dump_varargs_string( req );
+    dump_varargs_string( cur_size );
 }
 
-static void dump_open_named_pipe_reply( const struct open_named_pipe_request *req )
+static void dump_open_named_pipe_reply( const struct open_named_pipe_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -1787,7 +1792,7 @@
     fprintf( stderr, " overlapped=%p,", req->overlapped );
     fprintf( stderr, " func=%p,", req->func );
     fprintf( stderr, " filename=" );
-    cur_pos += dump_varargs_string( req );
+    dump_varargs_string( cur_size );
 }
 
 static void dump_disconnect_named_pipe_request( const struct disconnect_named_pipe_request *req )
@@ -1800,7 +1805,7 @@
     fprintf( stderr, " handle=%d", req->handle );
 }
 
-static void dump_get_named_pipe_info_reply( const struct get_named_pipe_info_request *req )
+static void dump_get_named_pipe_info_reply( const struct get_named_pipe_info_reply *req )
 {
     fprintf( stderr, " flags=%08x,", req->flags );
     fprintf( stderr, " maxinstances=%08x,", req->maxinstances );
@@ -1815,7 +1820,7 @@
     fprintf( stderr, " atom=%04x", req->atom );
 }
 
-static void dump_create_window_reply( const struct create_window_request *req )
+static void dump_create_window_reply( const struct create_window_reply *req )
 {
     fprintf( stderr, " handle=%08x", req->handle );
 }
@@ -1827,7 +1832,7 @@
     fprintf( stderr, " previous=%08x", req->previous );
 }
 
-static void dump_link_window_reply( const struct link_window_request *req )
+static void dump_link_window_reply( const struct link_window_reply *req )
 {
     fprintf( stderr, " full_parent=%08x", req->full_parent );
 }
@@ -1843,7 +1848,7 @@
     fprintf( stderr, " owner=%08x", req->owner );
 }
 
-static void dump_set_window_owner_reply( const struct set_window_owner_request *req )
+static void dump_set_window_owner_reply( const struct set_window_owner_reply *req )
 {
     fprintf( stderr, " full_owner=%08x", req->full_owner );
 }
@@ -1853,7 +1858,7 @@
     fprintf( stderr, " handle=%08x", req->handle );
 }
 
-static void dump_get_window_info_reply( const struct get_window_info_request *req )
+static void dump_get_window_info_reply( const struct get_window_info_reply *req )
 {
     fprintf( stderr, " full_handle=%08x,", req->full_handle );
     fprintf( stderr, " pid=%p,", req->pid );
@@ -1872,7 +1877,7 @@
     fprintf( stderr, " user_data=%p", req->user_data );
 }
 
-static void dump_set_window_info_reply( const struct set_window_info_request *req )
+static void dump_set_window_info_reply( const struct set_window_info_reply *req )
 {
     fprintf( stderr, " old_style=%08x,", req->old_style );
     fprintf( stderr, " old_ex_style=%08x,", req->old_ex_style );
@@ -1886,11 +1891,11 @@
     fprintf( stderr, " handle=%08x", req->handle );
 }
 
-static void dump_get_window_parents_reply( const struct get_window_parents_request *req )
+static void dump_get_window_parents_reply( const struct get_window_parents_reply *req )
 {
     fprintf( stderr, " count=%d,", req->count );
     fprintf( stderr, " parents=" );
-    cur_pos += dump_varargs_user_handles( req );
+    dump_varargs_user_handles( cur_size );
 }
 
 static void dump_get_window_children_request( const struct get_window_children_request *req )
@@ -1900,11 +1905,11 @@
     fprintf( stderr, " tid=%p", req->tid );
 }
 
-static void dump_get_window_children_reply( const struct get_window_children_request *req )
+static void dump_get_window_children_reply( const struct get_window_children_reply *req )
 {
     fprintf( stderr, " count=%d,", req->count );
     fprintf( stderr, " children=" );
-    cur_pos += dump_varargs_user_handles( req );
+    dump_varargs_user_handles( cur_size );
 }
 
 static void dump_get_window_tree_request( const struct get_window_tree_request *req )
@@ -1912,7 +1917,7 @@
     fprintf( stderr, " handle=%08x", req->handle );
 }
 
-static void dump_get_window_tree_reply( const struct get_window_tree_request *req )
+static void dump_get_window_tree_reply( const struct get_window_tree_reply *req )
 {
     fprintf( stderr, " parent=%08x,", req->parent );
     fprintf( stderr, " owner=%08x,", req->owner );
@@ -1928,10 +1933,10 @@
 {
     fprintf( stderr, " handle=%08x,", req->handle );
     fprintf( stderr, " window=" );
-    dump_rectangle( req, &req->window );
+    dump_rectangle( &req->window );
     fprintf( stderr, "," );
     fprintf( stderr, " client=" );
-    dump_rectangle( req, &req->client );
+    dump_rectangle( &req->client );
 }
 
 static void dump_get_window_rectangles_request( const struct get_window_rectangles_request *req )
@@ -1939,13 +1944,13 @@
     fprintf( stderr, " handle=%08x", req->handle );
 }
 
-static void dump_get_window_rectangles_reply( const struct get_window_rectangles_request *req )
+static void dump_get_window_rectangles_reply( const struct get_window_rectangles_reply *req )
 {
     fprintf( stderr, " window=" );
-    dump_rectangle( req, &req->window );
+    dump_rectangle( &req->window );
     fprintf( stderr, "," );
     fprintf( stderr, " client=" );
-    dump_rectangle( req, &req->client );
+    dump_rectangle( &req->client );
 }
 
 static void dump_get_window_text_request( const struct get_window_text_request *req )
@@ -1953,17 +1958,17 @@
     fprintf( stderr, " handle=%08x", req->handle );
 }
 
-static void dump_get_window_text_reply( const struct get_window_text_request *req )
+static void dump_get_window_text_reply( const struct get_window_text_reply *req )
 {
     fprintf( stderr, " text=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
 static void dump_set_window_text_request( const struct set_window_text_request *req )
 {
     fprintf( stderr, " handle=%08x,", req->handle );
     fprintf( stderr, " text=" );
-    cur_pos += dump_varargs_unicode_str( req );
+    dump_varargs_unicode_str( cur_size );
 }
 
 static void dump_inc_window_paint_count_request( const struct inc_window_paint_count_request *req )
@@ -1978,7 +1983,7 @@
     fprintf( stderr, " to=%08x", req->to );
 }
 
-static void dump_get_windows_offset_reply( const struct get_windows_offset_request *req )
+static void dump_get_windows_offset_reply( const struct get_windows_offset_reply *req )
 {
     fprintf( stderr, " x=%d,", req->x );
     fprintf( stderr, " y=%d", req->y );
@@ -1998,7 +2003,7 @@
     fprintf( stderr, " atom=%04x", req->atom );
 }
 
-static void dump_remove_window_property_reply( const struct remove_window_property_request *req )
+static void dump_remove_window_property_reply( const struct remove_window_property_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -2009,7 +2014,7 @@
     fprintf( stderr, " atom=%04x", req->atom );
 }
 
-static void dump_get_window_property_reply( const struct get_window_property_request *req )
+static void dump_get_window_property_reply( const struct get_window_property_reply *req )
 {
     fprintf( stderr, " handle=%d", req->handle );
 }
@@ -2019,10 +2024,11 @@
     fprintf( stderr, " window=%08x", req->window );
 }
 
-static void dump_get_window_properties_reply( const struct get_window_properties_request *req )
+static void dump_get_window_properties_reply( const struct get_window_properties_reply *req )
 {
+    fprintf( stderr, " total=%d,", req->total );
     fprintf( stderr, " props=" );
-    cur_pos += dump_varargs_properties( req );
+    dump_varargs_properties( cur_size );
 }
 
 static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
@@ -2033,7 +2039,6 @@
     (dump_func)dump_init_process_request,
     (dump_func)dump_init_process_done_request,
     (dump_func)dump_init_thread_request,
-    (dump_func)dump_set_thread_buffer_request,
     (dump_func)dump_terminate_process_request,
     (dump_func)dump_terminate_thread_request,
     (dump_func)dump_get_process_info_request,
@@ -2092,6 +2097,7 @@
     (dump_func)dump_write_console_input_request,
     (dump_func)dump_read_console_input_request,
     (dump_func)dump_write_console_output_request,
+    (dump_func)dump_fill_console_output_request,
     (dump_func)dump_read_console_output_request,
     (dump_func)dump_move_console_output_request,
     (dump_func)dump_create_change_notification_request,
@@ -2184,7 +2190,6 @@
     (dump_func)dump_init_process_reply,
     (dump_func)dump_init_process_done_reply,
     (dump_func)dump_init_thread_reply,
-    (dump_func)dump_set_thread_buffer_reply,
     (dump_func)dump_terminate_process_reply,
     (dump_func)dump_terminate_thread_reply,
     (dump_func)dump_get_process_info_reply,
@@ -2243,6 +2248,7 @@
     (dump_func)dump_write_console_input_reply,
     (dump_func)dump_read_console_input_reply,
     (dump_func)dump_write_console_output_reply,
+    (dump_func)dump_fill_console_output_reply,
     (dump_func)dump_read_console_output_reply,
     (dump_func)0,
     (dump_func)dump_create_change_notification_reply,
@@ -2335,7 +2341,6 @@
     "init_process",
     "init_process_done",
     "init_thread",
-    "set_thread_buffer",
     "terminate_process",
     "terminate_thread",
     "get_process_info",
@@ -2394,6 +2399,7 @@
     "write_console_input",
     "read_console_input",
     "write_console_output",
+    "fill_console_output",
     "read_console_output",
     "move_console_output",
     "create_change_notification",
@@ -2538,36 +2544,41 @@
     return buffer;
 }
 
-void trace_request( struct thread *thread, const union generic_request *request )
+void trace_request(void)
 {
-    enum request req = request->header.req;
-    cur_pos = 0;
+    enum request req = current->req.request_header.req;
     if (req < REQ_NB_REQUESTS)
     {
-        fprintf( stderr, "%08x: %s(", (unsigned int)thread, req_names[req] );
-        cur_pos = 0;
-        req_dumpers[req]( request );
+        fprintf( stderr, "%08x: %s(", (unsigned int)current, req_names[req] );
+        if (req_dumpers[req])
+        {
+            cur_pos = 0;
+            cur_data = get_req_data();
+            cur_size = get_req_data_size();
+            req_dumpers[req]( &current->req );
+        }
         fprintf( stderr, " )\n" );
     }
-    else fprintf( stderr, "%08x: %d(?)\n", (unsigned int)thread, req );
+    else fprintf( stderr, "%08x: %d(?)\n", (unsigned int)current, req );
 }
 
-void trace_reply( struct thread *thread, const union generic_request *request )
+void trace_reply( enum request req, const union generic_reply *reply )
 {
-    enum request req = request->header.req;
     if (req < REQ_NB_REQUESTS)
     {
         fprintf( stderr, "%08x: %s() = %s",
-                 (unsigned int)thread, req_names[req], get_status_name(thread->error) );
+                 (unsigned int)current, req_names[req], get_status_name(current->error) );
         if (reply_dumpers[req])
         {
             fprintf( stderr, " {" );
             cur_pos = 0;
-            reply_dumpers[req]( request );
+            cur_data = current->reply_data;
+            cur_size = reply->reply_header.reply_size;
+            reply_dumpers[req]( reply );
             fprintf( stderr, " }" );
         }
         fputc( '\n', stderr );
     }
     else fprintf( stderr, "%08x: %d() = %s\n",
-                  (unsigned int)thread, req, get_status_name(thread->error) );
+                  (unsigned int)current, req, get_status_name(current->error) );
 }
diff --git a/server/window.c b/server/window.c
index 1a3c4f2..c1ffe84 100644
--- a/server/window.c
+++ b/server/window.c
@@ -215,23 +215,6 @@
     free( win->properties );
 }
 
-/* enum all properties into the data array */
-static int enum_properties( struct window *win, property_data_t *data, int max )
-{
-    int i, count;
-
-    for (i = count = 0; i < win->prop_inuse && count < max; i++)
-    {
-        if (win->properties[i].type == PROP_TYPE_FREE) continue;
-        data->atom   = win->properties[i].atom;
-        data->string = (win->properties[i].type == PROP_TYPE_STRING);
-        data->handle = win->properties[i].handle;
-        data++;
-        count++;
-    }
-    return count;
-}
-
 /* destroy a window */
 static void destroy_window( struct window *win )
 {
@@ -376,7 +359,7 @@
 /* create a window */
 DECL_HANDLER(create_window)
 {
-    req->handle = 0;
+    reply->handle = 0;
     if (!req->parent)  /* return desktop window */
     {
         if (!top_window)
@@ -384,7 +367,7 @@
             if (!(top_window = create_window( NULL, NULL, req->atom ))) return;
             top_window->thread = NULL;  /* no thread owns the desktop */
         }
-        req->handle = top_window->handle;
+        reply->handle = top_window->handle;
     }
     else
     {
@@ -400,7 +383,7 @@
             return;
         }
         if (!(win = create_window( parent, owner, req->atom ))) return;
-        req->handle = win->handle;
+        reply->handle = win->handle;
     }
 }
 
@@ -418,7 +401,7 @@
         set_error( STATUS_INVALID_PARAMETER );
         return;
     }
-    req->full_parent = parent ? parent->handle : 0;
+    reply->full_parent = parent ? parent->handle : 0;
     if (parent && req->previous)
     {
         if (req->previous == (user_handle_t)1)  /* special case: HWND_BOTTOM */
@@ -467,7 +450,7 @@
         return;
     }
     win->owner = owner;
-    req->full_owner = owner->handle;
+    reply->full_owner = owner->handle;
 }
 
 
@@ -476,16 +459,16 @@
 {
     struct window *win = get_window( req->handle );
 
-    req->full_handle = 0;
-    req->tid = req->pid = 0;
+    reply->full_handle = 0;
+    reply->tid = reply->pid = 0;
     if (win)
     {
-        req->full_handle = win->handle;
+        reply->full_handle = win->handle;
         if (win->thread)
         {
-            req->tid  = get_thread_id( win->thread );
-            req->pid  = get_process_id( win->thread->process );
-            req->atom = win->atom;
+            reply->tid  = get_thread_id( win->thread );
+            reply->pid  = get_process_id( win->thread->process );
+            reply->atom = win->atom;
         }
     }
 }
@@ -496,11 +479,11 @@
 {
     struct window *win = get_window( req->handle );
     if (!win) return;
-    req->old_style     = win->style;
-    req->old_ex_style  = win->ex_style;
-    req->old_id        = win->id;
-    req->old_instance  = win->instance;
-    req->old_user_data = win->user_data;
+    reply->old_style     = win->style;
+    reply->old_ex_style  = win->ex_style;
+    reply->old_id        = win->id;
+    reply->old_instance  = win->instance;
+    reply->old_user_data = win->user_data;
     if (req->flags & SET_WIN_STYLE) win->style = req->style;
     if (req->flags & SET_WIN_EXSTYLE) win->ex_style = req->ex_style;
     if (req->flags & SET_WIN_ID) win->id = req->id;
@@ -514,16 +497,15 @@
 {
     struct window *ptr, *win = get_window( req->handle );
     int total = 0;
+    user_handle_t *data;
     size_t len;
 
     if (win) for (ptr = win->parent; ptr; ptr = ptr->parent) total++;
 
-    req->count = total;
-    len = min( get_req_data_size(req), total * sizeof(user_handle_t) );
-    set_req_data_size( req, len );
-    if (len)
+    reply->count = total;
+    len = min( get_reply_max_size(), total * sizeof(user_handle_t) );
+    if (len && ((data = set_reply_data_size( len ))))
     {
-        user_handle_t *data = get_req_data(req);
         for (ptr = win->parent; ptr && len; ptr = ptr->parent, len -= sizeof(*data))
             *data++ = ptr->handle;
     }
@@ -535,6 +517,7 @@
 {
     struct window *ptr, *parent = get_window( req->parent );
     int total = 0;
+    user_handle_t *data;
     size_t len;
 
     if (parent)
@@ -545,12 +528,10 @@
             total++;
         }
 
-    req->count = total;
-    len = min( get_req_data_size(req), total * sizeof(user_handle_t) );
-    set_req_data_size( req, len );
-    if (len)
+    reply->count = total;
+    len = min( get_reply_max_size(), total * sizeof(user_handle_t) );
+    if (len && ((data = set_reply_data_size( len ))))
     {
-        user_handle_t *data = get_req_data(req);
         for (ptr = parent->first_child; ptr && len; ptr = ptr->next, len -= sizeof(*data))
         {
             if (req->atom && ptr->atom != req->atom) continue;
@@ -571,24 +552,24 @@
     if (win->parent)
     {
         struct window *parent = win->parent;
-        req->parent        = parent->handle;
-        req->owner         = win->owner ? win->owner->handle : 0;
-        req->next_sibling  = win->next ? win->next->handle : 0;
-        req->prev_sibling  = win->prev ? win->prev->handle : 0;
-        req->first_sibling = parent->first_child ? parent->first_child->handle : 0;
-        req->last_sibling  = parent->last_child ? parent->last_child->handle : 0;
+        reply->parent        = parent->handle;
+        reply->owner         = win->owner ? win->owner->handle : 0;
+        reply->next_sibling  = win->next ? win->next->handle : 0;
+        reply->prev_sibling  = win->prev ? win->prev->handle : 0;
+        reply->first_sibling = parent->first_child ? parent->first_child->handle : 0;
+        reply->last_sibling  = parent->last_child ? parent->last_child->handle : 0;
     }
     else
     {
-        req->parent        = 0;
-        req->owner         = 0;
-        req->next_sibling  = 0;
-        req->prev_sibling  = 0;
-        req->first_sibling = 0;
-        req->last_sibling  = 0;
+        reply->parent        = 0;
+        reply->owner         = 0;
+        reply->next_sibling  = 0;
+        reply->prev_sibling  = 0;
+        reply->first_sibling = 0;
+        reply->last_sibling  = 0;
     }
-    req->first_child = win->first_child ? win->first_child->handle : 0;
-    req->last_child  = win->last_child ? win->last_child->handle : 0;
+    reply->first_child = win->first_child ? win->first_child->handle : 0;
+    reply->last_child  = win->last_child ? win->last_child->handle : 0;
 }
 
 
@@ -612,8 +593,8 @@
 
     if (win)
     {
-        req->window = win->window_rect;
-        req->client = win->client_rect;
+        reply->window = win->window_rect;
+        reply->client = win->client_rect;
     }
 }
 
@@ -622,15 +603,13 @@
 DECL_HANDLER(get_window_text)
 {
     struct window *win = get_window( req->handle );
-    size_t len = 0;
 
     if (win && win->text)
     {
-        len = strlenW( win->text ) * sizeof(WCHAR);
-        if (len > get_req_data_size(req)) len = get_req_data_size(req);
-        memcpy( get_req_data(req), win->text, len );
+        size_t len = strlenW( win->text ) * sizeof(WCHAR);
+        if (len > get_reply_max_size()) len = get_reply_max_size();
+        set_reply_data( win->text, len );
     }
-    set_req_data_size( req, len );
 }
 
 
@@ -642,11 +621,11 @@
     if (win)
     {
         WCHAR *text = NULL;
-        size_t len = get_req_data_size(req) / sizeof(WCHAR);
+        size_t len = get_req_data_size() / sizeof(WCHAR);
         if (len)
         {
             if (!(text = mem_alloc( (len+1) * sizeof(WCHAR) ))) return;
-            memcpy( text, get_req_data(req), len * sizeof(WCHAR) );
+            memcpy( text, get_req_data(), len * sizeof(WCHAR) );
             text[len] = 0;
         }
         if (win->text) free( win->text );
@@ -674,14 +653,14 @@
 {
     struct window *win;
 
-    req->x = req->y = 0;
+    reply->x = reply->y = 0;
     if (req->from)
     {
         if (!(win = get_window( req->from ))) return;
         while (win)
         {
-            req->x += win->client_rect.left;
-            req->y += win->client_rect.top;
+            reply->x += win->client_rect.left;
+            reply->y += win->client_rect.top;
             win = win->parent;
         }
     }
@@ -690,8 +669,8 @@
         if (!(win = get_window( req->to ))) return;
         while (win)
         {
-            req->x -= win->client_rect.left;
-            req->y -= win->client_rect.top;
+            reply->x -= win->client_rect.left;
+            reply->y -= win->client_rect.top;
             win = win->parent;
         }
     }
@@ -712,8 +691,8 @@
 DECL_HANDLER(remove_window_property)
 {
     struct window *win = get_window( req->window );
-    req->handle = 0;
-    if (win) req->handle = remove_property( win, req->atom );
+    reply->handle = 0;
+    if (win) reply->handle = remove_property( win, req->atom );
 }
 
 
@@ -721,18 +700,35 @@
 DECL_HANDLER(get_window_property)
 {
     struct window *win = get_window( req->window );
-    req->handle = 0;
-    if (win) req->handle = get_property( win, req->atom );
+    reply->handle = 0;
+    if (win) reply->handle = get_property( win, req->atom );
 }
 
 
 /* get the list of properties of a window */
 DECL_HANDLER(get_window_properties)
 {
-    int count = 0;
-    property_data_t *data = get_req_data(req);
+    property_data_t *data;
+    int i, count, max = get_reply_max_size() / sizeof(*data);
     struct window *win = get_window( req->window );
 
-    if (win) count = enum_properties( win, data, get_req_data_size(req) / sizeof(*data) );
-    set_req_data_size( req, count * sizeof(*data) );
+    reply->total = 0;
+    if (!win) return;
+
+    for (i = count = 0; i < win->prop_inuse; i++)
+        if (win->properties[i].type != PROP_TYPE_FREE) count++;
+    reply->total = count;
+
+    if (count > max) count = max;
+    if (!count || !(data = set_reply_data_size( count * sizeof(*data) ))) return;
+
+    for (i = 0; i < win->prop_inuse && count; i++)
+    {
+        if (win->properties[i].type == PROP_TYPE_FREE) continue;
+        data->atom   = win->properties[i].atom;
+        data->string = (win->properties[i].type == PROP_TYPE_STRING);
+        data->handle = win->properties[i].handle;
+        data++;
+        count--;
+    }
 }
diff --git a/tools/make_requests b/tools/make_requests
index ed3c59e..34cd54d 100755
--- a/tools/make_requests
+++ b/tools/make_requests
@@ -16,10 +16,12 @@
     "unsigned int"  => "%08x",
     "void*"         => "%p",
     "time_t"        => "%ld",
+    "size_t"        => "%d",
     "handle_t"      => "%d",
     "atom_t"        => "%04x",
     "user_handle_t" => "%08x",
     "rectangle_t"   => "&dump_rectangle",
+    "char_info_t"   => "&dump_char_info",
 );
 
 my @requests = ();
@@ -44,16 +46,24 @@
 
 &PARSE_REQUESTS;
 
-### Build the request list
+### Build the request list and structures
 
 print SERVER_PROT "\n\nenum request\n{\n";
 foreach $req (@requests) { print SERVER_PROT "    REQ_$req,\n"; }
 print SERVER_PROT "    REQ_NB_REQUESTS\n};\n\n";
+
 print SERVER_PROT "union generic_request\n{\n";
 print SERVER_PROT "    struct request_max_size max_size;\n";
-print SERVER_PROT "    struct request_header header;\n";
-foreach $req (@requests) { print SERVER_PROT "    struct ${req}_request $req;\n"; }
+print SERVER_PROT "    struct request_header request_header;\n";
+foreach $req (@requests) { print SERVER_PROT "    struct ${req}_request ${req}_request;\n"; }
+print SERVER_PROT "};\n";
+
+print SERVER_PROT "union generic_reply\n{\n";
+print SERVER_PROT "    struct request_max_size max_size;\n";
+print SERVER_PROT "    struct reply_header reply_header;\n";
+foreach $req (@requests) { print SERVER_PROT "    struct ${req}_reply ${req}_reply;\n"; }
 print SERVER_PROT "};\n\n";
+
 printf SERVER_PROT "#define SERVER_PROTOCOL_VERSION %d\n\n", $protocol + 1;
 print SERVER_PROT "#endif /* __WINE_WINE_SERVER_PROTOCOL_H */\n";
 close SERVER_PROT;
@@ -89,7 +99,7 @@
 
 foreach $req (@requests) { push @request_lines, "DECL_HANDLER($req);\n"; }
 push @request_lines, "\n#ifdef WANT_REQUEST_HANDLERS\n\n";
-push @request_lines, "typedef void (*req_handler)( void *req );\n";
+push @request_lines, "typedef void (*req_handler)( const void *req, void *reply );\n";
 push @request_lines, "static const req_handler req_handlers[REQ_NB_REQUESTS] =\n{\n";
 foreach $req (@requests)
 {
@@ -145,6 +155,9 @@
         if (/^\@REPLY/)
         {
             die "Misplaced \@REPLY" unless $state == 2;
+            print SERVER_PROT "};\n";
+            print SERVER_PROT "struct ${name}_reply\n{\n";
+            print SERVER_PROT "    struct reply_header __header;\n";
             $state++;
             next;
         }
@@ -154,6 +167,13 @@
             die "Misplaced \@END" unless ($state == 2 || $state == 3);
             print SERVER_PROT "};\n";
 
+            if ($state == 2)  # build dummy reply struct
+            {
+                print SERVER_PROT "struct ${name}_reply\n{\n";
+                print SERVER_PROT "    struct reply_header __header;\n";
+                print SERVER_PROT "};\n";
+            }
+
             # got a complete request
             push @requests, $name;
             &DO_DUMP_FUNC( $name, "request", @in_struct);
@@ -175,17 +195,23 @@
                 next;
             }
 
-            if (/^\s*VARARG\((\w+),(\w+)\)/)
+            if (/^\s*VARARG\((\w+),(\w+),(\w+)\)/)
             {
                 $var = $1;
-                $type = "&dump_varargs_" . $2;
+                $type = "dump_varargs_" . $2 . "( min(cur_size,req->" . $3 . ") )";
                 s!(VARARG\(.*\)\s*;)!/* $1 */!;
             }
-            elsif (/^\s*(\w+\**(\s+\w+\**)*)\s+(\w+)(\[[1]\])?;/)
+            elsif (/^\s*VARARG\((\w+),(\w+)\)/)
             {
-                $type = $1 . ($4 || "");
+                $var = $1;
+                $type = "dump_varargs_" . $2 . "( cur_size )";
+                s!(VARARG\(.*\)\s*;)!/* $1 */!;
+            }
+            elsif (/^\s*(\w+\**(\s+\w+\**)*)\s+(\w+);/)
+            {
+                $type = $1;
                 $var = $3;
-                die "Unrecognized type $type" unless (defined($formats{$type}) || $4);
+                die "Unrecognized type $type" unless defined($formats{$type});
             }
             else
             {
@@ -207,7 +233,7 @@
 {
     my $name = shift;
     my $req = shift;
-    push @trace_lines, "static void dump_${name}_$req( const struct ${name}_request *req )\n{\n";
+    push @trace_lines, "static void dump_${name}_$req( const struct ${name}_$req *req )\n{\n";
     while ($#_ >= 0)
     {
 	my $type = shift;
@@ -218,8 +244,7 @@
             {
                 my $func = $1;
                 push @trace_lines, "    fprintf( stderr, \" $var=\" );\n";
-                if ($type =~ /[1]/) { push @trace_lines, "    $func( req, req->$var );\n"; }
-                else { push @trace_lines, "    $func( req, &req->$var );\n"; }
+                push @trace_lines, "    $func( &req->$var );\n";
                 push @trace_lines, "    fprintf( stderr, \",\" );\n" if ($#_ > 0);
             }
             else
@@ -232,18 +257,10 @@
 	}
 	else  # must be some varargs format
 	{
-            if ($type =~ /^&(.*)/)
-            {
-                my $func = $1;
-                push @trace_lines, "    fprintf( stderr, \" $var=\" );\n";
-                push @trace_lines, "    cur_pos += $func( req );\n";
-                push @trace_lines, "    fputc( ',', stderr );\n" if ($#_ > 0);
-            }
-            else
-            {
-                push @trace_lines, "    fprintf( stderr, \" $var=\" );\n";
-                push @trace_lines, "    dump_varargs_${name}_${req}( req );\n";
-            }
+            my $func = $type;
+            push @trace_lines, "    fprintf( stderr, \" $var=\" );\n";
+            push @trace_lines, "    $func;\n";
+            push @trace_lines, "    fputc( ',', stderr );\n" if ($#_ > 0);
         }
     }
     push @trace_lines, "}\n\n";
diff --git a/win32/console.c b/win32/console.c
index 25e3c82..0ed21e3 100644
--- a/win32/console.c
+++ b/win32/console.c
@@ -47,7 +47,7 @@
 
     SERVER_START_REQ(free_console)
     {
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -172,7 +172,7 @@
     HANDLE 		handle_in = INVALID_HANDLE_VALUE;
     HANDLE		handle_out = INVALID_HANDLE_VALUE;
     HANDLE 		handle_err = INVALID_HANDLE_VALUE;
-    STARTUPINFOA	si;
+    STARTUPINFOW si;
 
     TRACE("()\n");
 
@@ -206,7 +206,7 @@
     SetStdHandle(STD_OUTPUT_HANDLE, handle_out);
     SetStdHandle(STD_ERROR_HANDLE,  handle_err);
 
-    GetStartupInfoA(&si);
+    GetStartupInfoW(&si);
     if (si.dwFlags & STARTF_USESIZE)
     {
 	COORD	c;
@@ -217,7 +217,7 @@
     if (si.dwFlags & STARTF_USEFILLATTRIBUTE)
 	SetConsoleTextAttribute(handle_out, si.dwFillAttribute);
     if (si.lpTitle)
-	SetConsoleTitleA(si.lpTitle);
+	SetConsoleTitleW(si.lpTitle);
 
     SetLastError(ERROR_SUCCESS);
 
@@ -245,19 +245,14 @@
     unsigned	read = 0;
     DWORD	mode;
 
-    count = min(count, REQUEST_MAX_VAR_SIZE/sizeof(INPUT_RECORD));
-    
-    SERVER_START_VAR_REQ(read_console_input, count*sizeof(INPUT_RECORD))
+    SERVER_START_REQ( read_console_input )
     {
         req->handle = handle;
         req->flush = flush;
-        if ((ret = !SERVER_CALL_ERR()))
-        {
-            if (count) memcpy(buffer, server_data_ptr(req), server_data_size(req));
-            read = req->read;
-        }
+        wine_server_set_reply( req, buffer, count * sizeof(INPUT_RECORD) );
+        if ((ret = !wine_server_call_err( req ))) read = reply->read;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     if (count && flush && GetConsoleMode(handle, &mode) && (mode & ENABLE_PROCESSED_INPUT))
     {
 	int	i;
@@ -356,33 +351,6 @@
 }
 
 
-/******************************************************************************
- * ReadConsoleInputA [KERNEL32.@]  Reads data from a console
- *
- * PARAMS
- *    hConsoleInput        [I] Handle to console input buffer
- *    lpBuffer             [O] Address of buffer for read data
- *    nLength              [I] Number of records to read
- *    lpNumberOfEventsRead [O] Address of number of records read
- *
- * RETURNS
- *    Success: TRUE
- *    Failure: FALSE
- */
-BOOL WINAPI ReadConsoleInputA(HANDLE hConsoleInput, LPINPUT_RECORD lpBuffer,
-                              DWORD nLength, LPDWORD lpNumberOfEventsRead)
-{
-    DWORD	nread;
-    
-    if (!ReadConsoleInputW(hConsoleInput, lpBuffer, nLength, &nread))
-	return FALSE;
-    
-    /* FIXME for now, the low part of unicode would do as ASCII */
-    if (lpNumberOfEventsRead) *lpNumberOfEventsRead = nread;
-    return TRUE;
-}
-
-
 /***********************************************************************
  *            ReadConsoleInputW   (KERNEL32.@)
  */
@@ -412,53 +380,74 @@
 }
 
 
-/***********************************************************************
- *            FlushConsoleInputBuffer   (KERNEL32.@)
- */
-BOOL WINAPI FlushConsoleInputBuffer(HANDLE handle)
-{
-    return read_console_input(handle, NULL, 0, NULL, TRUE);
-}
-
-
-/***********************************************************************
- *            PeekConsoleInputA   (KERNEL32.@)
+/******************************************************************************
+ * WriteConsoleOutputCharacterW [KERNEL32.@]  Copies character to consecutive
+ * 					      cells in the console screen buffer
  *
- * Gets 'count' first events (or less) from input queue.
+ * PARAMS
+ *    hConsoleOutput    [I] Handle to screen buffer
+ *    str               [I] Pointer to buffer with chars to write
+ *    length            [I] Number of cells to write to
+ *    coord             [I] Coords of first cell
+ *    lpNumCharsWritten [O] Pointer to number of cells written
  *
- * Does not need a complex console.
+ * RETURNS
+ *    Success: TRUE
+ *    Failure: FALSE
+ * 
  */
-BOOL WINAPI PeekConsoleInputA(HANDLE hConsoleInput, LPINPUT_RECORD pirBuffer, 
-			      DWORD cInRecords, LPDWORD lpcRead)
+BOOL WINAPI WriteConsoleOutputCharacterW( HANDLE hConsoleOutput, LPCWSTR str, DWORD length,
+                                          COORD coord, LPDWORD lpNumCharsWritten )
 {
-    /* FIXME: Hmm. Fix this if we get UNICODE input. */
-    return PeekConsoleInputW(hConsoleInput, pirBuffer, cInRecords, lpcRead);
-}
+    BOOL ret;
 
+    TRACE("(%d,%s,%ld,%dx%d,%p)\n", hConsoleOutput,
+          debugstr_wn(str, length), length, coord.X, coord.Y, lpNumCharsWritten);
 
-/***********************************************************************
- *            PeekConsoleInputW   (KERNEL32.@)
- */
-BOOL WINAPI PeekConsoleInputW(HANDLE hConsoleInput, LPINPUT_RECORD pirBuffer, 
-			      DWORD cInRecords, LPDWORD lpcRead)
-{
-    if (!cInRecords)
+    SERVER_START_REQ( write_console_output )
     {
-        if (lpcRead) *lpcRead = 0;
-        return TRUE;
+        req->handle = hConsoleOutput;
+        req->x      = coord.X;
+        req->y      = coord.Y;
+        req->mode   = CHAR_INFO_MODE_TEXT;
+        req->wrap   = TRUE;
+        wine_server_add_data( req, str, length * sizeof(WCHAR) );
+        if ((ret = !wine_server_call_err( req )))
+        {
+            if (lpNumCharsWritten) *lpNumCharsWritten = reply->written;
+        }
     }
-    return read_console_input(hConsoleInput, pirBuffer, cInRecords, lpcRead, FALSE);
+    SERVER_END_REQ;
+    return ret;
 }
 
 
-/***********************************************************************
- *            GetNumberOfConsoleInputEvents   (KERNEL32.@)
+/******************************************************************************
+ * SetConsoleTitleW [KERNEL32.@]  Sets title bar string for console
+ *
+ * PARAMS
+ *    title [I] Address of new title
+ *
+ * RETURNS
+ *    Success: TRUE
+ *    Failure: FALSE
  */
-BOOL WINAPI GetNumberOfConsoleInputEvents(HANDLE hcon, LPDWORD nrofevents)
+BOOL WINAPI SetConsoleTitleW(LPCWSTR title)
 {
-    return read_console_input(hcon, NULL, 0, nrofevents, FALSE);
+    BOOL ret;
+
+    SERVER_START_REQ( set_console_input_info )
+    {
+        req->handle = 0;
+        req->mask = SET_CONSOLE_INPUT_INFO_TITLE;
+        wine_server_add_data( req, title, strlenW(title) * sizeof(WCHAR) );
+        ret = !wine_server_call_err( req );
+    }
+    SERVER_END_REQ;
+    return ret;
 }
 
+
 /***********************************************************************
  *            GetNumberOfConsoleMouseButtons   (KERNEL32.@)
  */
@@ -470,70 +459,6 @@
 }
 
 /******************************************************************************
- * WriteConsoleInputA [KERNEL32.@]  Write data to a console input buffer
- *
- */
-BOOL WINAPI WriteConsoleInputA(HANDLE handle, INPUT_RECORD *buffer,
-			       DWORD count, LPDWORD written)
-{
-    BOOL ret = TRUE;
-
-    if (written) *written = 0;
-    /* FIXME should zero out the non ASCII part for key events */
-
-    while (count && ret)
-    {
-        DWORD len = min(count, REQUEST_MAX_VAR_SIZE/sizeof(INPUT_RECORD));
-        SERVER_START_VAR_REQ(write_console_input, len * sizeof(INPUT_RECORD))
-	{
-	    req->handle = handle;
-	    memcpy(server_data_ptr(req), buffer, len * sizeof(INPUT_RECORD));
-	    if ((ret = !SERVER_CALL_ERR()))
-	    {
-		if (written) *written += req->written;
-		count -= len;
-		buffer += len;
-	    }
-	}
-        SERVER_END_VAR_REQ;
-    }
-    return ret;
-}
-
-/******************************************************************************
- * WriteConsoleInputW [KERNEL32.@]  Write data to a console input buffer
- *
- */
-BOOL WINAPI WriteConsoleInputW(HANDLE handle, INPUT_RECORD *buffer,
-			       DWORD count, LPDWORD written)
-{
-    BOOL ret = TRUE;
-    
-    TRACE("(%d,%p,%ld,%p)\n", handle, buffer, count, written);
-    
-    if (written) *written = 0;
-    while (count && ret)
-    {
-        DWORD len = min(count, REQUEST_MAX_VAR_SIZE/sizeof(INPUT_RECORD));
-        SERVER_START_VAR_REQ(write_console_input, len * sizeof(INPUT_RECORD))
-        {
-            req->handle = handle;
-            memcpy(server_data_ptr(req), buffer, len * sizeof(INPUT_RECORD));
-            if ((ret = !SERVER_CALL_ERR()))
-            {
-                if (written) *written += req->written;
-                count -= len;
-                buffer += len;
-            }
-        }
-        SERVER_END_VAR_REQ;
-    }
-
-    return ret;
-}
-
-
-/******************************************************************************
  *  SetConsoleInputExeNameW	 [KERNEL32.@]
  * 
  * BUGS
@@ -661,8 +586,6 @@
 BOOL WINAPI GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
 				     DWORD dwProcessGroupID)
 {
-    BOOL	dbgOn = FALSE;
-
     if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
     {
 	ERR("invalid event %ld for PGID %ld\n", dwCtrlEvent, dwProcessGroupID);
@@ -681,45 +604,27 @@
 	if (dwCtrlEvent == CTRL_C_EVENT && console_ignore_ctrl_c)
 	    return TRUE;
 
-	/* if the program is debugged, then generate an exception to the debugger first */
-	SERVER_START_REQ( get_process_info )
-	{
-	    req->handle = GetCurrentProcess();
-	    if (!SERVER_CALL_ERR()) dbgOn = req->debugged;
-	}
-	SERVER_END_REQ;
-
-	if (dbgOn && (dwCtrlEvent == CTRL_C_EVENT || dwCtrlEvent == CTRL_BREAK_EVENT))
-	{
-	    /* the debugger is running... so try to pass the exception to it
-	     * if it continues, there's nothing more to do
-	     * otherwise, we need to send the ctrl-event to the handlers
-	     */
-	    BOOL	seen;
-	    __TRY
-	    {
-		seen = TRUE;
-		RaiseException((dwCtrlEvent == CTRL_C_EVENT) ? DBG_CONTROL_C : DBG_CONTROL_BREAK, 0, 0, NULL);
-	    }
-	    __EXCEPT(CONSOLE_CtrlEventHandler)
-	    {
-		/* the debugger didn't continue... so, pass to ctrl handlers */
-		seen = FALSE;
-	    }
-	    __ENDTRY;
-	    if (seen) return TRUE;
-	}
-
-	/* proceed with installed handlers */
-	for (i = 0; i < sizeof(handlers)/sizeof(handlers[0]); i++)
-	{
-	    if (handlers[i] && (handlers[i])(dwCtrlEvent)) break;
-	}
-	
-	return TRUE;
+        /* try to pass the exception to the debugger
+         * if it continues, there's nothing more to do
+         * otherwise, we need to send the ctrl-event to the handlers
+         */
+        __TRY
+        {
+            RaiseException( (dwCtrlEvent == CTRL_C_EVENT) ? DBG_CONTROL_C : DBG_CONTROL_BREAK,
+                            0, 0, NULL);
+        }
+        __EXCEPT(CONSOLE_CtrlEventHandler)
+        {
+            /* the debugger didn't continue... so, pass to ctrl handlers */
+            for (i = 0; i < sizeof(handlers)/sizeof(handlers[0]); i++)
+            {
+                if (handlers[i] && (handlers[i])(dwCtrlEvent)) break;
+            }
+        }
+        __ENDTRY;
+        return TRUE;
     }
-    FIXME("event %ld to external PGID %ld - not implemented yet\n", 
-	  dwCtrlEvent, dwProcessGroupID);
+    FIXME("event %ld to external PGID %ld - not implemented yet\n", dwCtrlEvent, dwProcessGroupID);
     return FALSE;
 }
 
@@ -762,8 +667,7 @@
 	req->access    = dwDesiredAccess;
 	req->share     = dwShareMode;
 	req->inherit   = (sa && sa->bInheritHandle);
-	if (!SERVER_CALL_ERR())
-	    ret = req->handle_out;
+	if (!wine_server_call_err( req )) ret = reply->handle_out;
     }
     SERVER_END_REQ;
     
@@ -780,21 +684,21 @@
 
     SERVER_START_REQ(get_console_output_info)
     {
-	req->handle = (handle_t)hConsoleOutput;
-	if ((ret = !SERVER_CALL_ERR()))
-	{
-	    csbi->dwSize.X              = req->width;
-	    csbi->dwSize.Y              = req->height;
-	    csbi->dwCursorPosition.X    = req->cursor_x;
-	    csbi->dwCursorPosition.Y    = req->cursor_y;
-	    csbi->wAttributes           = req->attr;
-	    csbi->srWindow.Left	        = req->win_left;
-	    csbi->srWindow.Right        = req->win_right;
-	    csbi->srWindow.Top	        = req->win_top;
-	    csbi->srWindow.Bottom       = req->win_bottom;
-	    csbi->dwMaximumWindowSize.X = req->max_width;
-	    csbi->dwMaximumWindowSize.Y = req->max_height;
-	}
+        req->handle = hConsoleOutput;
+        if ((ret = !wine_server_call_err( req )))
+        {
+            csbi->dwSize.X              = reply->width;
+            csbi->dwSize.Y              = reply->height;
+            csbi->dwCursorPosition.X    = reply->cursor_x;
+            csbi->dwCursorPosition.Y    = reply->cursor_y;
+            csbi->wAttributes           = reply->attr;
+            csbi->srWindow.Left         = reply->win_left;
+            csbi->srWindow.Right        = reply->win_right;
+            csbi->srWindow.Top          = reply->win_top;
+            csbi->srWindow.Bottom       = reply->win_bottom;
+            csbi->dwMaximumWindowSize.X = reply->max_width;
+            csbi->dwMaximumWindowSize.Y = reply->max_height;
+        }
     }
     SERVER_END_REQ;
 
@@ -811,117 +715,23 @@
  */
 BOOL WINAPI SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput)
 {
-    BOOL	ret;
-    
+    BOOL ret;
+
     TRACE("(%x)\n", hConsoleOutput);
-    
-    SERVER_START_VAR_REQ(set_console_input_info, 0)
+
+    SERVER_START_REQ( set_console_input_info )
     {
-	req->handle    = 0;
-	req->mask      = SET_CONSOLE_INPUT_INFO_ACTIVE_SB;
-	req->active_sb = hConsoleOutput;
-	
-	ret = !SERVER_CALL_ERR();
+        req->handle    = 0;
+        req->mask      = SET_CONSOLE_INPUT_INFO_ACTIVE_SB;
+        req->active_sb = hConsoleOutput;
+        ret = !wine_server_call_err( req );
     }
-    SERVER_END_VAR_REQ;
-    
+    SERVER_END_REQ;
     return ret;
 }
 
 
 /***********************************************************************
- *            GetLargestConsoleWindowSize   (KERNEL32.@)
- *
- * NOTE
- *	This should return a COORD, but calling convention for returning
- *      structures is different between Windows and gcc on i386.
- *
- * VERSION: [i386]
- */
-#ifdef __i386__
-#undef GetLargestConsoleWindowSize
-DWORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
-{
-    COORD c;
-    c.X = 80;
-    c.Y = 24;
-    return *(DWORD *)&c;
-}
-#endif /* defined(__i386__) */
-
-
-/***********************************************************************
- *            GetLargestConsoleWindowSize   (KERNEL32.@)
- *
- * NOTE
- *	This should return a COORD, but calling convention for returning
- *      structures is different between Windows and gcc on i386.
- *
- * VERSION: [!i386]
- */
-#ifndef __i386__
-COORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
-{
-    COORD c;
-    c.X = 80;
-    c.Y = 24;
-    return c;
-}
-#endif /* defined(__i386__) */
-
-
-/******************************************************************************
- * GetConsoleCP [KERNEL32.@]  Returns the OEM code page for the console
- *
- * RETURNS
- *    Code page code
- */
-UINT WINAPI GetConsoleCP(VOID)
-{
-    return GetACP();
-}
-
-
-/******************************************************************************
- *  SetConsoleCP	 [KERNEL32.@]
- * 
- * BUGS
- *   Unimplemented
- */
-BOOL WINAPI SetConsoleCP(UINT cp)
-{
-    FIXME("(%d): stub\n", cp);
-    
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
-}
-
-/***********************************************************************
- *            GetConsoleOutputCP   (KERNEL32.@)
- */
-UINT WINAPI GetConsoleOutputCP(VOID)
-{
-    return GetConsoleCP();
-}
-
-/******************************************************************************
- * SetConsoleOutputCP [KERNEL32.@]  Set the output codepage used by the console
- *
- * PARAMS
- *    cp [I] code page to set
- *
- * RETURNS
- *    Success: TRUE
- *    Failure: FALSE
- */
-BOOL WINAPI SetConsoleOutputCP(UINT cp)
-{
-    FIXME("stub\n");
-    return TRUE;
-}
-
-
-/***********************************************************************
  *            GetConsoleMode   (KERNEL32.@)
  */
 BOOL WINAPI GetConsoleMode(HANDLE hcon, LPDWORD mode)
@@ -931,8 +741,8 @@
     SERVER_START_REQ(get_console_mode)
     {
 	req->handle = hcon;
-	ret = !SERVER_CALL_ERR();
-	if (ret && mode) *mode = req->mode;
+	ret = !wine_server_call_err( req );
+	if (ret && mode) *mode = reply->mode;
     }
     SERVER_END_REQ;
     return ret;
@@ -960,7 +770,7 @@
     {
 	req->handle = hcon;
 	req->mode = mode;
-	ret = !SERVER_CALL_ERR();
+	ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     /* FIXME: when resetting a console input to editline mode, I think we should
@@ -970,142 +780,30 @@
 }
 
 
-/***********************************************************************
- *            SetConsoleTitleA   (KERNEL32.@)
- *
- * Sets the console title.
- *
- * We do not necessarily need to create a complex console for that,
- * but should remember the title and set it on creation of the latter.
- * (not fixed at this time).
- */
-BOOL WINAPI SetConsoleTitleA(LPCSTR title)
-{
-    LPWSTR	titleW = NULL;
-    BOOL	ret;
-    DWORD	len;
-    
-    len = MultiByteToWideChar(CP_ACP, 0, title, -1, NULL, 0);
-    titleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-    if (!titleW) return FALSE;
-    
-    MultiByteToWideChar(CP_ACP, 0, title, -1, titleW, len);
-    ret = SetConsoleTitleW(titleW);
-    
-    HeapFree(GetProcessHeap(), 0, titleW);
-    return ret;
-}
-
-
-/******************************************************************************
- * SetConsoleTitleW [KERNEL32.@]  Sets title bar string for console
- *
- * PARAMS
- *    title [I] Address of new title
- *
- * NOTES
- *    This should not be calling the A version
- *
- * RETURNS
- *    Success: TRUE
- *    Failure: FALSE
- */
-BOOL WINAPI SetConsoleTitleW(LPCWSTR title)
-{
-    size_t	len = strlenW(title) * sizeof(WCHAR);
-    BOOL 	ret;
-
-    len = min(len, REQUEST_MAX_VAR_SIZE);
-    SERVER_START_VAR_REQ(set_console_input_info, len)
-    {
-	req->handle = 0;
-        req->mask = SET_CONSOLE_INPUT_INFO_TITLE;
-        memcpy(server_data_ptr(req), title, len);
-        ret = !SERVER_CALL_ERR();
-    }
-    SERVER_END_VAR_REQ;
-
-    return ret;
-}
-
-/***********************************************************************
- *            GetConsoleTitleA   (KERNEL32.@)
- */
-DWORD WINAPI GetConsoleTitleA(LPSTR title, DWORD size)
-{
-    WCHAR*	ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
-    DWORD	ret;
-
-    if (!ptr) return 0;
-    
-    ret = GetConsoleTitleW(ptr, size);
-    if (ret) WideCharToMultiByte(CP_ACP, 0, ptr, ret + 1, title, size, NULL, NULL);
-
-    return ret;
-}
-
-
-/******************************************************************************
- * GetConsoleTitleW [KERNEL32.@]  Retrieves title string for console
- *
- * PARAMS
- *    title [O] Address of buffer for title
- *    size  [I] Size of buffer
- *
- * RETURNS
- *    Success: Length of string copied
- *    Failure: 0
- */
-DWORD WINAPI GetConsoleTitleW(LPWSTR title, DWORD size)
-{
-    DWORD ret = 0;
-
-    SERVER_START_VAR_REQ(get_console_input_info, REQUEST_MAX_VAR_SIZE)
-    {
-	req->handle = 0;
-        if (!SERVER_CALL_ERR())
-        {
-            ret = server_data_size(req) / sizeof(WCHAR);
-            size = min(size - 1, ret);
-            memcpy(title, server_data_ptr(req), size * sizeof(WCHAR));
-            title[size] = 0;
-        }
-    }
-    SERVER_END_VAR_REQ;
-
-    return ret;
-}
-
 /******************************************************************
  *		write_char
  *
  * WriteConsoleOutput helper: hides server call semantics
  */
-static	int	write_char(HANDLE hCon, LPCVOID lpBuffer, int nc, COORD* pos)
+static int write_char(HANDLE hCon, LPCWSTR lpBuffer, int nc, COORD* pos)
 {
-    BOOL	ret;
-    int		written = -1;
+    int written = -1;
 
     if (!nc) return 0;
 
-    assert(nc * sizeof(WCHAR) <= REQUEST_MAX_VAR_SIZE);
-
-    SERVER_START_VAR_REQ(write_console_output, nc * sizeof(WCHAR))
+    SERVER_START_REQ( write_console_output )
     {
-	req->handle = hCon;
-	req->x      = pos->X;
-	req->y      = pos->Y;
-	req->mode   = WRITE_CONSOLE_MODE_TEXTSTDATTR;
-	memcpy(server_data_ptr(req), lpBuffer, nc * sizeof(WCHAR));
-	if ((ret = !SERVER_CALL_ERR()))
-	{
-	    written = req->written;
-	}
+        req->handle = hCon;
+        req->x      = pos->X;
+        req->y      = pos->Y;
+        req->mode   = CHAR_INFO_MODE_TEXTSTDATTR;
+        req->wrap   = FALSE;
+        wine_server_add_data( req, lpBuffer, nc * sizeof(WCHAR) );
+        if (!wine_server_call_err( req )) written = reply->written;
     }
-    SERVER_END_VAR_REQ;
-    
-    if (written > 0) pos->X += written;
+    SERVER_END_REQ;
 
+    if (written > 0) pos->X += written;
     return written;
 }
 
@@ -1292,85 +990,6 @@
     return ret;
 }
 
-/***********************************************************************
- *            WriteConsoleOutputA   (KERNEL32.@)
- */
-BOOL WINAPI WriteConsoleOutputA(HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD dwBufferSize,
-				COORD dwBufferCoord, LPSMALL_RECT lpWriteRegion)
-{
-    CHAR_INFO	*ciw;
-    int		i;
-    BOOL	ret;
-    
-    ciw = HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR_INFO) * dwBufferSize.X * dwBufferSize.Y);
-    if (!ciw) return FALSE;
-    
-    for (i = 0; i < dwBufferSize.X * dwBufferSize.Y; i++)
-    {
-	ciw[i].Attributes = lpBuffer[i].Attributes;
-	MultiByteToWideChar(CP_ACP, 0, &lpBuffer[i].Char.AsciiChar, 1, &ciw[i].Char.UnicodeChar, 1);
-    }
-    ret = WriteConsoleOutputW(hConsoleOutput, ciw, dwBufferSize, dwBufferCoord, lpWriteRegion);
-    HeapFree(GetProcessHeap(), 0, ciw);
-    
-    return ret;
-}
-
-/***********************************************************************
- *            WriteConsoleOutputW   (KERNEL32.@)
- */
-BOOL WINAPI WriteConsoleOutputW(HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD dwBufferSize,
-				COORD dwBufferCoord, LPSMALL_RECT lpWriteRegion)
-{
-    short int	w, h;
-    unsigned	y;
-    DWORD	ret = TRUE;
-    DWORD	actual_width;
-    
-    TRACE("(%x,%p,(%d,%d),(%d,%d),(%d,%dx%d,%d)\n", 
-	  hConsoleOutput, lpBuffer, dwBufferSize.X, dwBufferSize.Y, dwBufferCoord.X, dwBufferCoord.Y,
-	  lpWriteRegion->Left, lpWriteRegion->Top, lpWriteRegion->Right, lpWriteRegion->Bottom);
-    
-    w = min(lpWriteRegion->Right - lpWriteRegion->Left + 1, dwBufferSize.X - dwBufferCoord.X);
-    h = min(lpWriteRegion->Bottom - lpWriteRegion->Top + 1, dwBufferSize.Y - dwBufferCoord.Y);
-    
-    if (w <= 0 || h <= 0)
-    {
-	memset(lpWriteRegion, 0, sizeof(SMALL_RECT));
-	return FALSE;
-    }
-    
-    /* this isn't supported for now, even if hConsoleOutput's row size fits in a single
-     * server's request... it would request cropping on client side
-     */
-    if (w * sizeof(CHAR_INFO) > REQUEST_MAX_VAR_SIZE)
-    {
-	FIXME("This isn't supported yet, too wide CHAR_INFO array (%d)\n", w);
-	memset(lpWriteRegion, 0, sizeof(SMALL_RECT));
-	return FALSE;
-    }
-
-    actual_width = w;
-    for (y = 0; ret && y < h; y++)
-    {
-	SERVER_START_VAR_REQ(write_console_output, w * sizeof(CHAR_INFO))
-	{
-	    req->handle = hConsoleOutput;
-	    req->mode = WRITE_CONSOLE_MODE_TEXTATTR;
-	    req->x = lpWriteRegion->Left;
-	    req->y = lpWriteRegion->Top + y;
-	    memcpy(server_data_ptr(req), &lpBuffer[(y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X], w * sizeof(CHAR_INFO));
-	    if ((ret = !SERVER_CALL()))
-		actual_width = min(actual_width, req->written);
-	}
-	SERVER_END_VAR_REQ;
-    }
-    lpWriteRegion->Bottom = lpWriteRegion->Top + h;
-    lpWriteRegion->Right = lpWriteRegion->Left + actual_width;
-
-    return ret;
-}
-
 /******************************************************************************
  * SetConsoleCursorPosition [KERNEL32.@]
  * Sets the cursor position in console
@@ -1396,7 +1015,7 @@
         req->cursor_x       = pos.X;
         req->cursor_y       = pos.Y;
         req->mask           = SET_CONSOLE_OUTPUT_INFO_CURSOR_POS;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
 
@@ -1453,11 +1072,11 @@
     SERVER_START_REQ(get_console_output_info)
     {
         req->handle = hcon;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
         if (ret && cinfo)
         {
-            cinfo->dwSize = req->cursor_size;
-            cinfo->bVisible = req->cursor_visible;
+            cinfo->dwSize = reply->cursor_size;
+            cinfo->bVisible = reply->cursor_visible;
         }
     }
     SERVER_END_REQ;
@@ -1485,7 +1104,7 @@
         req->cursor_size    = cinfo->dwSize;
         req->cursor_visible = cinfo->bVisible;
         req->mask           = SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -1526,7 +1145,7 @@
 	req->win_right      = p.Right;
 	req->win_bottom     = p.Bottom;
         req->mask           = SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
 
@@ -1550,10 +1169,10 @@
 
     SERVER_START_REQ(set_console_output_info)
     {
-        req->handle         = hConsoleOutput;
-        req->attr	    = wAttr;
-        req->mask           = SET_CONSOLE_OUTPUT_INFO_ATTR;
-        ret = !SERVER_CALL_ERR();
+        req->handle = hConsoleOutput;
+        req->attr   = wAttr;
+        req->mask   = SET_CONSOLE_OUTPUT_INFO_ATTR;
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -1575,23 +1194,13 @@
 {
     BOOL ret;
 
-    /* FIXME: most code relies on the fact we can transfer a complete row at a time...
-     * so check if it's possible...
-     */
-    if (dwSize.X > REQUEST_MAX_VAR_SIZE / 4)
-    {
-	FIXME("too wide width not supported\n");
-	SetLastError(STATUS_INVALID_PARAMETER);
-	return FALSE;
-    }
-
     SERVER_START_REQ(set_console_output_info)
     {
-        req->handle	= hConsoleOutput;
-        req->width	= dwSize.X;
-        req->height	= dwSize.Y;
-	req->mask       = SET_CONSOLE_OUTPUT_INFO_SIZE;
-        ret = !SERVER_CALL_ERR();
+        req->handle = hConsoleOutput;
+        req->width  = dwSize.X;
+        req->height = dwSize.Y;
+        req->mask   = SET_CONSOLE_OUTPUT_INFO_SIZE;
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -1599,135 +1208,6 @@
 
 
 /******************************************************************************
- * FillConsoleOutputCharacterA [KERNEL32.@]
- *
- * PARAMS
- *    hConsoleOutput    [I] Handle to screen buffer
- *    cCharacter        [I] Character to write
- *    nLength           [I] Number of cells to write to
- *    dwCoord           [I] Coords of first cell
- *    lpNumCharsWritten [O] Pointer to number of cells written
- *
- * RETURNS
- *    Success: TRUE
- *    Failure: FALSE
- */
-BOOL WINAPI FillConsoleOutputCharacterA(HANDLE hConsoleOutput, BYTE cCharacter,
-					DWORD nLength, COORD dwCoord, LPDWORD lpNumCharsWritten)
-{
-    WCHAR	wch;
-
-    MultiByteToWideChar(CP_ACP, 0, &cCharacter, 1, &wch, 1);
-
-    return FillConsoleOutputCharacterW(hConsoleOutput, wch, nLength, dwCoord, lpNumCharsWritten);
-}
-
-
-/******************************************************************************
- * FillConsoleOutputCharacterW [KERNEL32.@]  Writes characters to console
- *
- * PARAMS
- *    hConsoleOutput    [I] Handle to screen buffer
- *    cCharacter        [I] Character to write
- *    nLength           [I] Number of cells to write to
- *    dwCoord           [I] Coords of first cell
- *    lpNumCharsWritten [O] Pointer to number of cells written
- *
- * RETURNS
- *    Success: TRUE
- *    Failure: FALSE
- */
-BOOL WINAPI FillConsoleOutputCharacterW(HANDLE hConsoleOutput, WCHAR cCharacter,
-					DWORD nLength, COORD dwCoord, LPDWORD lpNumCharsWritten)
-{
-    CONSOLE_SCREEN_BUFFER_INFO	csbi;
-    int				written;
-    DWORD			initLen = nLength;
-
-    TRACE("(%d,%s,%ld,(%dx%d),%p)\n", 
-	  hConsoleOutput, debugstr_wn(&cCharacter, 1), nLength, 
-	  dwCoord.X, dwCoord.Y, lpNumCharsWritten);
-
-    if (!GetConsoleScreenBufferInfo(hConsoleOutput, &csbi))
-	return FALSE;
-
-    while (nLength)
-    {
-	SERVER_START_VAR_REQ(write_console_output, 
-			     min(csbi.dwSize.X - dwCoord.X, nLength) * sizeof(WCHAR))
-	{
-	    req->handle = hConsoleOutput;
-	    req->x      = dwCoord.X;
-	    req->y      = dwCoord.Y;
-	    req->mode   = WRITE_CONSOLE_MODE_TEXTSTDATTR|WRITE_CONSOLE_MODE_UNIFORM;
-	    memcpy(server_data_ptr(req), &cCharacter, sizeof(WCHAR));
-	    written = SERVER_CALL_ERR() ? 0 : req->written;
-	}
-	SERVER_END_VAR_REQ;
-
-	if (!written) break;
-	nLength -= written;
-	dwCoord.X = 0;
-	if (++dwCoord.Y == csbi.dwSize.Y) break;
-    }
-    
-    if (lpNumCharsWritten) *lpNumCharsWritten = initLen - nLength;
-    return initLen != nLength;
-}
-
-
-/******************************************************************************
- * FillConsoleOutputAttribute [KERNEL32.@]  Sets attributes for console
- *
- * PARAMS
- *    hConsoleOutput    [I] Handle to screen buffer
- *    wAttribute        [I] Color attribute to write
- *    nLength           [I] Number of cells to write to
- *    dwCoord           [I] Coords of first cell
- *    lpNumAttrsWritten [O] Pointer to number of cells written
- *
- * RETURNS
- *    Success: TRUE
- *    Failure: FALSE
- */
-BOOL WINAPI FillConsoleOutputAttribute(HANDLE hConsoleOutput, WORD wAttribute, 
-				       DWORD nLength, COORD dwCoord, LPDWORD lpNumAttrsWritten)
-{
-    CONSOLE_SCREEN_BUFFER_INFO	csbi;
-    int				written;
-    DWORD			initLen = nLength;
-    
-    TRACE("(%d,%d,%ld,(%dx%d),%p)\n", 
-	  hConsoleOutput, wAttribute, nLength, dwCoord.X, dwCoord.Y, lpNumAttrsWritten);
-    
-    if (!GetConsoleScreenBufferInfo(hConsoleOutput, &csbi))
-	return FALSE;
-
-    while (nLength)
-    {
-	SERVER_START_VAR_REQ(write_console_output, 
-			     min(csbi.dwSize.X - dwCoord.X, nLength) * sizeof(WCHAR))
-	{
-	    req->handle = hConsoleOutput;
-	    req->x      = dwCoord.X;
-	    req->y      = dwCoord.Y;
-	    req->mode   = WRITE_CONSOLE_MODE_ATTR|WRITE_CONSOLE_MODE_UNIFORM;
-	    memcpy(server_data_ptr(req), &wAttribute, sizeof(WORD));
-	    written = SERVER_CALL_ERR() ? 0 : req->written;
-	}
-	SERVER_END_VAR_REQ;
-
-	if (!written) break;
-	nLength -= written;
-	dwCoord.X = 0;
-	if (++dwCoord.Y == csbi.dwSize.Y) break;
-    }
-
-    if (lpNumAttrsWritten) *lpNumAttrsWritten = initLen - nLength;
-    return initLen != nLength;
-}
-
-/******************************************************************************
  * ScrollConsoleScreenBufferA [KERNEL32.@]
  * 
  */
@@ -1752,16 +1232,19 @@
  */
 static void fill_line_uniform(HANDLE hConsoleOutput, int i, int j, int len, LPCHAR_INFO lpFill)
 {
-    SERVER_START_VAR_REQ(write_console_output, len * sizeof(CHAR_INFO))
+    SERVER_START_REQ( fill_console_output )
     {
-	req->handle = hConsoleOutput;
-	req->x      = i;
-	req->y      = j;
-	req->mode   = WRITE_CONSOLE_MODE_TEXTATTR|WRITE_CONSOLE_MODE_UNIFORM;
-	memcpy(server_data_ptr(req), lpFill, sizeof(CHAR_INFO));
-	SERVER_CALL_ERR();
+        req->handle    = hConsoleOutput;
+        req->mode      = CHAR_INFO_MODE_TEXTATTR;
+        req->x         = i;
+        req->y         = j;
+        req->count     = len;
+        req->wrap      = FALSE;
+        req->data.ch   = lpFill->Char.UnicodeChar;
+        req->data.attr = lpFill->Attributes;
+        wine_server_call_err( req );
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
 }
 
 /******************************************************************************
@@ -1836,7 +1319,7 @@
 	req->y_dst = dst.Top;
 	req->w = dst.Right - dst.Left + 1;
 	req->h = dst.Bottom - dst.Top + 1;
-	ret = !SERVER_CALL_ERR();
+	ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
 
@@ -1874,350 +1357,6 @@
     return TRUE;
 }
 
-/******************************************************************************
- * ReadConsoleOutputCharacterA [KERNEL32.@]
- * 
- */
-BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpstr, DWORD toRead, 
-					COORD coord, LPDWORD lpdword)
-{
-    DWORD	read;
-    LPWSTR	wptr = HeapAlloc(GetProcessHeap(), 0, toRead * sizeof(WCHAR));
-    BOOL	ret;
-
-    if (lpdword) *lpdword = 0;
-    if (!wptr) return FALSE;
-
-    ret = ReadConsoleOutputCharacterW(hConsoleOutput, wptr, toRead, coord, &read);
-
-    read = WideCharToMultiByte(CP_ACP, 0, wptr, read, lpstr, toRead, NULL, NULL);
-    if (lpdword) *lpdword = read;
-
-    HeapFree(GetProcessHeap(), 0, wptr);
-
-    return ret;
-}
-
-/******************************************************************************
- * ReadConsoleOutputCharacterW [KERNEL32.@]
- * 
- */
-BOOL WINAPI ReadConsoleOutputCharacterW(HANDLE hConsoleOutput, LPWSTR lpstr, DWORD toRead, 
-					COORD coord, LPDWORD lpdword)
-{
-    DWORD	read = 0;
-    DWORD	ret = TRUE;
-    int		i;
-    DWORD*	ptr;
-
-    TRACE("(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput, lpstr, toRead, coord.X, coord.Y, lpdword);
-
-    while (ret && (read < toRead))
-    {
-	SERVER_START_VAR_REQ(read_console_output, REQUEST_MAX_VAR_SIZE)
-	{
-	    req->handle       = (handle_t)hConsoleOutput;
-	    req->x            = coord.X;
-	    req->y            = coord.Y;
-	    req->w            = REQUEST_MAX_VAR_SIZE / 4;
-	    req->h            = 1;
-	    if ((ret = !SERVER_CALL_ERR()))
-	    {
-		ptr = server_data_ptr(req);
-		
-		for (i = 0; i < req->eff_w && read < toRead; i++)
-		{
-		    lpstr[read++] = LOWORD(ptr[i]);
-		}
-		coord.X = 0;	coord.Y++;
-	    }
-	}
-	SERVER_END_VAR_REQ;
-    }
-    if (lpdword) *lpdword = read;
-    
-    TRACE("=> %lu %s\n", read, debugstr_wn(lpstr, read));
-    
-    return ret;
-}
-
-
-/******************************************************************************
- *  ReadConsoleOutputA [KERNEL32.@]
- * 
- */
-BOOL WINAPI ReadConsoleOutputA(HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD dwBufferSize,
-			       COORD dwBufferCoord, LPSMALL_RECT lpReadRegion)
-{
-    BOOL	ret;
-    int		x, y;
-    int		pos;
-    
-    ret = ReadConsoleOutputW(hConsoleOutput, lpBuffer, dwBufferSize, dwBufferCoord, lpReadRegion);
-    if (!ret) return FALSE;
-    for (y = 0; y <= lpReadRegion->Bottom - lpReadRegion->Top; y++)
-    {
-	for (x = 0; x <= lpReadRegion->Right - lpReadRegion->Left; x++)
-	{
-	    pos = (dwBufferCoord.Y + y) * dwBufferSize.X + dwBufferCoord.X + x;
-	    WideCharToMultiByte(CP_ACP, 0, &lpBuffer[pos].Char.UnicodeChar, 1, 
-				&lpBuffer[pos].Char.AsciiChar, 1, NULL, NULL);
-	}
-    }
-    return TRUE;
-}
-
-/******************************************************************************
- *  ReadConsoleOutputW [KERNEL32.@]
- * 
- */
-BOOL WINAPI ReadConsoleOutputW(HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD dwBufferSize,
-			       COORD dwBufferCoord, LPSMALL_RECT lpReadRegion)
-{
-    int		w, h;
-    int		actual_width;
-    int		y;
-    BOOL	ret = TRUE;
-    
-    w = min(lpReadRegion->Right - lpReadRegion->Left + 1, dwBufferSize.X - dwBufferCoord.X);
-    h = min(lpReadRegion->Bottom - lpReadRegion->Top + 1, dwBufferSize.Y - dwBufferCoord.Y);
-    
-    if (w <= 0 || h <= 0) goto got_err;
-
-    /* this isn't supported for now, even if hConsoleOutput's row size fits in a single
-     * server's request... it would request cropping on client side
-     */
-    if (w * sizeof(CHAR_INFO) > REQUEST_MAX_VAR_SIZE)
-    {
-	FIXME("This isn't supported yet, too wide CHAR_INFO array (%d)\n", w);
-	goto got_err;
-    }
-
-    actual_width = w;
-    for (y = 0; ret && y < h; y++)
-    {
-	SERVER_START_VAR_REQ(read_console_output, w * sizeof(CHAR_INFO))
-	{
-	    req->handle = hConsoleOutput;
-	    req->x = lpReadRegion->Left;
-	    req->y = lpReadRegion->Top;
-	    req->w = w;
-	    req->h = 1;
-	    if ((ret = !SERVER_CALL()))
-	    {
-		actual_width = min(actual_width, req->eff_w);
-		memcpy(&lpBuffer[(y + dwBufferCoord.Y) * dwBufferSize.X + dwBufferCoord.X], 
-		       server_data_ptr(req), 
-		       req->eff_w * sizeof(CHAR_INFO));
-	    }
-	}
-	SERVER_END_VAR_REQ;
-    }
-    if (!ret) goto got_err;
-    
-    lpReadRegion->Bottom = lpReadRegion->Top + y;
-    lpReadRegion->Right = lpReadRegion->Left + actual_width;
-    
-    return ret;
- got_err:
-    memset(lpReadRegion, 0, sizeof(SMALL_RECT));
-    return FALSE;
-}
-
-/******************************************************************************
- *  ReadConsoleOutputAttribute [KERNEL32.@]
- * 
- */
-BOOL WINAPI ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD nLength,
-				       COORD coord, LPDWORD lpNumberOfAttrsRead)
-{
-    DWORD	read = 0;
-    DWORD	ret = TRUE;
-    int		i;
-    DWORD*	ptr;
-    
-    TRACE("(%d,%p,%ld,%dx%d,%p)\n", 
-	  hConsoleOutput, lpAttribute, nLength, coord.X, coord.Y, lpNumberOfAttrsRead);
-    
-    while (ret && (read < nLength))
-    {
-	SERVER_START_VAR_REQ(read_console_output, REQUEST_MAX_VAR_SIZE)
-	{
-	    req->handle       = (handle_t)hConsoleOutput;
-	    req->x            = coord.X;
-	    req->y            = coord.Y;
-	    req->w            = REQUEST_MAX_VAR_SIZE / 4;
-	    req->h            = 1;
-	    if (SERVER_CALL_ERR()) 
-	    {
-		ret = FALSE;
-	    }
-	    else
-	    {
-		ptr = server_data_ptr(req);
-		
-		for (i = 0; i < req->eff_w && read < nLength; i++)
-		{
-		    lpAttribute[read++] = HIWORD(ptr[i]);
-		}
-		coord.X = 0;	coord.Y++;
-	    }
-	}
-	SERVER_END_VAR_REQ;
-    }
-    if (lpNumberOfAttrsRead) *lpNumberOfAttrsRead = read;
-    
-    return ret;
-}
-
-/******************************************************************************
- * WriteConsoleOutputAttribute [KERNEL32.@]  Sets attributes for some cells in
- * 					     the console screen buffer
- *
- * PARAMS
- *    hConsoleOutput    [I] Handle to screen buffer
- *    lpAttribute       [I] Pointer to buffer with write attributes
- *    nLength           [I] Number of cells to write to
- *    dwCoord           [I] Coords of first cell
- *    lpNumAttrsWritten [O] Pointer to number of cells written
- *
- * RETURNS
- *    Success: TRUE
- *    Failure: FALSE
- * 
- */
-BOOL WINAPI WriteConsoleOutputAttribute(HANDLE hConsoleOutput, CONST WORD *lpAttribute, 
-					DWORD nLength, COORD dwCoord, LPDWORD lpNumAttrsWritten)
-{
-    int		written = 0;
-    int		len;
-    BOOL	ret = TRUE;
-    DWORD	init_len = nLength;
-    CONSOLE_SCREEN_BUFFER_INFO csbi;
-    
-    TRACE("(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput,
-          lpAttribute,nLength,dwCoord.X,dwCoord.Y,lpNumAttrsWritten);
-    
-    if (!GetConsoleScreenBufferInfo(hConsoleOutput, & csbi))
-	return FALSE;
-    
-    while (ret && nLength)
-    {	
-	len = min(nLength * sizeof(WORD), REQUEST_MAX_VAR_SIZE);
-	SERVER_START_VAR_REQ(write_console_output, len)
-	{
-	    req->handle = hConsoleOutput;
-	    req->x      = dwCoord.X;
-	    req->y      = dwCoord.Y;
-	    req->mode   = WRITE_CONSOLE_MODE_ATTR;
-	    memcpy(server_data_ptr(req), &lpAttribute[written],  len);
-	    written = (SERVER_CALL_ERR()) ? 0 : req->written;
-	}
-	SERVER_END_VAR_REQ;
-
-	if (!written) break;
-	nLength -= written;
-	dwCoord.X = 0;
-	if (++dwCoord.Y == csbi.dwSize.Y) break;
-    }
-
-    if (lpNumAttrsWritten) *lpNumAttrsWritten = init_len - nLength;
-    return nLength != init_len;
-}
-
-/******************************************************************************
- * WriteConsoleOutputCharacterA [KERNEL32.@]  Copies character to consecutive
- * 					      cells in the console screen buffer
- *
- * PARAMS
- *    hConsoleOutput    [I] Handle to screen buffer
- *    lpCharacter       [I] Pointer to buffer with chars to write
- *    nLength           [I] Number of cells to write to
- *    dwCoord           [I] Coords of first cell
- *    lpNumCharsWritten [O] Pointer to number of cells written
- */
-BOOL WINAPI WriteConsoleOutputCharacterA(HANDLE hConsoleOutput, LPCSTR lpCharacter, DWORD nLength, 
-					 COORD dwCoord, LPDWORD lpNumCharsWritten)
-{
-    BOOL	ret;
-    LPWSTR	xstring;
-    DWORD 	n;
-    
-    TRACE("(%d,%s,%ld,%dx%d,%p)\n", hConsoleOutput,
-          debugstr_an(lpCharacter, nLength), nLength, dwCoord.X, dwCoord.Y, lpNumCharsWritten);
-    
-    n = MultiByteToWideChar(CP_ACP, 0, lpCharacter, nLength, NULL, 0);
-    
-    if (lpNumCharsWritten) *lpNumCharsWritten = 0;
-    xstring = HeapAlloc(GetProcessHeap(), 0, n * sizeof(WCHAR));
-    if (!xstring) return FALSE;
-    
-    MultiByteToWideChar(CP_ACP, 0, lpCharacter, nLength, xstring, n);
-    
-    ret = WriteConsoleOutputCharacterW(hConsoleOutput, xstring, n, dwCoord, lpNumCharsWritten);
-    
-    HeapFree(GetProcessHeap(), 0, xstring);
-    
-    return ret;
-}
-
-/******************************************************************************
- * WriteConsoleOutputCharacterW [KERNEL32.@]  Copies character to consecutive
- * 					      cells in the console screen buffer
- *
- * PARAMS
- *    hConsoleOutput    [I] Handle to screen buffer
- *    lpCharacter       [I] Pointer to buffer with chars to write
- *    nLength           [I] Number of cells to write to
- *    dwCoord           [I] Coords of first cell
- *    lpNumCharsWritten [O] Pointer to number of cells written
- *
- * RETURNS
- *    Success: TRUE
- *    Failure: FALSE
- * 
- */
-BOOL WINAPI WriteConsoleOutputCharacterW(HANDLE hConsoleOutput, LPCWSTR lpCharacter, DWORD nLength, 
-					 COORD dwCoord, LPDWORD lpNumCharsWritten)
-{
-    int		written = 0;
-    int		len;
-    DWORD	init_len = nLength;
-    CONSOLE_SCREEN_BUFFER_INFO csbi;
-    
-    TRACE("(%d,%s,%ld,%dx%d,%p)\n", hConsoleOutput,
-          debugstr_wn(lpCharacter, nLength), nLength, dwCoord.X, dwCoord.Y, lpNumCharsWritten);
-    
-    if (!GetConsoleScreenBufferInfo(hConsoleOutput, &csbi))
-	return FALSE;
-    
-    while (nLength)
-    {	
-	len = min(nLength * sizeof(WCHAR), REQUEST_MAX_VAR_SIZE);
-	SERVER_START_VAR_REQ(write_console_output, len)
-	{
-	    req->handle = hConsoleOutput;
-	    req->x      = dwCoord.X;
-	    req->y      = dwCoord.Y;
-	    req->mode   = WRITE_CONSOLE_MODE_TEXT;
-	    memcpy(server_data_ptr(req), &lpCharacter[written], len);
-	    written = (SERVER_CALL_ERR()) ? 0 : req->written;
-	}
-	SERVER_END_VAR_REQ;
-
-	if (!written) break;
-	nLength -= written;
-	dwCoord.X += written;
-	if (dwCoord.X >= csbi.dwSize.X)
-	{
-	    dwCoord.X = 0;
-	    if (++dwCoord.Y == csbi.dwSize.Y) break;
-	}
-    }
-
-    if (lpNumCharsWritten) *lpNumCharsWritten = init_len - nLength;
-    return nLength != init_len;
-}
 
 /* ====================================================================
  *
@@ -2232,26 +1371,25 @@
  *	SetConsoleCommandHistoryMode
  *	SetConsoleNumberOfCommands[AW]
  */
-int	CONSOLE_GetHistory(int idx, WCHAR* buf, int buf_len)
+int CONSOLE_GetHistory(int idx, WCHAR* buf, int buf_len)
 {
-    int		len = 0;
+    int len = 0;
 
-    SERVER_START_VAR_REQ(get_console_input_history, REQUEST_MAX_VAR_SIZE)
+    SERVER_START_REQ( get_console_input_history )
     {
-	req->handle = 0;
-	req->index = idx;
-	if (!SERVER_CALL_ERR())
-	{
-	    len = server_data_size(req) / sizeof(WCHAR) + 1;
-	    if (buf)
-	    {
-		len = min(len, buf_len);
-		memcpy(buf, server_data_ptr(req), len * sizeof(WCHAR));
-		buf[len - 1] = 0;
-	    }
-	}
-    }		
-    SERVER_END_VAR_REQ;
+        req->handle = 0;
+        req->index = idx;
+        if (buf && buf_len > sizeof(WCHAR))
+        {
+            wine_server_set_reply( req, buf, buf_len - sizeof(WCHAR) );
+        }
+        if (!wine_server_call_err( req ))
+        {
+            if (buf) buf[wine_server_reply_size(reply) / sizeof(WCHAR)] = 0;
+            len = reply->total / sizeof(WCHAR) + 1;
+        }
+    }
+    SERVER_END_REQ;
     return len;
 }
 
@@ -2265,17 +1403,15 @@
     size_t	len = strlenW(ptr);
     BOOL	ret;
 
-    while (len && (ptr[len - 1] == '\n' || ptr[len - 1] == '\r'))
-	len--;
+    while (len && (ptr[len - 1] == '\n' || ptr[len - 1] == '\r')) len--;
 
-    len *= sizeof(WCHAR);
-    SERVER_START_VAR_REQ(append_console_input_history, len)
+    SERVER_START_REQ( append_console_input_history )
     {
-	req->handle = 0;
-	memcpy(server_data_ptr(req), ptr, len);
-	ret = !SERVER_CALL_ERR();
+        req->handle = 0;
+        wine_server_add_data( req, ptr, len * sizeof(WCHAR) );
+        ret = !wine_server_call_err( req );
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     return ret;
 }
 
@@ -2289,8 +1425,8 @@
     unsigned ret = 0;
     SERVER_START_REQ(get_console_input_info)
     {
-	req->handle = 0;
-	if (!SERVER_CALL_ERR()) ret = req->history_index;
+        req->handle = 0;
+        if (!wine_server_call_err( req )) ret = reply->history_index;
     }
     SERVER_END_REQ;
     return ret;
diff --git a/win32/device.c b/win32/device.c
index 1e85018..0856d97 100644
--- a/win32/device.c
+++ b/win32/device.c
@@ -339,12 +339,12 @@
     SERVER_START_REQ( get_file_info )
     {
         req->handle = handle;
-        if (!SERVER_CALL() &&
-            (req->type == FILE_TYPE_UNKNOWN) &&
-            (req->attr & 0x10000))
+        if (!wine_server_call( req ) &&
+            (reply->type == FILE_TYPE_UNKNOWN) &&
+            (reply->attr & 0x10000))
         {
             for (info = VxDList; info->name; info++)
-                if (info->id == LOWORD(req->attr)) break;
+                if (info->id == LOWORD(reply->attr)) break;
         }
     }
     SERVER_END_REQ;
diff --git a/win32/except.c b/win32/except.c
index 849b5f4..d107835 100644
--- a/win32/except.c
+++ b/win32/except.c
@@ -159,29 +159,28 @@
     int ret;
     HANDLE handle = 0;
 
-    SERVER_START_VAR_REQ( queue_exception_event, sizeof(*rec) + sizeof(*context) )
+    SERVER_START_REQ( queue_exception_event )
     {
-        CONTEXT *context_ptr = server_data_ptr(req);
-        EXCEPTION_RECORD *rec_ptr = (EXCEPTION_RECORD *)(context_ptr + 1);
         req->first   = first_chance;
-        *rec_ptr     = *rec;
-        *context_ptr = *context;
-        if (!SERVER_CALL()) handle = req->handle;
+        wine_server_add_data( req, context, sizeof(*context) );
+        wine_server_add_data( req, rec, sizeof(*rec) );
+        if (!wine_server_call(req)) handle = reply->handle;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     if (!handle) return 0;  /* no debugger present or other error */
 
     /* No need to wait on the handle since the process gets suspended
      * once the event is passed to the debugger, so when we get back
      * here the event has been continued already.
      */
-    SERVER_START_VAR_REQ( get_exception_status, sizeof(*context) )
+    SERVER_START_REQ( get_exception_status )
     {
         req->handle = handle;
-        if (!SERVER_CALL()) *context = *(CONTEXT *)server_data_ptr(req);
-        ret = req->status;
+        wine_server_set_reply( req, context, sizeof(*context) );
+        wine_server_call( req );
+        ret = reply->status;
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     NtClose( handle );
     return ret;
 }
diff --git a/windows/defwnd.c b/windows/defwnd.c
index d56404c..7fe5e94 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -75,18 +75,16 @@
     if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
     if ((textW = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
     {
-        size_t len = min( REQUEST_MAX_VAR_SIZE, (count-1) * sizeof(WCHAR) );
-
         if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
         wndPtr->text = textW;
         MultiByteToWideChar( CP_ACP, 0, text, -1, textW, count );
-        SERVER_START_VAR_REQ( set_window_text, len )
+        SERVER_START_REQ( set_window_text )
         {
             req->handle = hwnd;
-            memcpy( server_data_ptr(req), textW, len );
-            SERVER_CALL();
+            wine_server_add_data( req, textW, (count-1) * sizeof(WCHAR) );
+            wine_server_call( req );
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
     }
     else
         ERR("Not enough memory for window text\n");
@@ -113,16 +111,14 @@
     if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
     if ((wndPtr->text = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
     {
-        size_t len = min( REQUEST_MAX_VAR_SIZE, (count-1) * sizeof(WCHAR) );
-
         strcpyW( wndPtr->text, text );
-        SERVER_START_VAR_REQ( set_window_text, len )
+        SERVER_START_REQ( set_window_text )
         {
             req->handle = hwnd;
-            memcpy( server_data_ptr(req), wndPtr->text, len );
-            SERVER_CALL();
+            wine_server_add_data( req, wndPtr->text, (count-1) * sizeof(WCHAR) );
+            wine_server_call( req );
         }
-        SERVER_END_VAR_REQ;
+        SERVER_END_REQ;
     }
     else
         ERR("Not enough memory for window text\n");
diff --git a/windows/input.c b/windows/input.c
index 9004c13..7a916a7 100644
--- a/windows/input.c
+++ b/windows/input.c
@@ -110,7 +110,7 @@
         req->time   = time;
         req->info   = extraInfo;
         req->timeout = 0;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 }
diff --git a/windows/message.c b/windows/message.c
index 8743e7b..fdd7981 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -109,7 +109,7 @@
         req->time   = msg->time;
         req->info   = extra_info;
         req->timeout = 0;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 }
@@ -707,7 +707,7 @@
         req->wake_mask    = (flags & MWMO_INPUTAVAILABLE) ? mask : 0;
         req->changed_mask = mask;
         req->skip_wait    = 0;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 
@@ -751,7 +751,7 @@
     {
         req->handle = hProcess;
         req->timeout = dwTimeOut;
-        if (!(ret = SERVER_CALL_ERR())) idle_event = req->event;
+        if (!(ret = wine_server_call_err( req ))) idle_event = reply->event;
     }
     SERVER_END_REQ;
     if (ret) return WAIT_FAILED;  /* error */
diff --git a/windows/painting.c b/windows/painting.c
index fa579eb..2963efe 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -54,7 +54,7 @@
     {
         req->handle = hwnd;
         req->incr   = incr;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 }
diff --git a/windows/queue.c b/windows/queue.c
index 1829d6c..00dd6aa 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -348,8 +348,8 @@
     {
         SERVER_START_REQ( get_msg_queue )
         {
-            SERVER_CALL_ERR();
-            handle = req->handle;
+            wine_server_call_err( req );
+            handle = reply->handle;
         }
         SERVER_END_REQ;
         if (!handle)
@@ -483,8 +483,8 @@
     SERVER_START_REQ( get_queue_status )
     {
         req->clear = 1;
-        SERVER_CALL();
-        ret = MAKELONG( req->changed_bits & flags, req->wake_bits & flags );
+        wine_server_call( req );
+        ret = MAKELONG( reply->changed_bits & flags, reply->wake_bits & flags );
     }
     SERVER_END_REQ;
     return ret;
@@ -501,8 +501,8 @@
     SERVER_START_REQ( get_queue_status )
     {
         req->clear = 0;
-        SERVER_CALL();
-        ret = req->wake_bits & (QS_KEY | QS_MOUSEBUTTON);
+        wine_server_call( req );
+        ret = reply->wake_bits & (QS_KEY | QS_MOUSEBUTTON);
     }
     SERVER_END_REQ;
     return ret;
diff --git a/windows/timer.c b/windows/timer.c
index 2168d61..2dc61fd 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -154,7 +154,7 @@
         req->id     = id;
         req->rate   = max( timeout, SYS_TIMER_RATE );
         req->lparam = (unsigned int)winproc;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 
@@ -191,7 +191,7 @@
         req->win = hwnd;
         req->msg = sys ? WM_SYSTIMER : WM_TIMER;
         req->id  = id;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 
diff --git a/windows/win.c b/windows/win.c
index b2bdb11..cf39d3f 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -94,7 +94,7 @@
         req->parent = parent;
         req->owner = owner;
         req->atom = atom;
-        if ((res = !SERVER_CALL_ERR())) handle = req->handle;
+        if ((res = !wine_server_call_err( req ))) handle = reply->handle;
     }
     SERVER_END_REQ;
 
@@ -131,7 +131,7 @@
         SERVER_START_REQ( destroy_window )
         {
             req->handle = hwnd;
-            if (!SERVER_CALL_ERR())
+            if (!wine_server_call_err( req ))
                 user_handles[index] = NULL;
             else
                 ptr = NULL;
@@ -152,26 +152,34 @@
  */
 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
 {
-    HWND *list = NULL;
+    HWND *list;
+    int size = 32;
 
-    SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE )
+    for (;;)
     {
-        req->parent = hwnd;
-        req->atom = atom;
-        req->tid = (void *)tid;
-        if (!SERVER_CALL())
+        int count = 0;
+
+        if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
+
+        SERVER_START_REQ( get_window_children )
         {
-            user_handle_t *data = server_data_ptr(req);
-            int i, count = server_data_size(req) / sizeof(*data);
-            if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
-            {
-                for (i = 0; i < count; i++) list[i] = data[i];
-                list[i] = 0;
-            }
+            req->parent = hwnd;
+            req->atom = atom;
+            req->tid = (void *)tid;
+            wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
+            if (!wine_server_call( req )) count = reply->count;
         }
+        SERVER_END_REQ;
+        if (count && count < size)
+        {
+            list[count] = 0;
+            return list;
+        }
+        HeapFree( GetProcessHeap(), 0, list );
+        if (!count) break;
+        size = count + 1;  /* restart with a large enough buffer */
     }
-    SERVER_END_VAR_REQ;
-    return list;
+    return NULL;
 }
 
 
@@ -194,19 +202,15 @@
  */
 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
 {
-    size_t len = (count - 1) * sizeof(WCHAR);
-    len = min( len, REQUEST_MAX_VAR_SIZE );
-    SERVER_START_VAR_REQ( get_window_text, len )
+    size_t len = 0;
+
+    SERVER_START_REQ( get_window_text )
     {
         req->handle = hwnd;
-        if (!SERVER_CALL_ERR())
-        {
-            len = server_data_size(req);
-            memcpy( text, server_data_ptr(req), len );
-        }
-        else len = 0;
+        wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
+        if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
     }
-    SERVER_END_VAR_REQ;
+    SERVER_END_REQ;
     text[len / sizeof(WCHAR)] = 0;
 }
 
@@ -300,7 +304,7 @@
         SERVER_START_REQ( get_window_info )
         {
             req->handle = hwnd;
-            if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
+            if (!wine_server_call_err( req )) hwnd = reply->full_handle;
         }
         SERVER_END_REQ;
     }
@@ -400,12 +404,12 @@
         req->handle   = hwnd;
         req->parent   = parent;
         req->previous = hwndInsertAfter;
-        if (!SERVER_CALL())
+        if (!wine_server_call( req ))
         {
-            if (req->full_parent && req->full_parent != wndPtr->parent)
+            if (reply->full_parent && reply->full_parent != wndPtr->parent)
             {
                 wndPtr->owner = 0;  /* reset owner when changing parent */
-                wndPtr->parent = req->full_parent;
+                wndPtr->parent = reply->full_parent;
             }
         }
 
@@ -434,7 +438,7 @@
     {
         req->handle = hwnd;
         req->owner  = owner;
-        if (!SERVER_CALL()) win->owner = req->full_owner;
+        if (!wine_server_call( req )) win->owner = reply->full_owner;
     }
     SERVER_END_REQ;
     WIN_ReleasePtr( win );
@@ -469,9 +473,9 @@
         req->handle = hwnd;
         req->flags  = SET_WIN_STYLE;
         req->style  = style;
-        if ((ok = !SERVER_CALL()))
+        if ((ok = !wine_server_call( req )))
         {
-            ret = req->old_style;
+            ret = reply->old_style;
             win->dwStyle = style;
         }
     }
@@ -509,9 +513,9 @@
         req->handle   = hwnd;
         req->flags    = SET_WIN_EXSTYLE;
         req->ex_style = style;
-        if (!SERVER_CALL())
+        if (!wine_server_call( req ))
         {
-            ret = req->old_ex_style;
+            ret = reply->old_ex_style;
             win->dwExStyle = style;
         }
     }
@@ -548,7 +552,7 @@
         req->client.top    = rectClient->top;
         req->client.right  = rectClient->right;
         req->client.bottom = rectClient->bottom;
-        ret = !SERVER_CALL();
+        ret = !wine_server_call( req );
     }
     SERVER_END_REQ;
     if (ret)
@@ -1062,7 +1066,7 @@
         req->style     = wndPtr->dwStyle;
         req->ex_style  = wndPtr->dwExStyle;
         req->instance  = (void *)wndPtr->hInstance;
-        SERVER_CALL();
+        wine_server_call( req );
     }
     SERVER_END_REQ;
 
@@ -1821,15 +1825,15 @@
         {
             req->handle = hwnd;
             req->flags  = 0;  /* don't set anything, just retrieve */
-            if (!SERVER_CALL_ERR())
+            if (!wine_server_call_err( req ))
             {
                 switch(offset)
                 {
-                case GWL_STYLE:     retvalue = req->style; break;
-                case GWL_EXSTYLE:   retvalue = req->ex_style; break;
-                case GWL_ID:        retvalue = req->id; break;
-                case GWL_HINSTANCE: retvalue = (ULONG_PTR)req->instance; break;
-                case GWL_USERDATA:  retvalue = (ULONG_PTR)req->user_data; break;
+                case GWL_STYLE:     retvalue = reply->old_style; break;
+                case GWL_EXSTYLE:   retvalue = reply->old_ex_style; break;
+                case GWL_ID:        retvalue = reply->old_id; break;
+                case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
+                case GWL_USERDATA:  retvalue = (ULONG_PTR)reply->old_user_data; break;
                 default:
                     SetLastError( ERROR_INVALID_INDEX );
                     break;
@@ -1991,29 +1995,29 @@
                 req->user_data = (void *)newval;
                 break;
             }
-            if ((ok = !SERVER_CALL_ERR()))
+            if ((ok = !wine_server_call_err( req )))
             {
                 switch(offset)
                 {
                 case GWL_STYLE:
                     wndPtr->dwStyle = newval;
-                    retval = req->old_style;
+                    retval = reply->old_style;
                     break;
                 case GWL_EXSTYLE:
                     wndPtr->dwExStyle = newval;
-                    retval = req->old_ex_style;
+                    retval = reply->old_ex_style;
                     break;
                 case GWL_ID:
                     wndPtr->wIDmenu = newval;
-                    retval = req->old_id;
+                    retval = reply->old_id;
                     break;
                 case GWL_HINSTANCE:
                     wndPtr->hInstance = newval;
-                    retval = (HINSTANCE)req->old_instance;
+                    retval = (HINSTANCE)reply->old_instance;
                     break;
                 case GWL_USERDATA:
                     wndPtr->userdata = newval;
-                    retval = (ULONG_PTR)req->old_user_data;
+                    retval = (ULONG_PTR)reply->old_user_data;
                     break;
                 }
             }
@@ -2281,7 +2285,7 @@
     SERVER_START_REQ( get_window_info )
     {
         req->handle = hwnd;
-        ret = !SERVER_CALL_ERR();
+        ret = !wine_server_call_err( req );
     }
     SERVER_END_REQ;
     return ret;
@@ -2315,10 +2319,10 @@
     SERVER_START_REQ( get_window_info )
     {
         req->handle = hwnd;
-        if (!SERVER_CALL_ERR())
+        if (!wine_server_call_err( req ))
         {
-            tid = (DWORD)req->tid;
-            if (process) *process = (DWORD)req->pid;
+            tid = (DWORD)reply->tid;
+            if (process) *process = (DWORD)reply->pid;
         }
     }
     SERVER_END_REQ;
@@ -2347,10 +2351,10 @@
             SERVER_START_REQ( get_window_tree )
             {
                 req->handle = hwnd;
-                if (!SERVER_CALL_ERR())
+                if (!wine_server_call_err( req ))
                 {
-                    if (style & WS_CHILD) retvalue = req->parent;
-                    else retvalue = req->owner;
+                    if (style & WS_CHILD) retvalue = reply->parent;
+                    else retvalue = reply->owner;
                 }
             }
             SERVER_END_REQ;
@@ -2372,56 +2376,43 @@
 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
 {
     WND *win;
-    HWND ret = 0;
-    size_t size;
+    HWND *list, ret = 0;
 
-    for (;;)
+    if (type == GA_PARENT)
     {
         if (!(win = WIN_GetPtr( hwnd )))
         {
             SetLastError( ERROR_INVALID_WINDOW_HANDLE );
             return 0;
         }
-        if (win == WND_OTHER_PROCESS) break;  /* need to do it the hard way */
-        ret = win->parent;
-        WIN_ReleasePtr( win );
-        if (type == GA_PARENT) return ret;
-        if (!ret || ret == GetDesktopWindow())
+        if (win != WND_OTHER_PROCESS)
         {
-            ret = hwnd;  /* if ret is the desktop, hwnd is the root ancestor */
-            goto done;
+            ret = win->parent;
+            WIN_ReleasePtr( win );
         }
-        hwnd = ret;  /* restart with parent as hwnd */
-    }
-
-    size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
-
-    SERVER_START_VAR_REQ( get_window_parents, size )
-    {
-        req->handle = hwnd;
-        if (!SERVER_CALL())
+        else /* need to query the server */
         {
-            user_handle_t *data = server_data_ptr(req);
-            int count = server_data_size(req) / sizeof(*data);
-            if (count)
+            SERVER_START_REQ( get_window_tree )
             {
-                switch(type)
-                {
-                case GA_PARENT:
-                    ret = data[0];
-                    break;
-                case GA_ROOT:
-                case GA_ROOTOWNER:
-                    if (count > 1) ret = data[count - 2];  /* get the one before the desktop */
-                    else ret = WIN_GetFullHandle( hwnd );
-                    break;
-                }
+                req->handle = hwnd;
+                if (!wine_server_call_err( req )) ret = reply->parent;
             }
+            SERVER_END_REQ;
         }
+        return ret;
     }
-    SERVER_END_VAR_REQ;
 
- done:
+    if (!(list = WIN_ListParents( hwnd ))) return 0;
+
+    if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd );  /* top-level window */
+    else
+    {
+        int count = 2;
+        while (list[count]) count++;
+        ret = list[count - 2];  /* get the one before the desktop */
+    }
+    HeapFree( GetProcessHeap(), 0, list );
+
     if (ret && type == GA_ROOTOWNER)
     {
         for (;;)
@@ -2597,27 +2588,27 @@
     SERVER_START_REQ( get_window_tree )
     {
         req->handle = hwnd;
-        if (!SERVER_CALL_ERR())
+        if (!wine_server_call_err( req ))
         {
             switch(rel)
             {
             case GW_HWNDFIRST:
-                retval = req->first_sibling;
+                retval = reply->first_sibling;
                 break;
             case GW_HWNDLAST:
-                retval = req->last_sibling;
+                retval = reply->last_sibling;
                 break;
             case GW_HWNDNEXT:
-                retval = req->next_sibling;
+                retval = reply->next_sibling;
                 break;
             case GW_HWNDPREV:
-                retval = req->prev_sibling;
+                retval = reply->prev_sibling;
                 break;
             case GW_OWNER:
-                retval = req->owner;
+                retval = reply->owner;
                 break;
             case GW_CHILD:
-                retval = req->first_child;
+                retval = reply->first_child;
                 break;
             }
         }
@@ -2795,29 +2786,27 @@
     }
 
     /* at least one parent belongs to another process, have to query the server */
-    SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
+
+    for (;;)
     {
-        req->handle = hwnd;
-        if (!SERVER_CALL())
+        count = 0;
+        SERVER_START_REQ( get_window_parents )
         {
-            user_handle_t *data = server_data_ptr(req);
-            count = server_data_size(req) / sizeof(*data);
-            if (count)
-            {
-                HWND *new_list = HeapReAlloc( GetProcessHeap(), 0,
-                                              list, (count + 1) * sizeof(HWND) );
-                if (new_list)
-                {
-                    list = new_list;
-                    for (pos = 0; pos < count; pos++) list[pos] = data[pos];
-                    list[pos] = 0;
-                }
-                else count = 0;
-            }
+            req->handle = hwnd;
+            wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
+            if (!wine_server_call( req )) count = reply->count;
         }
+        SERVER_END_REQ;
+        if (!count) goto empty;
+        if (size > count)
+        {
+            list[count] = 0;
+            return list;
+        }
+        HeapFree( GetProcessHeap(), 0, list );
+        size = count + 1;
+        if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
     }
-    SERVER_END_VAR_REQ;
-    if (count) return list;
 
  empty:
     HeapFree( GetProcessHeap(), 0, list );
diff --git a/windows/winpos.c b/windows/winpos.c
index 64f8ddd..bb7e48d 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -189,12 +189,12 @@
         SERVER_START_REQ( get_window_rectangles )
         {
             req->handle = hwnd;
-            if ((ret = !SERVER_CALL_ERR()))
+            if ((ret = !wine_server_call_err( req )))
             {
-                rect->left   = req->window.left;
-                rect->top    = req->window.top;
-                rect->right  = req->window.right;
-                rect->bottom = req->window.bottom;
+                rect->left   = reply->window.left;
+                rect->top    = reply->window.top;
+                rect->right  = reply->window.right;
+                rect->bottom = reply->window.bottom;
             }
         }
         SERVER_END_REQ;
@@ -309,10 +309,10 @@
         SERVER_START_REQ( get_window_rectangles )
         {
             req->handle = hwnd;
-            if ((ret = !SERVER_CALL_ERR()))
+            if ((ret = !wine_server_call_err( req )))
             {
-                rect->right  = req->client.right - req->client.left;
-                rect->bottom = req->client.bottom - req->client.top;
+                rect->right  = reply->client.right - reply->client.left;
+                rect->bottom = reply->client.bottom - reply->client.top;
             }
         }
         SERVER_END_REQ;
@@ -600,10 +600,10 @@
     {
         req->from = hwndFrom;
         req->to   = hwndTo;
-        if (!SERVER_CALL())
+        if (!wine_server_call( req ))
         {
-            offset->x = req->x;
-            offset->y = req->y;
+            offset->x = reply->x;
+            offset->y = reply->y;
         }
     }
     SERVER_END_REQ;