Partial implementations of NtOpenFile and NtReadFile

Mike McCormack mikem at codeweavers.com
Sun Jun 9 12:48:02 CDT 2002


Hi,

This patch implements NtOpenFile for files on DOS drives and simple 
synchronous reads using NtReadFile. To make NtOpenFile work properly, we 
need to handle NT pathnames in wineserver.

Mike


License: LPGL (as always)
ChangeLog:
* partially implement NtOpenFile and NtReadFile
-------------- next part --------------
Index: dlls/ntdll/file.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/file.c,v
retrieving revision 1.13
diff -u -r1.13 file.c
--- dlls/ntdll/file.c	31 May 2002 23:25:49 -0000	1.13
+++ dlls/ntdll/file.c	9 Jun 2002 09:17:24 -0000
@@ -16,16 +16,28 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include "config.h"
+#include "wine/port.h"
+
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_ERRNO_H
+#include <sys/errno.h>
+#endif
 #include "wine/debug.h"
+#include "wine/server.h"
 #include "ntdll_misc.h"
+#include "file.h" /* FIXME */
 
 #include "ntddk.h"
 #include "winioctl.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 
+
 /**************************************************************************
  *                 NtOpenFile				[NTDLL.@]
  *                 ZwOpenFile				[NTDLL.@]
@@ -46,11 +58,60 @@
 	ULONG ShareAccess,
 	ULONG OpenOptions)
 {
-	FIXME("(%p,0x%08lx,%p,%p,0x%08lx,0x%08lx) stub\n",
-	FileHandle, DesiredAccess, ObjectAttributes,
-	IoStatusBlock, ShareAccess, OpenOptions);
+	ULONG len = 0;
+	PSTR filename;
+	CHAR szDosDevices[] = "\\DosDevices\\";
+	DOS_FULL_NAME full_name;
+	NTSTATUS r;
+	
+	FIXME("(%p,0x%08lx,%p,%p,0x%08lx,0x%08lx) partial stub\n",
+		FileHandle, DesiredAccess, ObjectAttributes,
+		IoStatusBlock, ShareAccess, OpenOptions);
+
 	dump_ObjectAttributes (ObjectAttributes);
-	return 0;
+
+	if(ObjectAttributes->RootDirectory)
+	{
+		FIXME("Object root directory unknown %x\n",
+			ObjectAttributes->RootDirectory);
+		return STATUS_OBJECT_NAME_NOT_FOUND;
+	}
+
+	/* create an ascii string from the unicode filename */
+	RtlUnicodeToMultiByteSize( &len, ObjectAttributes->ObjectName->Buffer, 
+				ObjectAttributes->ObjectName->Length );
+	filename = RtlAllocateHeap( GetProcessHeap(), 0, len + 1);
+	RtlUnicodeToMultiByteN(filename, len, NULL, ObjectAttributes->ObjectName->Buffer,
+				ObjectAttributes->ObjectName->Length );
+	filename[len]=0;
+
+	/* FIXME: DOSFS stuff should call here, not vice-versa */
+	if(strncmp(filename, szDosDevices, strlen(szDosDevices)))
+		return STATUS_OBJECT_NAME_NOT_FOUND;
+
+	/* FIXME: this calls SetLastError() -> bad */
+	if(!DOSFS_GetFullName(&filename[strlen(szDosDevices)], TRUE,
+				&full_name))
+		return STATUS_OBJECT_NAME_NOT_FOUND;
+
+	/* FIXME: modify server protocol so 
+                  create file takes an OBJECT_ATTRIBUTES structure */
+        SERVER_START_REQ( create_file )
+        {
+            req->access     = DesiredAccess;
+            req->inherit    = 0;
+            req->sharing    = ShareAccess;
+            req->create     = OPEN_EXISTING;
+            req->attrs      = 0;
+            req->drive_type = GetDriveTypeA( full_name.short_name );
+            wine_server_add_data( req, full_name.long_name, strlen(full_name.long_name) );
+            SetLastError(0);
+            r = wine_server_call( req );
+            *FileHandle = reply->handle;
+        }
+        SERVER_END_REQ;
+
+	return r;
 }
 
 /**************************************************************************
@@ -94,6 +155,34 @@
 	return 0;
 }
 
+/* set the last error depending on errno */
+NTSTATUS NTFILE_errno_to_status(int val)
+{
+    switch (val)
+    {
+    case EAGAIN:    return ( STATUS_SHARING_VIOLATION );
+    case ESPIPE:
+    case EBADF:     return ( STATUS_INVALID_HANDLE );
+    case ENOSPC:    return ( STATUS_DISK_FULL );
+    case EACCES:
+    case ESRCH:
+    case EPERM:     return ( STATUS_ACCESS_DENIED );
+    case EROFS:     return ( STATUS_MEDIA_WRITE_PROTECTED );
+    case EBUSY:     return ( STATUS_FILE_LOCK_CONFLICT );
+    case ENOENT:    return ( STATUS_NO_SUCH_FILE );
+    case EISDIR:    return ( STATUS_FILE_IS_A_DIRECTORY );
+    case ENFILE:
+    case EMFILE:    return ( STATUS_NO_MORE_FILES );
+    case EEXIST:    return ( STATUS_OBJECT_NAME_COLLISION );
+    case EINVAL:    return ( STATUS_INVALID_PARAMETER );
+    case ENOTEMPTY: return ( STATUS_DIRECTORY_NOT_EMPTY );
+    case EIO:       return ( STATUS_ACCESS_VIOLATION );
+    }
+    perror("file_set_error");
+    return ( STATUS_INVALID_PARAMETER );
+}
+
+
 /******************************************************************************
  *  NtReadFile					[NTDLL.@]
  *  ZwReadFile					[NTDLL.@]
@@ -108,8 +197,76 @@
  *   ULONG 		Length
  *   PLARGE_INTEGER 	ByteOffset 	OPTIONAL
  *   PULONG 		Key 		OPTIONAL
+ *
+ * IoStatusBlock->Information contains the number of bytes read on return.
  */
 NTSTATUS WINAPI NtReadFile (
+	HANDLE FileHandle,
+	HANDLE EventHandle,
+	PIO_APC_ROUTINE ApcRoutine,
+	PVOID ApcContext,
+	PIO_STATUS_BLOCK IoStatusBlock,
+	PVOID Buffer,
+	ULONG Length,
+	PLARGE_INTEGER ByteOffset,
+	PULONG Key)
+{
+	int fd, result, flags, ret;
+	enum fd_type type;
+
+	FIXME("(0x%08x,0x%08x,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
+		FileHandle,EventHandle,ApcRoutine,ApcContext,IoStatusBlock,Buffer,Length,ByteOffset,Key);
+
+	if (IsBadWritePtr( Buffer, Length ) || 
+	    IsBadWritePtr( IoStatusBlock, sizeof *IoStatusBlock) ||
+	    IsBadWritePtr( ByteOffset, sizeof *ByteOffset) )
+		return STATUS_ACCESS_VIOLATION;
+
+	IoStatusBlock->Information = 0;
+
+	ret = wine_server_handle_to_fd( FileHandle, GENERIC_READ, &fd, &type, &flags );
+	if(ret)
+		return ret;
+
+	/* FIXME: this code only does synchronous reads so far */
+
+	/* FIXME: depending on how libc implements this, between two processes
+	      there could be a race condition between the seek and read here */
+	do
+	{
+               	result = pread( fd, Buffer, Length, ByteOffset->QuadPart);
+	}
+	while ( (result == -1) && ((errno == EAGAIN) || (errno == EINTR)) );
+
+	close( fd );
+
+	if (result == -1)
+	{
+		return IoStatusBlock->u.Status = NTFILE_errno_to_status(errno);
+	}
+
+	IoStatusBlock->Information = result;
+	IoStatusBlock->u.Status = 0;
+
+	return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ *  NtWriteFile					[NTDLL.@]
+ *  ZwWriteFile					[NTDLL.@]
+ *
+ * Parameters
+ *   HANDLE32 		FileHandle
+ *   HANDLE32 		Event 		OPTIONAL
+ *   PIO_APC_ROUTINE 	ApcRoutine 	OPTIONAL
+ *   PVOID 		ApcContext 	OPTIONAL
+ *   PIO_STATUS_BLOCK 	IoStatusBlock
+ *   PVOID 		Buffer
+ *   ULONG 		Length
+ *   PLARGE_INTEGER 	ByteOffset 	OPTIONAL
+ *   PULONG 		Key 		OPTIONAL
+ */
+NTSTATUS WINAPI NtWriteFile (
 	HANDLE FileHandle,
 	HANDLE EventHandle,
 	PIO_APC_ROUTINE ApcRoutine,


More information about the wine-patches mailing list