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
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,