VirtualBox

source: vbox/trunk/src/VBox/Runtime/nt/RTNtPathExpand8dot3Path.cpp@ 77816

Last change on this file since 77816 was 77816, checked in by vboxsync, 6 years ago

SupHardNt: Made RTNtPathExpand8dot3Path() work correctly in kernel context (needs IPRT_NT_MAP_TO_ZW) and expand 8.3 names when comparing the executable image we found in the memory map with what NT returns for the process.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.7 KB
Line 
1/* $Id: RTNtPathExpand8dot3Path.cpp 77816 2019-03-21 00:01:49Z vboxsync $ */
2/** @file
3 * IPRT - Native NT, RTNtPathExpand8dot3Path.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_FS
32#if !defined(IPRT_NT_MAP_TO_ZW) && defined(IN_RING0)
33# define IPRT_NT_MAP_TO_ZW
34#endif
35#ifdef IN_SUP_HARDENED_R3
36# include <iprt/nt/nt-and-windows.h>
37#else
38# include <iprt/nt/nt.h>
39#endif
40
41#include <iprt/mem.h>
42#include <iprt/errcore.h>
43#include <iprt/string.h>
44
45
46
47/**
48 * Fixes up a path possibly containing one or more alternative 8-dot-3 style
49 * components.
50 *
51 * The path is fixed up in place. Errors are ignored.
52 *
53 * @returns VINF_SUCCESS if it all went smoothly, informational status codes
54 * indicating the nature of last problem we ran into.
55 *
56 * @param pUniStr The path to fix up. MaximumLength is the max buffer
57 * length.
58 * @param fPathOnly Whether to only process the path and leave the filename
59 * as passed in.
60 */
61RTDECL(int) RTNtPathExpand8dot3Path(PUNICODE_STRING pUniStr, bool fPathOnly)
62{
63 int rc = VINF_SUCCESS;
64
65 /*
66 * We could use FileNormalizedNameInformation here and slap the volume device
67 * path in front of the result, but it's only supported since windows 8.0
68 * according to some docs... So we expand all supicious names.
69 */
70 union fix8dot3tmp
71 {
72 FILE_BOTH_DIR_INFORMATION Info;
73 uint8_t abBuffer[sizeof(FILE_BOTH_DIR_INFORMATION) + 2048 * sizeof(WCHAR)];
74 } *puBuf = NULL;
75
76
77 PRTUTF16 pwszFix = pUniStr->Buffer;
78 while (*pwszFix)
79 {
80 pwszFix = RTNtPathFindPossible8dot3Name(pwszFix);
81 if (pwszFix == NULL)
82 break;
83
84 RTUTF16 wc;
85 PRTUTF16 pwszFixEnd = pwszFix;
86 while ((wc = *pwszFixEnd) != '\0' && wc != '\\' && wc != '/')
87 pwszFixEnd++;
88 if (wc == '\0' && fPathOnly)
89 break;
90
91 if (!puBuf)
92 {
93 puBuf = (union fix8dot3tmp *)RTMemAlloc(sizeof(*puBuf));
94 if (!puBuf)
95 {
96 rc = -VERR_NO_MEMORY;
97 break;
98 }
99 }
100
101 RTUTF16 const wcSaved = *pwszFix;
102 *pwszFix = '\0'; /* paranoia. */
103
104 UNICODE_STRING NtDir;
105 NtDir.Buffer = pUniStr->Buffer;
106 NtDir.Length = NtDir.MaximumLength = (USHORT)((pwszFix - pUniStr->Buffer) * sizeof(WCHAR));
107
108 HANDLE hDir = RTNT_INVALID_HANDLE_VALUE;
109 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
110
111 OBJECT_ATTRIBUTES ObjAttr;
112 InitializeObjectAttributes(&ObjAttr, &NtDir, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
113#ifdef IN_RING0
114 ObjAttr.Attributes |= OBJ_KERNEL_HANDLE;
115#endif
116
117 NTSTATUS rcNt = NtCreateFile(&hDir,
118 FILE_LIST_DIRECTORY | SYNCHRONIZE,
119 &ObjAttr,
120 &Ios,
121 NULL /* Allocation Size*/,
122 FILE_ATTRIBUTE_NORMAL,
123 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
124 FILE_OPEN,
125 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
126 NULL /*EaBuffer*/,
127 0 /*EaLength*/);
128 *pwszFix = wcSaved;
129 if (NT_SUCCESS(rcNt))
130 {
131 RT_ZERO(*puBuf);
132
133 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
134 UNICODE_STRING NtFilterStr;
135 NtFilterStr.Buffer = pwszFix;
136 NtFilterStr.Length = (USHORT)((uintptr_t)pwszFixEnd - (uintptr_t)pwszFix);
137 NtFilterStr.MaximumLength = NtFilterStr.Length;
138 rcNt = NtQueryDirectoryFile(hDir,
139 NULL /* Event */,
140 NULL /* ApcRoutine */,
141 NULL /* ApcContext */,
142 &Ios,
143 puBuf,
144 sizeof(*puBuf) - sizeof(WCHAR),
145 FileBothDirectoryInformation,
146 FALSE /*ReturnSingleEntry*/,
147 &NtFilterStr,
148 FALSE /*RestartScan */);
149 if (NT_SUCCESS(rcNt) && puBuf->Info.NextEntryOffset == 0) /* There shall only be one entry matching... */
150 {
151 uint32_t offName = puBuf->Info.FileNameLength / sizeof(WCHAR);
152 while (offName > 0 && puBuf->Info.FileName[offName - 1] != '\\' && puBuf->Info.FileName[offName - 1] != '/')
153 offName--;
154 uint32_t cwcNameNew = (puBuf->Info.FileNameLength / sizeof(WCHAR)) - offName;
155 uint32_t cwcNameOld = (uint32_t)(pwszFixEnd - pwszFix);
156
157 if (cwcNameOld == cwcNameNew)
158 memcpy(pwszFix, &puBuf->Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
159 else if ( pUniStr->Length + cwcNameNew * sizeof(WCHAR) - cwcNameOld * sizeof(WCHAR) + sizeof(WCHAR)
160 <= pUniStr->MaximumLength)
161 {
162 size_t cwcLeft = pUniStr->Length - (pwszFixEnd - pUniStr->Buffer) * sizeof(WCHAR) + sizeof(WCHAR);
163 memmove(&pwszFix[cwcNameNew], pwszFixEnd, cwcLeft * sizeof(WCHAR));
164 pUniStr->Length -= (USHORT)(cwcNameOld * sizeof(WCHAR));
165 pUniStr->Length += (USHORT)(cwcNameNew * sizeof(WCHAR));
166 pwszFixEnd -= cwcNameOld;
167 pwszFixEnd += cwcNameNew;
168 memcpy(pwszFix, &puBuf->Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
169 }
170 else
171 rc = VINF_BUFFER_OVERFLOW;
172 }
173 else if (NT_SUCCESS(rcNt))
174 rc = -VERR_DUPLICATE;
175 else
176 {
177 rc = -RTErrConvertFromNtStatus(rcNt);
178 if (rc < 0)
179 rc = -rc;
180 }
181
182 NtClose(hDir);
183 }
184 else
185 rc = -RTErrConvertFromNtStatus(rcNt);
186
187 /* Advance */
188 pwszFix = pwszFixEnd;
189 }
190
191 if (puBuf)
192 RTMemFree(puBuf);
193
194 if (pUniStr->Length < pUniStr->MaximumLength)
195 pUniStr->Buffer[pUniStr->Length / sizeof(WCHAR)] = '\0';
196
197 return rc;
198}
199
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette