VirtualBox

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

Last change on this file since 69496 was 69111, checked in by vboxsync, 7 years ago

(C) year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
Line 
1/* $Id: RTNtPathExpand8dot3Path.cpp 69111 2017-10-17 14:26:02Z vboxsync $ */
2/** @file
3 * IPRT - Native NT, RTNtPathExpand8dot3Path.
4 */
5
6/*
7 * Copyright (C) 2006-2017 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#ifdef IN_SUP_HARDENED_R3
33# include <iprt/nt/nt-and-windows.h>
34#else
35# include <iprt/nt/nt.h>
36#endif
37
38#include <iprt/mem.h>
39#include <iprt/string.h>
40
41
42
43/**
44 * Fixes up a path possibly containing one or more alternative 8-dot-3 style
45 * components.
46 *
47 * The path is fixed up in place. Errors are ignored.
48 *
49 * @returns VINF_SUCCESS if it all went smoothly, informational status codes
50 * indicating the nature of last problem we ran into.
51 *
52 * @param pUniStr The path to fix up. MaximumLength is the max buffer
53 * length.
54 * @param fPathOnly Whether to only process the path and leave the filename
55 * as passed in.
56 */
57RTDECL(int) RTNtPathExpand8dot3Path(PUNICODE_STRING pUniStr, bool fPathOnly)
58{
59 int rc = VINF_SUCCESS;
60
61 /*
62 * We could use FileNormalizedNameInformation here and slap the volume device
63 * path in front of the result, but it's only supported since windows 8.0
64 * according to some docs... So we expand all supicious names.
65 */
66 union fix8dot3tmp
67 {
68 FILE_BOTH_DIR_INFORMATION Info;
69 uint8_t abBuffer[sizeof(FILE_BOTH_DIR_INFORMATION) + 2048 * sizeof(WCHAR)];
70 } *puBuf = NULL;
71
72
73 PRTUTF16 pwszFix = pUniStr->Buffer;
74 while (*pwszFix)
75 {
76 pwszFix = RTNtPathFindPossible8dot3Name(pwszFix);
77 if (pwszFix == NULL)
78 break;
79
80 RTUTF16 wc;
81 PRTUTF16 pwszFixEnd = pwszFix;
82 while ((wc = *pwszFixEnd) != '\0' && wc != '\\' && wc != '/')
83 pwszFixEnd++;
84 if (wc == '\0' && fPathOnly)
85 break;
86
87 if (!puBuf)
88 {
89 puBuf = (union fix8dot3tmp *)RTMemAlloc(sizeof(*puBuf));
90 if (!puBuf)
91 {
92 rc = -VERR_NO_MEMORY;
93 break;
94 }
95 }
96
97 RTUTF16 const wcSaved = *pwszFix;
98 *pwszFix = '\0'; /* paranoia. */
99
100 UNICODE_STRING NtDir;
101 NtDir.Buffer = pUniStr->Buffer;
102 NtDir.Length = NtDir.MaximumLength = (USHORT)((pwszFix - pUniStr->Buffer) * sizeof(WCHAR));
103
104 HANDLE hDir = RTNT_INVALID_HANDLE_VALUE;
105 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
106
107 OBJECT_ATTRIBUTES ObjAttr;
108 InitializeObjectAttributes(&ObjAttr, &NtDir, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
109#ifdef IN_RING0
110 ObjAttr.Attributes |= OBJ_KERNEL_HANDLE;
111#endif
112
113 NTSTATUS rcNt = NtCreateFile(&hDir,
114 FILE_LIST_DIRECTORY | SYNCHRONIZE,
115 &ObjAttr,
116 &Ios,
117 NULL /* Allocation Size*/,
118 FILE_ATTRIBUTE_NORMAL,
119 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
120 FILE_OPEN,
121 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
122 NULL /*EaBuffer*/,
123 0 /*EaLength*/);
124 *pwszFix = wcSaved;
125 if (NT_SUCCESS(rcNt))
126 {
127 RT_ZERO(*puBuf);
128
129 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
130 UNICODE_STRING NtFilterStr;
131 NtFilterStr.Buffer = pwszFix;
132 NtFilterStr.Length = (USHORT)((uintptr_t)pwszFixEnd - (uintptr_t)pwszFix);
133 NtFilterStr.MaximumLength = NtFilterStr.Length;
134 rcNt = NtQueryDirectoryFile(hDir,
135 NULL /* Event */,
136 NULL /* ApcRoutine */,
137 NULL /* ApcContext */,
138 &Ios,
139 puBuf,
140 sizeof(*puBuf) - sizeof(WCHAR),
141 FileBothDirectoryInformation,
142 FALSE /*ReturnSingleEntry*/,
143 &NtFilterStr,
144 FALSE /*RestartScan */);
145 if (NT_SUCCESS(rcNt) && puBuf->Info.NextEntryOffset == 0) /* There shall only be one entry matching... */
146 {
147 uint32_t offName = puBuf->Info.FileNameLength / sizeof(WCHAR);
148 while (offName > 0 && puBuf->Info.FileName[offName - 1] != '\\' && puBuf->Info.FileName[offName - 1] != '/')
149 offName--;
150 uint32_t cwcNameNew = (puBuf->Info.FileNameLength / sizeof(WCHAR)) - offName;
151 uint32_t cwcNameOld = (uint32_t)(pwszFixEnd - pwszFix);
152
153 if (cwcNameOld == cwcNameNew)
154 memcpy(pwszFix, &puBuf->Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
155 else if ( pUniStr->Length + cwcNameNew * sizeof(WCHAR) - cwcNameOld * sizeof(WCHAR) + sizeof(WCHAR)
156 <= pUniStr->MaximumLength)
157 {
158 size_t cwcLeft = pUniStr->Length - (pwszFixEnd - pUniStr->Buffer) * sizeof(WCHAR) + sizeof(WCHAR);
159 memmove(&pwszFix[cwcNameNew], pwszFixEnd, cwcLeft * sizeof(WCHAR));
160 pUniStr->Length -= (USHORT)(cwcNameOld * sizeof(WCHAR));
161 pUniStr->Length += (USHORT)(cwcNameNew * sizeof(WCHAR));
162 pwszFixEnd -= cwcNameOld;
163 pwszFixEnd += cwcNameNew;
164 memcpy(pwszFix, &puBuf->Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
165 }
166 else
167 rc = VINF_BUFFER_OVERFLOW;
168 }
169 else if (NT_SUCCESS(rcNt))
170 rc = -VERR_DUPLICATE;
171 else
172 {
173 rc = -RTErrConvertFromNtStatus(rcNt);
174 if (rc < 0)
175 rc = -rc;
176 }
177
178 NtClose(hDir);
179 }
180 else
181 rc = -RTErrConvertFromNtStatus(rcNt);
182
183 /* Advance */
184 pwszFix = pwszFixEnd;
185 }
186
187 if (puBuf)
188 RTMemFree(puBuf);
189
190 if (pUniStr->Length < pUniStr->MaximumLength)
191 pUniStr->Buffer[pUniStr->Length / sizeof(WCHAR)] = '\0';
192
193 return rc;
194}
195
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