Further server optimizations:
- merged request and reply structures
- build requests directly into the buffer to avoid a copy

diff --git a/files/file.c b/files/file.c
index d7e8558..edce507 100644
--- a/files/file.c
+++ b/files/file.c
@@ -304,24 +304,16 @@
 HFILE FILE_DupUnixHandle( int fd, DWORD access )
 {
     int unix_handle;
-    struct create_file_request req;
-    struct create_file_reply reply;
+    struct alloc_file_handle_request *req = get_req_buffer();
 
     if ((unix_handle = dup(fd)) == -1)
     {
         FILE_SetDosError();
         return INVALID_HANDLE_VALUE;
     }
-    req.access  = access;
-    req.inherit = 1;
-    req.sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
-    req.create  = 0;
-    req.attrs   = 0;
-    
-    CLIENT_SendRequest( REQ_CREATE_FILE, unix_handle, 1,
-                        &req, sizeof(req) );
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-    return reply.handle;
+    req->access  = access;
+    server_call_fd( REQ_ALLOC_FILE_HANDLE, unix_handle, NULL );
+    return req->handle;
 }
 
 
@@ -334,38 +326,28 @@
                          LPSECURITY_ATTRIBUTES sa, DWORD creation,
                          DWORD attributes, HANDLE template )
 {
-    struct create_file_request req;
-    struct create_file_reply reply;
+    struct create_file_request *req = get_req_buffer();
 
-    req.access  = access;
-    req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-    req.sharing = sharing;
-    req.create  = creation;
-    req.attrs   = attributes;
-    CLIENT_SendRequest( REQ_CREATE_FILE, -1, 2,
-                        &req, sizeof(req),
-                        filename, strlen(filename) + 1 );
+    req->access  = access;
+    req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+    req->sharing = sharing;
+    req->create  = creation;
+    req->attrs   = attributes;
+    lstrcpynA( req->name, filename, server_remaining(req->name) );
     SetLastError(0);
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
+    server_call( REQ_CREATE_FILE );
 
     /* If write access failed, retry without GENERIC_WRITE */
 
-    if ((reply.handle == -1) && !Options.failReadOnly &&
+    if ((req->handle == -1) && !Options.failReadOnly &&
         (access & GENERIC_WRITE)) 
     {
     	DWORD lasterror = GetLastError();
-	if ((lasterror == ERROR_ACCESS_DENIED) || 
-	    (lasterror == ERROR_WRITE_PROTECT))
-        {
-	    req.access &= ~GENERIC_WRITE;
-	    CLIENT_SendRequest( REQ_CREATE_FILE, -1, 2,
-				&req, sizeof(req),
-				filename, strlen(filename) + 1 );
-            SetLastError(0);
-	    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-	}
+	if ((lasterror == ERROR_ACCESS_DENIED) || (lasterror == ERROR_WRITE_PROTECT))
+            return FILE_CreateFile( filename, access & ~GENERIC_WRITE, sharing,
+                                    sa, creation, attributes, template );
     }
-    return reply.handle;
+    return req->handle;
 }
 
 
@@ -376,16 +358,14 @@
  */
 HFILE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa )
 {
-    struct create_device_request req;
-    struct create_device_reply reply;
+    struct create_device_request *req = get_req_buffer();
 
-    req.access  = access;
-    req.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
-    req.id      = client_id;
-    CLIENT_SendRequest( REQ_CREATE_DEVICE, -1, 1, &req, sizeof(req) );
+    req->access  = access;
+    req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
+    req->id      = client_id;
     SetLastError(0);
-    CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL );
-    return reply.handle;
+    server_call( REQ_CREATE_DEVICE );
+    return req->handle;
 }
 
 
