VirtualBox

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

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

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