5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * IPRT - Native NT, Internal Path stuff.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Copyright (C) 2006-2013 Oracle Corporation
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * available from http://www.virtualbox.org. This file is free software;
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * you can redistribute it and/or modify it under the terms of the GNU
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * General Public License (GPL) as published by the Free Software
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * The contents of this file may alternatively be used under the terms
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * of the Common Development and Distribution License Version 1.0
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * VirtualBox OSE distribution, in which case the provisions of the
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * CDDL are applicable instead of those of the GPL.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * You may elect to license modified versions of this file under the
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * terms and conditions of either the GPL or the CDDL or both.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync/*******************************************************************************
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync* Header Files *
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync*******************************************************************************/
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync/*******************************************************************************
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync* Global Variables *
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync*******************************************************************************/
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * Handles the pass thru case for UTF-8 input.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @returns IPRT status code.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param pNtName Where to return the NT name.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param phRootDir Where to return the root handle, if applicable.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param pszPath The UTF-8 path.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsyncstatic int rtNtPathFromWinUtf8PassThru(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync int rc = RTStrToUtf16Ex(pszPath + 1, RTSTR_MAX, &pwszPath, 0, &cwcLen);
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync pNtName->Length = (uint16_t)(cwcLen * sizeof(RTUTF16));
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync pNtName->MaximumLength = pNtName->Length + sizeof(RTUTF16);
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * Handles the pass thru case for UTF-16 input.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @returns IPRT status code.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @param pNtName Where to return the NT name.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @param phRootDir Stores NULL here, as we don't use it.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @param pwszWinPath The UTF-16 windows-style path.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @param cwcWinPath The length of the windows-style input path.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsyncstatic int rtNtPathFromWinUtf16PassThru(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir,
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync /* Drop a character because: \\?\ -> \.\ */
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync /* Check length and allocate memory for it. */
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync PRTUTF16 pwszNtPath = (PRTUTF16)RTUtf16Alloc((cwcWinPath + 1) * sizeof(RTUTF16));
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync /* Intialize the path. */
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync memcpy(pwszNtPath + 3, pwszWinPath + 3, (cwcWinPath - 3) * sizeof(RTUTF16));
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync /* Initialize the return values. */
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync pNtName->Length = (uint16_t)(cwcWinPath * sizeof(RTUTF16));
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync pNtName->MaximumLength = pNtName->Length + sizeof(RTUTF16);
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * Converts the path to UTF-16 and sets all the return values.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @returns IPRT status code.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param pNtName Where to return the NT name.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param phRootDir Where to return the root handle, if applicable.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param pszPath The UTF-8 path.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsyncstatic int rtNtPathUtf8ToUniStr(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync int rc = RTStrToUtf16Ex(pszPath, RTSTR_MAX, &pwszPath, 0, &cwcLen);
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync pNtName->Length = (uint16_t)(cwcLen * sizeof(RTUTF16));
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync pNtName->MaximumLength = pNtName->Length + sizeof(RTUTF16);
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Converts a path to NT format and encoding.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @returns IPRT status code.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param pNtName Where to return the NT name.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param phRootDir Where to return the root handle, if applicable.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param pszPath The UTF-8 path.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsyncstatic int rtNtPathToNative(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Very simple conversion of a win32-like path into an NT path.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync return rtNtPathFromWinUtf8PassThru(pNtName, phRootDir, pszPath);
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync /* Special hack: The path starts with "\\\\!\\", we will skip past the bang and pass it thru. */
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync return rtNtPathUtf8ToUniStr(pNtName, phRootDir, pszPath + 3);
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Device path.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Note! I suspect \\.\stuff\..\otherstuff may be handled differently by windows.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Straighten out all .. and uncessary . references and convert slashes.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync int rc = RTPathAbs(pszPath, &szPath[cchPrefix - cchSkip], sizeof(szPath) - (cchPrefix - cchSkip));
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Add prefix and convert it to UTF16.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync return rtNtPathUtf8ToUniStr(pNtName, phRootDir, szPath);
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * Converts a UTF-16 windows-style path to NT format.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @returns IPRT status code.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @param pNtName Where to return the NT name. Free using
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * RTNtPathFree.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @param phRootDir Where to return the root handle, if applicable.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @param pwszWinPath The UTF-16 windows-style path.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @param cwcWinPath The max length of the windows-style path in
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * RTUTF16 units. Use RTSTR_MAX if unknown and @a
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * pwszWinPath is correctly terminated.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsyncRTDECL(int) RTNtPathFromWinUtf16Ex(struct _UNICODE_STRING *pNtName, HANDLE *phRootDir, PCRTUTF16 pwszWinPath, size_t cwcWinPath)
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * Validate the input, calculating the correct length.
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync RTUtf16NLenEx(pwszWinPath, cwcWinPath, &cwcWinPath);
46b9d3cd08a855c5d0e968e4fff0e89dea3fc2dfvboxsync int rc = RTUtf16ValidateEncodingEx(pwszWinPath, cwcWinPath, 0);
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * Very simple conversion of a win32-like path into an NT path.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync return rtNtPathFromWinUtf16PassThru(pNtName, phRootDir, pwszWinPath, cwcWinPath);
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync /* Special hack: The path starts with "\\\\!\\", we will skip past the bang and pass it thru. */
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync PRTUTF16 pwszNtPath = RTUtf16Alloc((cwcWinPath + 1) * sizeof(RTUTF16));
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync memcpy(pwszNtPath, pwszWinPath, cwcWinPath * sizeof(RTUTF16));
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync pNtName->Length = (uint16_t)(cwcWinPath * sizeof(RTUTF16));
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync pNtName->MaximumLength = pNtName->Length + sizeof(RTUTF16);
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * Device path.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * Note! I suspect \\.\stuff\..\otherstuff may be handled differently by windows.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * Straighten out all .. and unnecessary . references and convert slashes.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync rc = RTUtf16ToUtf8Ex(pwszWinPath, cwcWinPath, &pszRelPath, sizeof(szRelPath), &cchRelPath);
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync rc = RTPathAbs(szRelPath, &szAbsPath[cchPrefix - cchSkip], sizeof(szAbsPath) - (cchPrefix - cchSkip));
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * Add prefix and convert it to UTF16.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync return rtNtPathUtf8ToUniStr(pNtName, phRootDir, szAbsPath);
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Frees the native path and root handle.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param pNtName The NT path after a successful rtNtPathToNative
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param phRootDir The root handle variable after a
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * rtNtPathToNative.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsyncstatic void rtNtPathFreeNative(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir)
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * Frees the native path and root handle.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @param pNtName The NT path after a successful
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * RTNtPathFromWinUtf16Ex call.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * @param phRootDir The root handle variable after a successfull
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsync * RTNtPathFromWinUtf16Ex call.
1eda04de692c4c416332941e87bab4cc8fc45a18vboxsyncRTDECL(void) RTNtPathFree(struct _UNICODE_STRING *pNtName, HANDLE *phRootDir)
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Wrapper around NtCreateFile.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @returns IPRT status code.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param pszPath The UTF-8 path.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param fDesiredAccess See NtCreateFile.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param fFileAttribs See NtCreateFile.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param fShareAccess See NtCreateFile.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param fCreateDisposition See NtCreateFile.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param fCreateOptions See NtCreateFile.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param fObjAttribs The OBJECT_ATTRIBUTES::Attributes value, see
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * NtCreateFile and InitializeObjectAttributes.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param phHandle Where to return the handle.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param puAction Where to return the action taken. Optional.
304e26e9a9c1422dbc299ed139eceacca271a9ddvboxsyncRTDECL(int) RTNtPathOpen(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,
304e26e9a9c1422dbc299ed139eceacca271a9ddvboxsync ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync int rc = rtNtPathToNative(&NtName, &hRootDir, pszPath);
304e26e9a9c1422dbc299ed139eceacca271a9ddvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync InitializeObjectAttributes(&ObjAttr, &NtName, fObjAttribs, hRootDir, NULL);
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync 0 /*EaLength*/);
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * Wrapper around NtCreateFile.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @returns IPRT status code.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param pszPath The UTF-8 path.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param fDesiredAccess See NtCreateFile.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param fFileAttribs See NtCreateFile.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param fShareAccess See NtCreateFile.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param fCreateDisposition See NtCreateFile.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param fCreateOptions See NtCreateFile.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param fObjAttribs The OBJECT_ATTRIBUTES::Attributes value, see
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * NtCreateFile and InitializeObjectAttributes.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param phHandle Where to return the handle.
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @param pfObjDir If not NULL, the variable pointed to will be set
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * to @c true if we opened an object directory and
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * @c false if we opened an directory file (normal
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync * directory).
304e26e9a9c1422dbc299ed139eceacca271a9ddvboxsyncRTDECL(int) RTNtPathOpenDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fShareAccess, ULONG fCreateOptions,
304e26e9a9c1422dbc299ed139eceacca271a9ddvboxsync ULONG fObjAttribs, PHANDLE phHandle, bool *pfObjDir)
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync int rc = rtNtPathToNative(&NtName, &hRootDir, pszPath);
304e26e9a9c1422dbc299ed139eceacca271a9ddvboxsync IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync InitializeObjectAttributes(&ObjAttr, &NtName, fObjAttribs, hRootDir, NULL);
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync 0 /*EaLength*/);
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync && (rcNt == STATUS_OBJECT_NAME_INVALID || rcNt == STATUS_OBJECT_TYPE_MISMATCH)
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync /* Strip trailing slash. */
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync && RTPATH_IS_SLASH(NtName.Buffer[(NtName.Length / 2) - 1]))
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync /* Rought conversion of the access flags. */
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync if (fDesiredAccess & (GENERIC_ALL | STANDARD_RIGHTS_ALL))
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync if (fDesiredAccess & (FILE_GENERIC_WRITE | GENERIC_WRITE | STANDARD_RIGHTS_WRITE))
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync fObjDesiredAccess |= DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_OBJECT;
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync if ( (fDesiredAccess & (FILE_LIST_DIRECTORY | FILE_GENERIC_READ | GENERIC_READ | STANDARD_RIGHTS_READ))
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync fObjDesiredAccess |= DIRECTORY_QUERY | FILE_LIST_DIRECTORY;
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync rcNt = NtOpenDirectoryObject(&hFile, fObjDesiredAccess, &ObjAttr);
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * Closes an handled open by rtNtPathOpen.
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @returns IPRT status code
5bf0ee311caa414469f26237ff607cb1b3591508vboxsync * @param hHandle The handle value.