@@ -562,24 +542,21 @@
 DWORD WINAPI GetFileInformationByHandle( HFILE hFile,
                                          BY_HANDLE_FILE_INFORMATION *info )
 {
-    struct get_file_info_request req;
-    struct get_file_info_reply reply;
+    struct get_file_info_request *req = get_req_buffer();
 
     if (!info) return 0;
-    req.handle = hFile;
-    CLIENT_SendRequest( REQ_GET_FILE_INFO, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ))
-        return 0;
-    DOSFS_UnixTimeToFileTime( reply.write_time, &info->ftCreationTime, 0 );
-    DOSFS_UnixTimeToFileTime( reply.write_time, &info->ftLastWriteTime, 0 );
-    DOSFS_UnixTimeToFileTime( reply.access_time, &info->ftLastAccessTime, 0 );
-    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;
+    req->handle = hFile;
+    if (server_call( REQ_GET_FILE_INFO )) return 0;
+    DOSFS_UnixTimeToFileTime( req->write_time, &info->ftCreationTime, 0 );
+    DOSFS_UnixTimeToFileTime( req->write_time, &info->ftLastWriteTime, 0 );
+    DOSFS_UnixTimeToFileTime( req->access_time, &info->ftLastAccessTime, 0 );
+    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;
     return 1;
 }
 
