fileio-win.cpp revision 87a7321dd85d8678d49ff924d8df0d2d1eb0cb6c
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * IPRT - File I/O, native implementation for the Windows host platform.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * available from http://www.virtualbox.org. This file is free software;
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * you can redistribute it and/or modify it under the terms of the GNU
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * General Public License (GPL) as published by the Free Software
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * The contents of this file may alternatively be used under the terms
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * of the Common Development and Distribution License Version 1.0
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * VirtualBox OSE distribution, in which case the provisions of the
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * CDDL are applicable instead of those of the GPL.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * You may elect to license modified versions of this file under the
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * terms and conditions of either the GPL or the CDDL or both.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * additional information or have any questions.
65d5d20a66da594035919d97e70ebf8f44bc8dbdvboxsync/*******************************************************************************
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync* Header Files *
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync*******************************************************************************/
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync/*******************************************************************************
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync* Defined Constants And Macros *
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync*******************************************************************************/
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync/** @def RT_DONT_CONVERT_FILENAMES
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * Define this to pass UTF-8 unconverted to the kernel. */
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * This is wrapper around the ugly SetFilePointer api.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * It's equivalent to SetFilePointerEx which we so unfortunately cannot use because of
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * it not being present in NT4 GA.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * @returns Success indicator. Extended error information obtainable using GetLastError().
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * @param File Filehandle.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * @param offSeek Offset to seek.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * @param poffNew Where to store the new file offset. NULL allowed.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * @param uMethod Seek method. (The windows one!)
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsyncDECLINLINE(bool) MySetFilePointer(RTFILE File, uint64_t offSeek, uint64_t *poffNew, unsigned uMethod)
65d5d20a66da594035919d97e70ebf8f44bc8dbdvboxsync off.LowPart = SetFilePointer((HANDLE)File, off.LowPart, &off.HighPart, uMethod);
65d5d20a66da594035919d97e70ebf8f44bc8dbdvboxsync off.LowPart = SetFilePointer((HANDLE)File, off.LowPart, &off.HighPart, uMethod);
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync fRc = SetFilePointerEx((HANDLE)File, off, &off, uMethod);
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * This is a helper to check if an attempt was made to grow a file beyond the
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * limit of the filesystem.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * @returns true for file size limit exceeded.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * @param File Filehandle.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * @param offSeek Offset to seek.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * @param uMethod The seek method.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsyncDECLINLINE(bool) IsBeyondLimit(RTFILE File, uint64_t offSeek, unsigned uMethod)
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * Get the current file position and try set the new one.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * If it fails with a seek error it's because we hit the file system limit.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync/** @todo r=bird: I'd be very interested to know on which versions of windows and on which file systems
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * this supposedly works. The fastfat sources in the latest WDK makes no limit checks during
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * file seeking, only at the time of writing (and some other odd ones we cannot make use of). */
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync if (MySetFilePointer(File, 0, &offCurrent, FILE_CURRENT))
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync if (!MySetFilePointer(File, offSeek, NULL, uMethod))
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync else /* Restore file pointer on success. */
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync MySetFilePointer(File, offCurrent, NULL, FILE_BEGIN);
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync bool fRc = false;
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * Convert to UTF-16.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * Query and check attributes.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync DWORD dwAttr = GetFileAttributesW((LPCWSTR)pwszString);
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync LogFlow(("RTFileExists(%p:{%s}): returns %RTbool\n", pszPath, pszPath, fRc));
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsyncRTR3DECL(int) RTFileFromNative(PRTFILE pFile, RTHCINTPTR uNative)
65d5d20a66da594035919d97e70ebf8f44bc8dbdvboxsync AssertReturn(File != NIL_RTFILE, (RTHCINTPTR)INVALID_HANDLE_VALUE);
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsyncRTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, unsigned fOpen)
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * Validate input.
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync * Merge forced open flags and validate them.
65d5d20a66da594035919d97e70ebf8f44bc8dbdvboxsync * Determine disposition, access, share mode, creation flags, and security attributes
65d5d20a66da594035919d97e70ebf8f44bc8dbdvboxsync * for the CreateFile API call.
65d5d20a66da594035919d97e70ebf8f44bc8dbdvboxsync dwCreationDisposition = fOpen & RTFILE_O_TRUNCATE ? TRUNCATE_EXISTING : OPEN_EXISTING;
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync AssertMsgFailed(("Impossible fOpen=%#x\n", fOpen));
65d5d20a66da594035919d97e70ebf8f44bc8dbdvboxsync dwDesiredAccess = FILE_GENERIC_READ; /* RTFILE_O_APPEND is ignored. */
65d5d20a66da594035919d97e70ebf8f44bc8dbdvboxsync ? FILE_GENERIC_READ | (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA)
65d5d20a66da594035919d97e70ebf8f44bc8dbdvboxsync AssertMsgFailed(("Impossible fOpen=%#x\n", fOpen));
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync /* RTFileSetMode needs following rights as well. */
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync case RTFILE_O_ACCESS_ATTR_READ: dwDesiredAccess |= FILE_READ_ATTRIBUTES | SYNCHRONIZE; break;
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync case RTFILE_O_ACCESS_ATTR_WRITE: dwDesiredAccess |= FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break;
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync case RTFILE_O_ACCESS_ATTR_READWRITE: dwDesiredAccess |= FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break;
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync /* Attributes access is the same as the file access. */
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync case RTFILE_O_READ: dwDesiredAccess |= FILE_READ_ATTRIBUTES | SYNCHRONIZE; break;
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync case RTFILE_O_WRITE: dwDesiredAccess |= FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break;
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync case RTFILE_O_READWRITE: dwDesiredAccess |= FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break;
d864e15f6de5312c6b93b67cfd1ae74f3c78134avboxsync AssertMsgFailed(("Impossible fOpen=%#x\n", fOpen));
case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_NONE: dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; break;
case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READ: dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_WRITE; break;
case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE: dwShareMode = FILE_SHARE_DELETE | FILE_SHARE_READ; break;
return VERR_INVALID_PARAMETER;
#ifdef RT_DONT_CONVERT_FILENAMES
NULL);
return rc;
NULL);
if ( fCreated
#ifdef RT_DONT_CONVERT_FILENAMES
else if ( !fCreated
#ifndef RT_DONT_CONVERT_FILENAMES
return VINF_SUCCESS;
#ifndef RT_DONT_CONVERT_FILENAMES
return rc;
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
if (cbToRead <= 0)
return VINF_SUCCESS;
if (pcbRead)
if (cbReadPart == 0)
return VERR_EOF;
return VINF_SUCCESS;
if (cbToWrite <= 0)
return VINF_SUCCESS;
if (pcbWritten)
if (!WriteFile((HANDLE)File, (char*)pvBuf + cbWritten, cbToWriteAdj - cbWritten, &cbWrittenPart, NULL))
return rc;
if (cbWrittenPart == 0)
return VERR_WRITE_ERROR;
return VINF_SUCCESS;
return rc;
int rc;
return VINF_SUCCESS;
int rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_NOT_IMPLEMENTED;
switch (dwType)
case FILE_TYPE_CHAR:
case FILE_TYPE_DISK:
case FILE_TYPE_PIPE:
case FILE_TYPE_REMOTE:
case FILE_TYPE_UNKNOWN:
return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
return VERR_INVALID_PARAMETER;
return rc;
return rc;
unsigned fLockOld = (fLock & RTFILE_LOCK_WRITE) ? fLock & ~RTFILE_LOCK_WRITE : fLock | RTFILE_LOCK_WRITE;
return VERR_FILE_LOCK_VIOLATION;
return VERR_FILE_LOCK_LOST;
if (UnlockFile((HANDLE)File, LOW_DWORD(offLock), HIGH_DWORD(offLock), LOW_DWORD(cbLock), HIGH_DWORD(cbLock)))
return VINF_SUCCESS;
RTR3DECL(int) RTFileQueryInfo(RTFILE File, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
return VERR_INVALID_PARAMETER;
if (!pObjInfo)
return VERR_INVALID_PARAMETER;
return VERR_INVALID_PARAMETER;
pObjInfo->Attr.fMode = rtFsModeFromDos((Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, "", 0);
switch (enmAdditionalAttribs)
case RTFSOBJATTRADD_EASIZE:
case RTFSOBJATTRADD_UNIX:
pObjInfo->Attr.u.Unix.INodeIdDevice = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */
case RTFSOBJATTRADD_NOTHING:
return VERR_INTERNAL_ERROR;
return VINF_SUCCESS;
if (pBirthTime)
if (pAccessTime)
if (pModificationTime)
return rc;
return VERR_INVALID_PARAMETER;
Log(("RTFileSetMode(%RTfile, %RTfmode): rtFileNativeSetAttributes (0x%08X) failed with err %d (%Rrc)\n",
return rc;
return VINF_SUCCESS;
#ifdef RT_DONT_CONVERT_FILENAMES
return VINF_SUCCESS;
return rc;
AssertMsgReturn(!(fRename & ~RTPATHRENAME_FLAGS_REPLACE), ("%#x\n", fRename), VERR_INVALID_PARAMETER);
return rc;
return rc;