summaryrefslogtreecommitdiffstats
path: root/src/VBox/Runtime/nt
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/Runtime/nt
parentInitial commit. (diff)
downloadvirtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz
virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/VBox/Runtime/nt/Makefile.kup0
-rw-r--r--src/VBox/Runtime/nt/NtProcessStartup-stub.cpp40
-rw-r--r--src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp107
-rw-r--r--src/VBox/Runtime/nt/RTNtPathExpand8dot3Path.cpp196
-rw-r--r--src/VBox/Runtime/nt/RTNtPathFindPossible8dot3Name.cpp72
-rw-r--r--src/VBox/Runtime/nt/fileioutils-nt.cpp179
6 files changed, 594 insertions, 0 deletions
diff --git a/src/VBox/Runtime/nt/Makefile.kup b/src/VBox/Runtime/nt/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Runtime/nt/Makefile.kup
diff --git a/src/VBox/Runtime/nt/NtProcessStartup-stub.cpp b/src/VBox/Runtime/nt/NtProcessStartup-stub.cpp
new file mode 100644
index 00000000..3032c420
--- /dev/null
+++ b/src/VBox/Runtime/nt/NtProcessStartup-stub.cpp
@@ -0,0 +1,40 @@
+/* $Id: NtProcessStartup-stub.cpp $ */
+/** @file
+ * IPRT - NtProcessStartup stub to make the link happy.
+ */
+
+/*
+ * Copyright (C) 2009-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <iprt/asm.h>
+
+
+extern "C" void __cdecl NtProcessStartup(void *pvIgnored);
+extern "C" void __cdecl NtProcessStartup(void *pvIgnored)
+{
+ ASMBreakpoint();
+ NOREF(pvIgnored);
+}
+
diff --git a/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp b/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp
new file mode 100644
index 00000000..c844de08
--- /dev/null
+++ b/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp
@@ -0,0 +1,107 @@
+/* $Id: RTErrConvertFromNtStatus.cpp $ */
+/** @file
+ * IPRT - Convert NT status codes to iprt status codes.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <ntstatus.h>
+typedef long NTSTATUS; /** @todo figure out which headers to include to get this one typedef... */
+
+#include <iprt/err.h>
+#ifdef VBOX
+# include <VBox/err.h>
+#endif
+#include <iprt/log.h>
+#include <iprt/assert.h>
+
+
+
+RTDECL(int) RTErrConvertFromNtStatus(long lNativeCode)
+{
+ switch (lNativeCode)
+ {
+ case STATUS_SUCCESS: return VINF_SUCCESS;
+
+ case STATUS_ALERTED: return VERR_INTERRUPTED;
+ case STATUS_USER_APC: return VERR_INTERRUPTED;
+
+ case STATUS_INVALID_INFO_CLASS: return VERR_INVALID_FUNCTION;
+ case STATUS_DATATYPE_MISALIGNMENT: return VERR_INVALID_POINTER;
+ case STATUS_NO_MORE_FILES: return VERR_NO_MORE_FILES;
+ case STATUS_NO_MORE_ENTRIES: return VERR_NO_MORE_FILES;
+ case STATUS_NO_MEMORY: return VERR_NO_MEMORY;
+
+ case STATUS_INVALID_HANDLE: return VERR_INVALID_HANDLE;
+ case STATUS_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_1: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_2: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_3: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_4: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_5: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_6: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_7: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_8: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_9: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_10: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_11: return VERR_INVALID_PARAMETER;
+ case STATUS_INVALID_PARAMETER_12: return VERR_INVALID_PARAMETER;
+ case STATUS_NO_SUCH_DEVICE: return VERR_FILE_NOT_FOUND;
+ case STATUS_NO_SUCH_FILE: return VERR_FILE_NOT_FOUND;
+ case STATUS_INVALID_DEVICE_REQUEST: return VERR_IO_BAD_COMMAND;
+ case STATUS_ACCESS_DENIED: return VERR_ACCESS_DENIED;
+ case STATUS_OBJECT_TYPE_MISMATCH: return VERR_UNEXPECTED_FS_OBJ_TYPE;
+ case STATUS_OBJECT_NAME_INVALID: return VERR_INVALID_NAME;
+ case STATUS_OBJECT_NAME_NOT_FOUND: return VERR_FILE_NOT_FOUND;
+ case STATUS_OBJECT_PATH_INVALID: return VERR_INVALID_NAME;
+ case STATUS_OBJECT_PATH_NOT_FOUND: return VERR_PATH_NOT_FOUND;
+ case STATUS_OBJECT_PATH_SYNTAX_BAD: return VERR_INVALID_NAME;
+ case STATUS_BAD_NETWORK_PATH: return VERR_NET_PATH_NOT_FOUND;
+ case STATUS_NOT_A_DIRECTORY: return VERR_NOT_A_DIRECTORY;
+ case STATUS_DIRECTORY_NOT_EMPTY: return VERR_DIR_NOT_EMPTY;
+ case STATUS_SHARING_VIOLATION: return VERR_SHARING_VIOLATION;
+ case STATUS_NO_MEDIA_IN_DEVICE: return VERR_DRIVE_IS_EMPTY;
+
+ case STATUS_REPARSE_POINT_NOT_RESOLVED:
+ return VERR_TOO_MANY_SYMLINKS;
+ case STATUS_UNEXPECTED_NETWORK_ERROR:
+ return VERR_NET_IO_ERROR;
+ case STATUS_INVALID_IMAGE_HASH: return VERR_LDR_IMAGE_HASH;
+#ifdef VBOX
+ case STATUS_TRUST_FAILURE: return VERR_SUPLIB_NT_PROCESS_UNTRUSTED_5;
+#endif
+ }
+
+ /* unknown error. */
+#ifndef IN_SUP_HARDENED_R3
+ AssertLogRelMsgFailed(("Unhandled error %#lx (%lu)\n", lNativeCode, lNativeCode));
+#else
+ /* hardened main has no LogRel */
+ AssertMsgFailed(("Unhandled error %#lx (%lu)\n", lNativeCode, lNativeCode));
+#endif
+ return VERR_UNRESOLVED_ERROR;
+}
+
diff --git a/src/VBox/Runtime/nt/RTNtPathExpand8dot3Path.cpp b/src/VBox/Runtime/nt/RTNtPathExpand8dot3Path.cpp
new file mode 100644
index 00000000..0e865f4d
--- /dev/null
+++ b/src/VBox/Runtime/nt/RTNtPathExpand8dot3Path.cpp
@@ -0,0 +1,196 @@
+/* $Id: RTNtPathExpand8dot3Path.cpp $ */
+/** @file
+ * IPRT - Native NT, RTNtPathExpand8dot3Path.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_FS
+#ifdef IN_SUP_HARDENED_R3
+# include <iprt/nt/nt-and-windows.h>
+#else
+# include <iprt/nt/nt.h>
+#endif
+
+#include <iprt/mem.h>
+#include <iprt/errcore.h>
+#include <iprt/string.h>
+
+
+
+/**
+ * Fixes up a path possibly containing one or more alternative 8-dot-3 style
+ * components.
+ *
+ * The path is fixed up in place. Errors are ignored.
+ *
+ * @returns VINF_SUCCESS if it all went smoothly, informational status codes
+ * indicating the nature of last problem we ran into.
+ *
+ * @param pUniStr The path to fix up. MaximumLength is the max buffer
+ * length.
+ * @param fPathOnly Whether to only process the path and leave the filename
+ * as passed in.
+ */
+RTDECL(int) RTNtPathExpand8dot3Path(PUNICODE_STRING pUniStr, bool fPathOnly)
+{
+ int rc = VINF_SUCCESS;
+
+ /*
+ * We could use FileNormalizedNameInformation here and slap the volume device
+ * path in front of the result, but it's only supported since windows 8.0
+ * according to some docs... So we expand all supicious names.
+ */
+ union fix8dot3tmp
+ {
+ FILE_BOTH_DIR_INFORMATION Info;
+ uint8_t abBuffer[sizeof(FILE_BOTH_DIR_INFORMATION) + 2048 * sizeof(WCHAR)];
+ } *puBuf = NULL;
+
+
+ PRTUTF16 pwszFix = pUniStr->Buffer;
+ while (*pwszFix)
+ {
+ pwszFix = RTNtPathFindPossible8dot3Name(pwszFix);
+ if (pwszFix == NULL)
+ break;
+
+ RTUTF16 wc;
+ PRTUTF16 pwszFixEnd = pwszFix;
+ while ((wc = *pwszFixEnd) != '\0' && wc != '\\' && wc != '/')
+ pwszFixEnd++;
+ if (wc == '\0' && fPathOnly)
+ break;
+
+ if (!puBuf)
+ {
+ puBuf = (union fix8dot3tmp *)RTMemAlloc(sizeof(*puBuf));
+ if (!puBuf)
+ {
+ rc = -VERR_NO_MEMORY;
+ break;
+ }
+ }
+
+ RTUTF16 const wcSaved = *pwszFix;
+ *pwszFix = '\0'; /* paranoia. */
+
+ UNICODE_STRING NtDir;
+ NtDir.Buffer = pUniStr->Buffer;
+ NtDir.Length = NtDir.MaximumLength = (USHORT)((pwszFix - pUniStr->Buffer) * sizeof(WCHAR));
+
+ HANDLE hDir = RTNT_INVALID_HANDLE_VALUE;
+ IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
+
+ OBJECT_ATTRIBUTES ObjAttr;
+ InitializeObjectAttributes(&ObjAttr, &NtDir, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
+#ifdef IN_RING0
+ ObjAttr.Attributes |= OBJ_KERNEL_HANDLE;
+#endif
+
+ NTSTATUS rcNt = NtCreateFile(&hDir,
+ FILE_LIST_DIRECTORY | SYNCHRONIZE,
+ &ObjAttr,
+ &Ios,
+ NULL /* Allocation Size*/,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_OPEN,
+ FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL /*EaBuffer*/,
+ 0 /*EaLength*/);
+ *pwszFix = wcSaved;
+ if (NT_SUCCESS(rcNt))
+ {
+ RT_ZERO(*puBuf);
+
+ IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
+ UNICODE_STRING NtFilterStr;
+ NtFilterStr.Buffer = pwszFix;
+ NtFilterStr.Length = (USHORT)((uintptr_t)pwszFixEnd - (uintptr_t)pwszFix);
+ NtFilterStr.MaximumLength = NtFilterStr.Length;
+ rcNt = NtQueryDirectoryFile(hDir,
+ NULL /* Event */,
+ NULL /* ApcRoutine */,
+ NULL /* ApcContext */,
+ &Ios,
+ puBuf,
+ sizeof(*puBuf) - sizeof(WCHAR),
+ FileBothDirectoryInformation,
+ FALSE /*ReturnSingleEntry*/,
+ &NtFilterStr,
+ FALSE /*RestartScan */);
+ if (NT_SUCCESS(rcNt) && puBuf->Info.NextEntryOffset == 0) /* There shall only be one entry matching... */
+ {
+ uint32_t offName = puBuf->Info.FileNameLength / sizeof(WCHAR);
+ while (offName > 0 && puBuf->Info.FileName[offName - 1] != '\\' && puBuf->Info.FileName[offName - 1] != '/')
+ offName--;
+ uint32_t cwcNameNew = (puBuf->Info.FileNameLength / sizeof(WCHAR)) - offName;
+ uint32_t cwcNameOld = (uint32_t)(pwszFixEnd - pwszFix);
+
+ if (cwcNameOld == cwcNameNew)
+ memcpy(pwszFix, &puBuf->Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
+ else if ( pUniStr->Length + cwcNameNew * sizeof(WCHAR) - cwcNameOld * sizeof(WCHAR) + sizeof(WCHAR)
+ <= pUniStr->MaximumLength)
+ {
+ size_t cwcLeft = pUniStr->Length - (pwszFixEnd - pUniStr->Buffer) * sizeof(WCHAR) + sizeof(WCHAR);
+ memmove(&pwszFix[cwcNameNew], pwszFixEnd, cwcLeft * sizeof(WCHAR));
+ pUniStr->Length -= (USHORT)(cwcNameOld * sizeof(WCHAR));
+ pUniStr->Length += (USHORT)(cwcNameNew * sizeof(WCHAR));
+ pwszFixEnd -= cwcNameOld;
+ pwszFixEnd += cwcNameNew;
+ memcpy(pwszFix, &puBuf->Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
+ }
+ else
+ rc = VINF_BUFFER_OVERFLOW;
+ }
+ else if (NT_SUCCESS(rcNt))
+ rc = -VERR_DUPLICATE;
+ else
+ {
+ rc = -RTErrConvertFromNtStatus(rcNt);
+ if (rc < 0)
+ rc = -rc;
+ }
+
+ NtClose(hDir);
+ }
+ else
+ rc = -RTErrConvertFromNtStatus(rcNt);
+
+ /* Advance */
+ pwszFix = pwszFixEnd;
+ }
+
+ if (puBuf)
+ RTMemFree(puBuf);
+
+ if (pUniStr->Length < pUniStr->MaximumLength)
+ pUniStr->Buffer[pUniStr->Length / sizeof(WCHAR)] = '\0';
+
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/nt/RTNtPathFindPossible8dot3Name.cpp b/src/VBox/Runtime/nt/RTNtPathFindPossible8dot3Name.cpp
new file mode 100644
index 00000000..9f915c90
--- /dev/null
+++ b/src/VBox/Runtime/nt/RTNtPathFindPossible8dot3Name.cpp
@@ -0,0 +1,72 @@
+/* $Id: RTNtPathFindPossible8dot3Name.cpp $ */
+/** @file
+ * IPRT - Native NT, RTNtPathFindPossible8dot3Name.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_FS
+#ifdef IN_SUP_HARDENED_R3
+# include <iprt/nt/nt-and-windows.h>
+#else
+# include <iprt/nt/nt.h>
+#endif
+
+
+
+/**
+ * Checks whether the path could be containing alternative 8.3 names generated
+ * by NTFS, FAT, or other similar file systems.
+ *
+ * @returns Pointer to the first component that might be an 8.3 name, NULL if
+ * not 8.3 path.
+ * @param pwszPath The path to check.
+ *
+ * @remarks This is making bad ASSUMPTION wrt to the naming scheme of 8.3 names,
+ * however, non-tilde 8.3 aliases are probably rare enough to not be
+ * worth all the extra code necessary to open each path component and
+ * check if we've got the short name or not.
+ */
+RTDECL(PRTUTF16) RTNtPathFindPossible8dot3Name(PCRTUTF16 pwszPath)
+{
+ PCRTUTF16 pwszName = pwszPath;
+ for (;;)
+ {
+ RTUTF16 wc = *pwszPath++;
+ if (wc == '~')
+ {
+ /* Could check more here before jumping to conclusions... */
+ if (pwszPath - pwszName <= 8+1+3)
+ return (PRTUTF16)pwszName;
+ }
+ else if (wc == '\\' || wc == '/' || wc == ':')
+ pwszName = pwszPath;
+ else if (wc == 0)
+ break;
+ }
+ return NULL;
+}
+
diff --git a/src/VBox/Runtime/nt/fileioutils-nt.cpp b/src/VBox/Runtime/nt/fileioutils-nt.cpp
new file mode 100644
index 00000000..43eb395f
--- /dev/null
+++ b/src/VBox/Runtime/nt/fileioutils-nt.cpp
@@ -0,0 +1,179 @@
+/* $Id: fileioutils-nt.cpp $ */
+/** @file
+ * IPRT - File I/O, common NT helpers.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <iprt/nt/nt.h>
+#include "internal/iprt.h"
+
+#include <iprt/errcore.h>
+#include "internal/file.h"
+
+
+
+/**
+ * Helper for converting RTFILE_O_XXX to the various NtCreateFile flags.
+ *
+ * @returns IPRT status code
+ * @param fOpen The RTFILE_O_XXX flags to convert.
+ * @param pfDesiredAccess Where to return the desired access mask.
+ * @param pfObjAttribs Where to return the NT object attributes.
+ * @param pfFileAttribs Where to return the file attributes (create).
+ * @param pfShareAccess Where to return the file sharing access mask.
+ * @param pfCreateDisposition Where to return the file create disposition.
+ * @param pfCreateOptions Where to return the file open/create options.
+ */
+DECLHIDDEN(int) rtFileNtValidateAndConvertFlags(uint64_t fOpen, uint32_t *pfDesiredAccess, uint32_t *pfObjAttribs,
+ uint32_t *pfFileAttribs, uint32_t *pfShareAccess, uint32_t *pfCreateDisposition,
+ uint32_t *pfCreateOptions)
+{
+ /*
+ * Merge forced open flags and validate them.
+ */
+ int rc = rtFileRecalcAndValidateFlags(&fOpen);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Determine disposition, access, share mode, creation flags, and security attributes
+ * for the CreateFile API call.
+ */
+ ULONG fCreateDisposition;
+ switch (fOpen & RTFILE_O_ACTION_MASK)
+ {
+ case RTFILE_O_OPEN:
+ fCreateDisposition = fOpen & RTFILE_O_TRUNCATE ? FILE_OVERWRITE : FILE_OPEN;
+ break;
+ case RTFILE_O_OPEN_CREATE:
+ fCreateDisposition = FILE_OPEN_IF;
+ break;
+ case RTFILE_O_CREATE:
+ fCreateDisposition = FILE_CREATE;
+ break;
+ case RTFILE_O_CREATE_REPLACE:
+ fCreateDisposition = FILE_SUPERSEDE;
+ break;
+ default:
+ AssertMsgFailed(("Impossible fOpen=%#llx\n", fOpen));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ ACCESS_MASK fDesiredAccess;
+ switch (fOpen & RTFILE_O_ACCESS_MASK)
+ {
+ case RTFILE_O_READ:
+ fDesiredAccess = FILE_GENERIC_READ; /* RTFILE_O_APPEND is ignored. */
+ break;
+ case RTFILE_O_WRITE:
+ fDesiredAccess = fOpen & RTFILE_O_APPEND
+ ? FILE_GENERIC_WRITE & ~FILE_WRITE_DATA
+ : FILE_GENERIC_WRITE;
+ break;
+ case RTFILE_O_READWRITE:
+ fDesiredAccess = fOpen & RTFILE_O_APPEND
+ ? FILE_GENERIC_READ | (FILE_GENERIC_WRITE & ~FILE_WRITE_DATA)
+ : FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+ break;
+ case RTFILE_O_ATTR_ONLY:
+ if (fOpen & RTFILE_O_ACCESS_ATTR_MASK)
+ {
+ fDesiredAccess = 0;
+ break;
+ }
+ RT_FALL_THRU();
+ default:
+ AssertMsgFailed(("Impossible fOpen=%#llx\n", fOpen));
+ return VERR_INVALID_PARAMETER;
+ }
+ if (fCreateDisposition == FILE_OVERWRITE)
+ /* Required for truncating the file (see MSDN), it is *NOT* part of FILE_GENERIC_WRITE. */
+ fDesiredAccess |= GENERIC_WRITE;
+
+ /* RTFileSetMode needs following rights as well. */
+ switch (fOpen & RTFILE_O_ACCESS_ATTR_MASK)
+ {
+ case RTFILE_O_ACCESS_ATTR_READ: fDesiredAccess |= FILE_READ_ATTRIBUTES | SYNCHRONIZE; break;
+ case RTFILE_O_ACCESS_ATTR_WRITE: fDesiredAccess |= FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break;
+ case RTFILE_O_ACCESS_ATTR_READWRITE: fDesiredAccess |= FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break;
+ default:
+ /* Attributes access is the same as the file access. */
+ switch (fOpen & RTFILE_O_ACCESS_MASK)
+ {
+ case RTFILE_O_READ: fDesiredAccess |= FILE_READ_ATTRIBUTES | SYNCHRONIZE; break;
+ case RTFILE_O_WRITE: fDesiredAccess |= FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break;
+ case RTFILE_O_READWRITE: fDesiredAccess |= FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE; break;
+ default:
+ AssertMsgFailed(("Impossible fOpen=%#llx\n", fOpen));
+ return VERR_INVALID_PARAMETER;
+ }
+ }
+
+ ULONG fShareAccess;
+ switch (fOpen & RTFILE_O_DENY_MASK)
+ {
+ case RTFILE_O_DENY_NONE: fShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; break;
+ case RTFILE_O_DENY_READ: fShareAccess = FILE_SHARE_WRITE; break;
+ case RTFILE_O_DENY_WRITE: fShareAccess = FILE_SHARE_READ; break;
+ case RTFILE_O_DENY_READWRITE: fShareAccess = 0; break;
+
+ case RTFILE_O_DENY_NOT_DELETE: fShareAccess = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; break;
+ case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READ: fShareAccess = FILE_SHARE_DELETE | FILE_SHARE_WRITE; break;
+ case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_WRITE: fShareAccess = FILE_SHARE_DELETE | FILE_SHARE_READ; break;
+ case RTFILE_O_DENY_NOT_DELETE | RTFILE_O_DENY_READWRITE:fShareAccess = FILE_SHARE_DELETE; break;
+ default:
+ AssertMsgFailed(("Impossible fOpen=%#llx\n", fOpen));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ ULONG fObjAttribs = 0;
+ if (fOpen & RTFILE_O_INHERIT)
+ fObjAttribs = OBJ_INHERIT;
+
+ ULONG fCreateOptions = FILE_NON_DIRECTORY_FILE;
+ if (fOpen & RTFILE_O_WRITE_THROUGH)
+ fCreateOptions |= FILE_WRITE_THROUGH;
+ if (!(fOpen & RTFILE_O_ASYNC_IO))
+ fCreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT;
+ if (fOpen & RTFILE_O_NO_CACHE)
+ {
+ fCreateOptions |= FILE_NO_INTERMEDIATE_BUFFERING;
+ fDesiredAccess &= ~FILE_APPEND_DATA;
+ }
+
+ /*
+ * Done.
+ */
+ *pfDesiredAccess = fDesiredAccess;
+ *pfObjAttribs = fObjAttribs;
+ *pfFileAttribs = FILE_ATTRIBUTE_NORMAL;
+ *pfShareAccess = fShareAccess;
+ *pfCreateDisposition = fCreateDisposition;
+ *pfCreateOptions = fCreateOptions;
+ return VINF_SUCCESS;
+}
+