Reimplemented Read/WriteFile to use server file descriptors.
Removed file position hack as it is wrong for Win32 (should be redone
for Win16 only).
diff --git a/files/file.c b/files/file.c
index 779c41b..585b461 100644
--- a/files/file.c
+++ b/files/file.c
@@ -45,24 +45,29 @@
#define MAP_ANON MAP_ANONYMOUS
#endif
+#if 0
static BOOL32 FILE_Signaled(K32OBJ *ptr, DWORD tid);
static BOOL32 FILE_Satisfied(K32OBJ *ptr, DWORD thread_id);
static void FILE_AddWait(K32OBJ *ptr, DWORD tid);
static void FILE_RemoveWait(K32OBJ *ptr, DWORD thread_id);
-static BOOL32 FILE_Read(K32OBJ *ptr, LPVOID lpBuffer, DWORD nNumberOfChars,
- LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped);
-static BOOL32 FILE_Write(K32OBJ *ptr, LPCVOID lpBuffer, DWORD nNumberOfChars,
- LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped);
+#endif
static void FILE_Destroy( K32OBJ *obj );
const K32OBJ_OPS FILE_Ops =
{
+#if 0
FILE_Signaled, /* signaled */
FILE_Satisfied, /* satisfied */
FILE_AddWait, /* add_wait */
FILE_RemoveWait, /* remove_wait */
- FILE_Read, /* read */
- FILE_Write, /* write */
+#else
+ NULL, /* signaled */
+ NULL, /* satisfied */
+ NULL, /* add_wait */
+ NULL, /* remove_wait */
+#endif
+ NULL, /* read */
+ NULL, /* write */
FILE_Destroy /* destroy */
};
@@ -91,7 +96,6 @@
struct create_file_request req;
struct create_file_reply reply;
int len;
- int fd = dup(unix_handle);
req.access = FILE_ALL_ACCESS | GENERIC_READ |
GENERIC_WRITE | GENERIC_EXECUTE; /* FIXME */
@@ -111,9 +115,7 @@
(*file)->header.type = K32OBJ_FILE;
(*file)->header.refcount = 0;
(*file)->unix_name = NULL;
- (*file)->unix_handle = fd;
(*file)->type = FILE_TYPE_DISK;
- (*file)->pos = 0;
(*file)->mode = 0;
(*file)->wait_queue = NULL;
@@ -127,7 +129,7 @@
/***********************************************************************
* FILE_async_handler [internal]
*/
-#if 1
+#if 0
static void
FILE_async_handler(int unixfd,void *private) {
FILE_OBJECT *file = (FILE_OBJECT*)private;
@@ -176,76 +178,6 @@
}
#endif
-/* FIXME: lpOverlapped is ignored */
-static BOOL32 FILE_Read(K32OBJ *ptr, LPVOID lpBuffer, DWORD nNumberOfChars,
- LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
-{
- FILE_OBJECT *file = (FILE_OBJECT *)ptr;
- int result;
-
- TRACE(file, "%p %p %ld\n", ptr, lpBuffer,
- nNumberOfChars);
-
- if (nNumberOfChars == 0) {
- *lpNumberOfChars = 0; /* FIXME: does this change */
- return TRUE;
- }
-
- if ( (file->pos < 0) || /* workaround, see SetFilePointer */
- ((result = read(file->unix_handle, lpBuffer, nNumberOfChars)) == -1) )
- {
- FILE_SetDosError();
- return FALSE;
- }
- file->pos += result;
- *lpNumberOfChars = result;
- return TRUE;
-}
-
-/**
- * experimentation yields that WriteFile:
- * o does not truncate on write of 0
- * o always changes the *lpNumberOfChars to actual number of
- * characters written
- * o write of 0 nNumberOfChars returns TRUE
- */
-static BOOL32 FILE_Write(K32OBJ *ptr, LPCVOID lpBuffer, DWORD nNumberOfChars,
- LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
-{
- FILE_OBJECT *file = (FILE_OBJECT *)ptr;
- int result;
-
- TRACE(file, "%p %p %ld\n", ptr, lpBuffer,
- nNumberOfChars);
-
- *lpNumberOfChars = 0;
-
- /*
- * I assume this loop around EAGAIN is here because
- * win32 doesn't have interrupted system calls
- */
-
- if (file->pos < 0) { /* workaround, see SetFilePointer */
- FILE_SetDosError();
- return FALSE;
- }
-
- for (;;)
- {
- result = write(file->unix_handle, lpBuffer, nNumberOfChars);
- if (result != -1) {
- *lpNumberOfChars = result;
- file->pos += result;
- return TRUE;
- }
- if (errno != EINTR) {
- FILE_SetDosError();
- return FALSE;
- }
- }
-}
-
-
/***********************************************************************
* FILE_Destroy
@@ -1309,6 +1241,96 @@
/***********************************************************************
+ * ReadFile (KERNEL32.428)
+ */
+BOOL32 WINAPI ReadFile( HANDLE32 hFile, LPVOID buffer, DWORD bytesToRead,
+ LPDWORD bytesRead, LPOVERLAPPED overlapped )
+{
+ K32OBJ *ptr;
+ struct get_read_fd_request req;
+
+ TRACE(file, "%d %p %ld\n", hFile, buffer, bytesToRead );
+
+ if (bytesRead) *bytesRead = 0; /* Do this before anything else */
+ if (!bytesToRead) return TRUE;
+
+ if (!(ptr = HANDLE_GetObjPtr( PROCESS_Current(), hFile,
+ K32OBJ_UNKNOWN, GENERIC_READ, &req.handle )))
+ return FALSE;
+
+ if (req.handle != -1) /* We have a server handle */
+ {
+ int unix_handle, result;
+
+ CLIENT_SendRequest( REQ_GET_READ_FD, -1, 1, &req, sizeof(req) );
+ CLIENT_WaitReply( NULL, &unix_handle, 0 );
+ if (unix_handle == -1) return FALSE;
+ if ((result = read( unix_handle, buffer, bytesToRead )) == -1)
+ FILE_SetDosError();
+ close( unix_handle );
+ K32OBJ_DecCount( ptr );
+ if (result == -1) return FALSE;
+ if (bytesRead) *bytesRead = result;
+ return TRUE;
+ }
+ else
+ {
+ BOOL32 status = FALSE;
+ if (K32OBJ_OPS(ptr)->read)
+ status = K32OBJ_OPS(ptr)->read(ptr, buffer, bytesToRead, bytesRead, overlapped );
+ K32OBJ_DecCount( ptr );
+ return status;
+ }
+}
+
+
+/***********************************************************************
+ * WriteFile (KERNEL32.578)
+ */
+BOOL32 WINAPI WriteFile( HANDLE32 hFile, LPCVOID buffer, DWORD bytesToWrite,
+ LPDWORD bytesWritten, LPOVERLAPPED overlapped )
+{
+ K32OBJ *ptr;
+ struct get_write_fd_request req;
+
+ TRACE(file, "%d %p %ld\n", hFile, buffer, bytesToWrite );
+
+ if (bytesWritten) *bytesWritten = 0; /* Do this before anything else */
+ if (!bytesToWrite) return TRUE;
+
+ if (!(ptr = HANDLE_GetObjPtr( PROCESS_Current(), hFile,
+ K32OBJ_UNKNOWN, GENERIC_WRITE, &req.handle )))
+ return FALSE;
+
+ if (req.handle != -1) /* We have a server handle */
+ {
+ int unix_handle, result;
+
+ CLIENT_SendRequest( REQ_GET_WRITE_FD, -1, 1, &req, sizeof(req) );
+ CLIENT_WaitReply( NULL, &unix_handle, 0 );
+ if (unix_handle == -1) return FALSE;
+
+ if ((result = write( unix_handle, buffer, bytesToWrite )) == -1)
+ FILE_SetDosError();
+ close( unix_handle );
+ K32OBJ_DecCount( ptr );
+ if (result == -1) return FALSE;
+ if (bytesWritten) *bytesWritten = result;
+ return TRUE;
+ }
+ else
+ {
+ BOOL32 status = FALSE;
+ if (K32OBJ_OPS(ptr)->write)
+ status = K32OBJ_OPS(ptr)->write( ptr, buffer, bytesToWrite,
+ bytesWritten, overlapped );
+ K32OBJ_DecCount( ptr );
+ return status;
+ }
+}
+
+
+/***********************************************************************
* WIN16_hread
*/
LONG WINAPI WIN16_hread( HFILE16 hFile, SEGPTR buffer, LONG count )
@@ -1339,18 +1361,9 @@
*/
UINT32 WINAPI _lread32( HFILE32 handle, LPVOID buffer, UINT32 count )
{
- K32OBJ *ptr;
- DWORD numWritten;
- BOOL32 result = FALSE;
-
- TRACE( file, "%d %p %d\n", handle, buffer, count);
- if (!(ptr = HANDLE_GetObjPtr( PROCESS_Current(), handle,
- K32OBJ_UNKNOWN, 0, NULL))) return -1;
- if (K32OBJ_OPS(ptr)->read)
- result = K32OBJ_OPS(ptr)->read(ptr, buffer, count, &numWritten, NULL);
- K32OBJ_DecCount( ptr );
- if (!result) return -1;
- return (UINT32)numWritten;
+ DWORD result;
+ if (!ReadFile( handle, buffer, count, &result, NULL )) return -1;
+ return result;
}
@@ -1403,8 +1416,9 @@
DWORD method )
{
FILE_OBJECT *file;
- DWORD result = 0xffffffff;
- int unix_handle;
+ struct set_file_pointer_request req;
+ struct set_file_pointer_reply reply;
+ int len, err;
if (highword && *highword)
{
@@ -1415,64 +1429,31 @@
TRACE(file, "handle %d offset %ld origin %ld\n",
hFile, distance, method );
- if (!(file = FILE_GetFile( hFile, 0, NULL ))) return 0xffffffff;
- if ((unix_handle = FILE_GetUnixHandle( hFile, 0 )) == -1)
- {
- FILE_ReleaseFile( file );
- return 0xffffffff;
- }
+ if (!(file = FILE_GetFile( hFile, 0, &req.handle ))) return 0xffffffff;
+ assert( req.handle != -1 );
- /* the pointer may be positioned before the start of the file;
- no error is returned in that case,
- but subsequent attempts at I/O will produce errors.
- This is not allowed with Unix lseek(),
- so we'll need some emulation here */
- switch(method)
- {
- case FILE_CURRENT:
- distance += file->pos; /* fall through */
- case FILE_BEGIN:
- if ((result = lseek(unix_handle, distance, SEEK_SET)) == -1)
- {
- if ((INT32)distance < 0)
- file->pos = result = distance;
- }
- else
- file->pos = result;
- break;
- case FILE_END:
- if ((result = lseek(unix_handle, distance, SEEK_END)) == -1)
- {
- if ((INT32)distance < 0)
- {
- /* get EOF */
- result = lseek(unix_handle, 0, SEEK_END);
-
- /* return to the old pos, as the first lseek failed */
- lseek(unix_handle, file->pos, SEEK_END);
-
- file->pos = (result += distance);
- }
- else
- ERR(file, "lseek: unknown error. Please report.\n");
- }
- else file->pos = result;
- break;
- default:
- ERR(file, "Unknown origin %ld !\n", method);
- }
-
- if (result == -1)
- FILE_SetDosError();
-
- close( unix_handle );
+ 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) );
+ err = CLIENT_WaitReply( &len, NULL, 1, &reply, sizeof(reply) );
+ CHECK_LEN( len, sizeof(reply) );
FILE_ReleaseFile( file );
- return result;
+ if (err) return 0xffffffff;
+ SetLastError( 0 );
+ if (highword) *highword = reply.high;
+ return reply.low;
}
/***********************************************************************
* _llseek16 (KERNEL.84)
+ *
+ * FIXME:
+ * Seeking before the start of the file should be allowed for _llseek16,
+ * but cause subsequent I/O operations to fail (cf. interrupt list)
+ *
*/
LONG WINAPI _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin )
{
@@ -1521,7 +1502,7 @@
}
/***********************************************************************
- * _lwrite32 (KERNEL.86)
+ * _lwrite32 (KERNEL32.761)
*/
UINT32 WINAPI _lwrite32( HFILE32 hFile, LPCSTR buffer, UINT32 count )
{
@@ -1559,7 +1540,7 @@
/***********************************************************************
* _hwrite32 (KERNEL32.591)
*
- * experimenation yields that _lwrite:
+ * experimentation yields that _lwrite:
* o truncates the file at the current position with
* a 0 len write
* o returns 0 on a 0 length write
@@ -1568,35 +1549,19 @@
*/
LONG WINAPI _hwrite32( HFILE32 handle, LPCSTR buffer, LONG count )
{
- K32OBJ *ioptr;
- DWORD result;
- BOOL32 status = FALSE;
-
- TRACE(file, "%d %p %ld\n", handle, buffer, count );
+ DWORD result;
- if (count == 0) { /* Expand or truncate at current position */
- int unix_handle = FILE_GetUnixHandle( handle, GENERIC_WRITE );
- if ((unix_handle != -1) &&
- (ftruncate(unix_handle,
- lseek( unix_handle, 0, SEEK_CUR)) == 0 ))
- {
- close( unix_handle );
- return 0;
- } else {
- FILE_SetDosError();
- close( unix_handle );
- return HFILE_ERROR32;
- }
- }
-
- if (!(ioptr = HANDLE_GetObjPtr( PROCESS_Current(), handle,
- K32OBJ_UNKNOWN, 0, NULL )))
- return HFILE_ERROR32;
- if (K32OBJ_OPS(ioptr)->write)
- status = K32OBJ_OPS(ioptr)->write(ioptr, buffer, count, &result, NULL);
- K32OBJ_DecCount( ioptr );
- if (!status) result = HFILE_ERROR32;
- return result;
+ TRACE(file, "%d %p %ld\n", handle, buffer, count );
+
+ if (!count)
+ {
+ /* Expand or truncate at current position */
+ if (!SetEndOfFile( handle )) return HFILE_ERROR32;
+ return 0;
+ }
+ if (!WriteFile( handle, buffer, count, &result, NULL ))
+ return HFILE_ERROR32;
+ return result;
}
@@ -1666,18 +1631,16 @@
*/
BOOL32 WINAPI FlushFileBuffers( HFILE32 hFile )
{
- int unix_handle;
+ FILE_OBJECT *file;
BOOL32 ret;
+ struct flush_file_request req;
- TRACE(file, "(%d)\n", hFile );
- if ((unix_handle = FILE_GetUnixHandle( hFile, 0)) == -1) return FALSE;
- if (fsync( unix_handle ) != -1) ret = TRUE;
- else
- {
- FILE_SetDosError();
- ret = FALSE;
- }
- close( unix_handle );
+ if (!(file = FILE_GetFile( hFile, GENERIC_WRITE, &req.handle ))) return FALSE;
+ assert( req.handle != -1 );
+
+ CLIENT_SendRequest( REQ_FLUSH_FILE, -1, 1, &req, sizeof(req) );
+ ret = !CLIENT_WaitReply( NULL, NULL, 0 );
+ FILE_ReleaseFile( file );
return ret;
}
@@ -1687,18 +1650,16 @@
*/
BOOL32 WINAPI SetEndOfFile( HFILE32 hFile )
{
- int unix_handle;
- BOOL32 ret = TRUE;
+ FILE_OBJECT *file;
+ BOOL32 ret;
+ struct truncate_file_request req;
- TRACE(file, "(%d)\n", hFile );
- if ((unix_handle = FILE_GetUnixHandle( hFile, GENERIC_WRITE )) == -1) return FALSE;
- if (ftruncate( unix_handle,
- lseek( unix_handle, 0, SEEK_CUR ) ))
- {
- FILE_SetDosError();
- ret = FALSE;
- }
- close( unix_handle );
+ if (!(file = FILE_GetFile( hFile, GENERIC_WRITE, &req.handle ))) return FALSE;
+ assert( req.handle != -1 );
+
+ CLIENT_SendRequest( REQ_TRUNCATE_FILE, -1, 1, &req, sizeof(req) );
+ ret = !CLIENT_WaitReply( NULL, NULL, 0 );
+ FILE_ReleaseFile( file );
return ret;
}
@@ -1764,30 +1725,6 @@
/***********************************************************************
- * FILE_mmap
- */
-LPVOID FILE_mmap( HFILE32 hFile, LPVOID start,
- DWORD size_high, DWORD size_low,
- DWORD offset_high, DWORD offset_low,
- int prot, int flags )
-{
- LPVOID ret;
- int unix_handle;
- FILE_OBJECT *file = FILE_GetFile( hFile, 0, NULL );
- if (!file) return (LPVOID)-1;
- if ((unix_handle = FILE_GetUnixHandle( hFile, 0 )) == -1) ret = (LPVOID)-1;
- else
- {
- ret = FILE_dommap( file, unix_handle, start, size_high, size_low,
- offset_high, offset_low, prot, flags );
- close( unix_handle );
- }
- FILE_ReleaseFile( file );
- return ret;
-}
-
-
-/***********************************************************************
* FILE_dommap
*/
LPVOID FILE_dommap( FILE_OBJECT *file, int unix_handle, LPVOID start,