@@ -1121,7 +1098,7 @@
 BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
                         LPDWORD bytesRead, LPOVERLAPPED overlapped )
 {
-    struct get_read_fd_request req;
+    struct get_read_fd_request *req = get_req_buffer();
     int unix_handle, result;
 
     TRACE(file, "%d %p %ld\n", hFile, buffer, bytesToRead );
@@ -1129,9 +1106,8 @@
     if (bytesRead) *bytesRead = 0;  /* Do this before anything else */
     if (!bytesToRead) return TRUE;
 
-    req.handle = hFile;
-    CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &req, sizeof(req) );
-    CLIENT_WaitReply( NULL, &unix_handle, 0 );
+    req->handle = hFile;
+    server_call_fd( REQ_GET_READ_FD, -1, &unix_handle );
     if (unix_handle == -1) return FALSE;
     while ((result = read( unix_handle, buffer, bytesToRead )) == -1)
     {
@@ -1153,7 +1129,7 @@
 BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
                          LPDWORD bytesWritten, LPOVERLAPPED overlapped )
 {
-    struct get_write_fd_request req;
+    struct get_write_fd_request *req = get_req_buffer();
     int unix_handle, result;
 
     TRACE(file, "%d %p %ld\n", hFile, buffer, bytesToWrite );
@@ -1161,9 +1137,8 @@
     if (bytesWritten) *bytesWritten = 0;  /* Do this before anything else */
     if (!bytesToWrite) return TRUE;
 
-    req.handle = hFile;
-    CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
-    CLIENT_WaitReply( NULL, &unix_handle, 0 );
+    req->handle = hFile;
+    server_call_fd( REQ_GET_WRITE_FD, -1, &unix_handle );
     if (unix_handle == -1) return FALSE;
     while ((result = write( unix_handle, buffer, bytesToWrite )) == -1)
     {
@@ -1254,8 +1229,7 @@
 DWORD WINAPI SetFilePointer( HFILE hFile, LONG distance, LONG *highword,
                              DWORD method )
 {
-    struct set_file_pointer_request req;
-    struct set_file_pointer_reply reply;
+    struct set_file_pointer_request *req = get_req_buffer();
 
     if (highword && *highword)
     {
@@ -1266,16 +1240,15 @@
     TRACE(file, "handle %d offset %ld origin %ld\n",
           hFile, distance, method );
 
-    req.handle = hFile;
-    req.low = distance;
-    req.high = highword ? *highword : 0;
+    req->handle = hFile;
+    req->low = distance;
+    req->high = highword ? *highword : 0;
     /* FIXME: assumes 1:1 mapping between Windows and Unix seek constants */
-    req.whence = method;
-    CLIENT_SendRequest( REQ_SET_FILE_POINTER, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0xffffffff;
+    req->whence = method;
     SetLastError( 0 );
-    if (highword) *highword = reply.high;
-    return reply.low;
+    if (server_call( REQ_SET_FILE_POINTER )) return 0xffffffff;
+    if (highword) *highword = req->new_high;
+    return req->new_low;
 }
 
 
@@ -1462,11 +1435,9 @@
  */
 BOOL WINAPI FlushFileBuffers( HFILE hFile )
 {
-    struct flush_file_request req;
-
-    req.handle = hFile;
-    CLIENT_SendRequest( REQ_FLUSH_FILE, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct flush_file_request *req = get_req_buffer();
+    req->handle = hFile;
+    return !server_call( REQ_FLUSH_FILE );
 }
 
 
@@ -1475,11 +1446,9 @@
  */
 BOOL WINAPI SetEndOfFile( HFILE hFile )
 {
-    struct truncate_file_request req;
-
-    req.handle = hFile;
-    CLIENT_SendRequest( REQ_TRUNCATE_FILE, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    struct truncate_file_request *req = get_req_buffer();
+    req->handle = hFile;
+    return !server_call( REQ_TRUNCATE_FILE );
 }
 
 
@@ -1631,14 +1600,10 @@
  */
 DWORD WINAPI GetFileType( HFILE hFile )
 {
-    struct get_file_info_request req;
-    struct get_file_info_reply reply;
-
-    req.handle = hFile;
-    CLIENT_SendRequest( REQ_GET_FILE_INFO, -1, 1, &req, sizeof(req) );
-    if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ))
-        return FILE_TYPE_UNKNOWN;
-    return reply.type;
+    struct get_file_info_request *req = get_req_buffer();
+    req->handle = hFile;
+    if (server_call( REQ_GET_FILE_INFO )) return FILE_TYPE_UNKNOWN;
+    return req->type;
 }
 
 
@@ -1913,20 +1878,18 @@
                            const FILETIME *lpLastAccessTime,
                            const FILETIME *lpLastWriteTime )
 {
-    struct set_file_time_request req;
+    struct set_file_time_request *req = get_req_buffer();
 
-    req.handle = hFile;
+    req->handle = hFile;
     if (lpLastAccessTime)
-	req.access_time = DOSFS_FileTimeToUnixTime(lpLastAccessTime, NULL);
+	req->access_time = DOSFS_FileTimeToUnixTime(lpLastAccessTime, NULL);
     else
-	req.access_time = 0; /* FIXME */
+	req->access_time = 0; /* FIXME */
     if (lpLastWriteTime)
-	req.write_time = DOSFS_FileTimeToUnixTime(lpLastWriteTime, NULL);
+	req->write_time = DOSFS_FileTimeToUnixTime(lpLastWriteTime, NULL);
     else
-	req.write_time = 0; /* FIXME */
-
-    CLIENT_SendRequest( REQ_SET_FILE_TIME, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+	req->write_time = 0; /* FIXME */
+    return !server_call( REQ_SET_FILE_TIME );
 }
 
 
@@ -1936,15 +1899,14 @@
 BOOL WINAPI LockFile( HFILE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
                         DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh )
 {
-    struct lock_file_request req;
+    struct lock_file_request *req = get_req_buffer();
 
-    req.handle      = hFile;
-    req.offset_low  = dwFileOffsetLow;
-    req.offset_high = dwFileOffsetHigh;
-    req.count_low   = nNumberOfBytesToLockLow;
-    req.count_high  = nNumberOfBytesToLockHigh;
-    CLIENT_SendRequest( REQ_LOCK_FILE, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    req->handle      = hFile;
+    req->offset_low  = dwFileOffsetLow;
+    req->offset_high = dwFileOffsetHigh;
+    req->count_low   = nNumberOfBytesToLockLow;
+    req->count_high  = nNumberOfBytesToLockHigh;
+    return !server_call( REQ_LOCK_FILE );
 }
 
 /**************************************************************************
@@ -1984,15 +1946,14 @@
 BOOL WINAPI UnlockFile( HFILE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
                           DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh )
 {
-    struct unlock_file_request req;
+    struct unlock_file_request *req = get_req_buffer();
 
-    req.handle      = hFile;
-    req.offset_low  = dwFileOffsetLow;
-    req.offset_high = dwFileOffsetHigh;
-    req.count_low   = nNumberOfBytesToUnlockLow;
-    req.count_high  = nNumberOfBytesToUnlockHigh;
-    CLIENT_SendRequest( REQ_UNLOCK_FILE, -1, 1, &req, sizeof(req) );
-    return !CLIENT_WaitReply( NULL, NULL, 0 );
+    req->handle      = hFile;
+    req->offset_low  = dwFileOffsetLow;
+    req->offset_high = dwFileOffsetHigh;
+    req->count_low   = nNumberOfBytesToUnlockLow;
+    req->count_high  = nNumberOfBytesToUnlockHigh;
+    return !server_call( REQ_UNLOCK_FILE );
 }