/* * Copyright 1999, 2000 Juergen Schmied * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "wine/port.h" #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_ERRNO_H #include #endif #define NONAMELESSUNION #define NONAMELESSSTRUCT #include "wine/unicode.h" #include "wine/debug.h" #include "wine/server.h" #include "ntdll_misc.h" #include "file.h" /* FIXME */ #include "winternl.h" #include "winioctl.h" WINE_DEFAULT_DEBUG_CHANNEL(ntdll); /************************************************************************** * NtOpenFile [NTDLL.@] * ZwOpenFile [NTDLL.@] * FUNCTION: Opens a file * ARGUMENTS: * FileHandle Variable that receives the file handle on return * DesiredAccess Access desired by the caller to the file * ObjectAttributes Structue describing the file to be opened * IoStatusBlock Receives details about the result of the operation * ShareAccess Type of shared access the caller requires * OpenOptions Options for the file open */ NTSTATUS WINAPI NtOpenFile( OUT PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions) { LPWSTR filename; static const WCHAR szDosDevices[] = {'\\','D','o','s','D','e','v','i','c','e','s','\\',0}; 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); if(ObjectAttributes->RootDirectory) { FIXME("Object root directory unknown %p\n", ObjectAttributes->RootDirectory); return STATUS_OBJECT_NAME_NOT_FOUND; } filename = ObjectAttributes->ObjectName->Buffer; /* FIXME: DOSFS stuff should call here, not vice-versa */ if(strncmpW(filename, szDosDevices, strlenW(szDosDevices))) return STATUS_OBJECT_NAME_NOT_FOUND; /* FIXME: this calls SetLastError() -> bad */ if(!DOSFS_GetFullName(&filename[strlenW(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 = GetDriveTypeW( 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; } /************************************************************************** * NtCreateFile [NTDLL.@] * ZwCreateFile [NTDLL.@] * FUNCTION: Either causes a new file or directory to be created, or it opens * an existing file, device, directory or volume, giving the caller a handle * for the file object. This handle can be used by subsequent calls to * manipulate data within the file or the file object's state of attributes. * ARGUMENTS: * FileHandle Points to a variable which receives the file handle on return * DesiredAccess Desired access to the file * ObjectAttributes Structure describing the file * IoStatusBlock Receives information about the operation on return * AllocationSize Initial size of the file in bytes * FileAttributes Attributes to create the file with * ShareAccess Type of shared access the caller would like to the file * CreateDisposition Specifies what to do, depending on whether the file already exists * CreateOptions Options for creating a new file * EaBuffer Undocumented * EaLength Undocumented */ NTSTATUS WINAPI NtCreateFile( OUT PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocateSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength) { FIXME("(%p,0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx) stub\n", FileHandle,DesiredAccess,ObjectAttributes, IoStatusBlock,AllocateSize,FileAttributes, ShareAccess,CreateDisposition,CreateOptions,EaBuffer,EaLength); dump_ObjectAttributes (ObjectAttributes); 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.@] * * 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 * * 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("(%p,%p,%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, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key) { FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%p),stub!\n", FileHandle,EventHandle,ApcRoutine,ApcContext,IoStatusBlock,Buffer,Length,ByteOffset,Key); return 0; } /************************************************************************** * NtDeviceIoControlFile [NTDLL.@] * ZwDeviceIoControlFile [NTDLL.@] */ NTSTATUS WINAPI NtDeviceIoControlFile( IN HANDLE DeviceHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, IN PVOID UserApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, OUT PVOID OutputBuffer, IN ULONG OutputBufferSize) { FIXME("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx): empty stub\n", DeviceHandle, Event, UserApcRoutine, UserApcContext, IoStatusBlock, IoControlCode, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize); return 0; } /****************************************************************************** * NtFsControlFile [NTDLL.@] * ZwFsControlFile [NTDLL.@] */ NTSTATUS WINAPI NtFsControlFile( IN HANDLE DeviceHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, OUT PVOID OutputBuffer, IN ULONG OutputBufferSize) { FIXME("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx): stub\n", DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,IoControlCode, InputBuffer,InputBufferSize,OutputBuffer,OutputBufferSize); return 0; } /****************************************************************************** * NtSetVolumeInformationFile [NTDLL.@] * ZwSetVolumeInformationFile [NTDLL.@] */ NTSTATUS WINAPI NtSetVolumeInformationFile( IN HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass) { FIXME("(%p,%p,%p,0x%08lx,0x%08x) stub\n", FileHandle,IoStatusBlock,FsInformation,Length,FsInformationClass); return 0; } /****************************************************************************** * NtQueryInformationFile [NTDLL.@] * ZwQueryInformationFile [NTDLL.@] */ NTSTATUS WINAPI NtQueryInformationFile( HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass) { FIXME("(%p,%p,%p,0x%08lx,0x%08x),stub!\n", FileHandle,IoStatusBlock,FileInformation,Length,FileInformationClass); return 0; } /****************************************************************************** * NtSetInformationFile [NTDLL.@] * ZwSetInformationFile [NTDLL.@] */ NTSTATUS WINAPI NtSetInformationFile( HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass) { FIXME("(%p,%p,%p,0x%08lx,0x%08x)\n", FileHandle,IoStatusBlock,FileInformation,Length,FileInformationClass); return 0; } /****************************************************************************** * NtQueryDirectoryFile [NTDLL.@] * ZwQueryDirectoryFile [NTDLL.@] * ZwQueryDirectoryFile */ NTSTATUS WINAPI NtQueryDirectoryFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass, IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan) { FIXME("(%p %p %p %p %p %p 0x%08lx 0x%08x 0x%08x %p 0x%08x\n", FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FileInformation, Length, FileInformationClass, ReturnSingleEntry, debugstr_us(FileName),RestartScan); return 0; } /****************************************************************************** * NtQueryVolumeInformationFile [NTDLL.@] * ZwQueryVolumeInformationFile [NTDLL.@] */ NTSTATUS WINAPI NtQueryVolumeInformationFile ( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FSInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FSInformationClass) { ULONG len = 0; FIXME("(%p %p %p 0x%08lx 0x%08x) stub!\n", FileHandle, IoStatusBlock, FSInformation, Length, FSInformationClass); switch ( FSInformationClass ) { case FileFsVolumeInformation: len = sizeof( FILE_FS_VOLUME_INFORMATION ); break; case FileFsLabelInformation: len = 0; break; case FileFsSizeInformation: len = sizeof( FILE_FS_SIZE_INFORMATION ); break; case FileFsDeviceInformation: len = sizeof( FILE_FS_DEVICE_INFORMATION ); break; case FileFsAttributeInformation: len = sizeof( FILE_FS_ATTRIBUTE_INFORMATION ); break; case FileFsControlInformation: len = 0; break; case FileFsFullSizeInformation: len = 0; break; case FileFsObjectIdInformation: len = 0; break; case FileFsMaximumInformation: len = 0; break; } if (Length < len) return STATUS_BUFFER_TOO_SMALL; switch ( FSInformationClass ) { case FileFsVolumeInformation: break; case FileFsLabelInformation: break; case FileFsSizeInformation: break; case FileFsDeviceInformation: if (FSInformation) { FILE_FS_DEVICE_INFORMATION * DeviceInfo = FSInformation; DeviceInfo->DeviceType = FILE_DEVICE_DISK; DeviceInfo->Characteristics = 0; break; }; case FileFsAttributeInformation: break; case FileFsControlInformation: break; case FileFsFullSizeInformation: break; case FileFsObjectIdInformation: break; case FileFsMaximumInformation: break; } IoStatusBlock->DUMMYUNIONNAME.Status = STATUS_SUCCESS; IoStatusBlock->Information = len; return STATUS_SUCCESS; } /****************************************************************** * NtFlushBuffersFile (NTDLL.@) */ NTSTATUS WINAPI NtFlushBuffersFile( HANDLE hFile, IO_STATUS_BLOCK* IoStatusBlock ) { NTSTATUS ret; SERVER_START_REQ( flush_file ) { req->handle = hFile; ret = wine_server_call( req ); } SERVER_END_REQ; return ret; }