ReactOS 0.4.16-dev-1946-g52006dd
GetFinalPathNameByHandle.c File Reference
#include "k32_vista.h"
#include <winnls.h>
#include <mountmgr.h>
#include <debug.h>
Include dependency graph for GetFinalPathNameByHandle.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static NTSTATUS QueryDosVolumeNameForNtDeviceName (_In_ PCUNICODE_STRING DeviceName, _Inout_ PUNICODE_STRING DosVolumeName)
 
DWORD WINAPI GetFinalPathNameByHandleW (_In_ HANDLE hFile, _Out_writes_(cchFilePath) LPWSTR lpszFilePath, _In_ DWORD cchFilePath, _In_ DWORD dwFlags)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file GetFinalPathNameByHandle.c.

Function Documentation

◆ GetFinalPathNameByHandleW()

DWORD WINAPI GetFinalPathNameByHandleW ( _In_ HANDLE  hFile,
_Out_writes_(cchFilePath) LPWSTR  lpszFilePath,
_In_ DWORD  cchFilePath,
_In_ DWORD  dwFlags 
)

Definition at line 119 of file GetFinalPathNameByHandle.c.

124{
125 struct
126 {
127 union
128 {
131 };
133 } NameInfoBuffer;
134 PFILE_NAME_INFORMATION FileNameInfo = &NameInfoBuffer.File;
135 PUNICODE_STRING ObjectName = &NameInfoBuffer.Object.Name;
136 WCHAR VolumeBuffer[sizeof("\\Device\\Volume{01234567-89ab-cdef-0123-456789abcdef}")];
138 PWSTR PathSplit;
139 UNICODE_STRING DeviceName, RelativePath, VolumeName;
140 SIZE_T VolumeLength;
141 ULONG VolumeType;
143 ULONG FinalLength;
145
146 /* Extract the requested volume type */
148
149 /* Check if more than one volume type flag is set */
150 if (VolumeType & (VolumeType- 1))
151 {
152 DPRINT1("Invalid flags passed: %lx\n", dwFlags);
154 return 0;
155 }
156
157 /* Query the file name. This returns the relative path without volume.
158 This also validates that the handle refers to a file. */
161 &NameInfoBuffer,
162 sizeof(NameInfoBuffer),
164 if (!NT_SUCCESS(Status))
165 {
166 DPRINT1("NtQueryInformationFile failed: %lx\n", Status);
168 return 0;
169 }
170
171 /* If no volume was requested, return the relative path */
172 if (VolumeType == VOLUME_NAME_NONE)
173 {
174 FinalLength = FileNameInfo->FileNameLength / sizeof(WCHAR);
175 if (cchFilePath < FinalLength + 1)
176 {
178 return FinalLength + 1;
179 }
180
181 /* Copy the name to the caller's buffer */
182 RtlCopyMemory(lpszFilePath, FileNameInfo->FileName, FileNameInfo->FileNameLength);
183 lpszFilePath[FinalLength] = UNICODE_NULL;
184
185 /* Return the length of the name */
186 return FinalLength;
187 }
188
189 /* Query the NT object name */
192 &NameInfoBuffer,
193 sizeof(NameInfoBuffer) - sizeof(WCHAR),
194 NULL);
195 if (!NT_SUCCESS(Status))
196 {
197 DPRINT1("NtQueryObject failed: %lx\n", Status);
199 return 0;
200 }
201
202 /* If the NT path was requested, we return the name as it is */
203 if (VolumeType == VOLUME_NAME_NT)
204 {
205 /* Calculate the final length and validate the buffer size */
206 FinalLength = ObjectName->Length / sizeof(WCHAR);
207 if (cchFilePath < FinalLength + 1)
208 {
210 return FinalLength + 1;
211 }
212
213 /* Copy the name to the caller's buffer */
214 RtlCopyMemory(lpszFilePath, ObjectName->Buffer, ObjectName->Length);
215 lpszFilePath[ObjectName->Length / sizeof(WCHAR)] = UNICODE_NULL;
216
217 /* Return the length of the name */
218 return FinalLength;
219 }
220
221 /* For everything else we need to split the path */
222 PathSplit = wcschr(&ObjectName->Buffer[sizeof("\\Device\\") - 1], L'\\');
223 if (PathSplit == NULL)
224 {
225 DPRINT1("Invalid object name: %wZ\n", ObjectName);
227 return 0;
228 }
229
230 DeviceName.Buffer = ObjectName->Buffer;
231 DeviceName.Length = (USHORT)(PathSplit - ObjectName->Buffer) * sizeof(WCHAR);
232 DeviceName.MaximumLength = DeviceName.Length;
233
234 RelativePath.Buffer = PathSplit + 1;
235 RelativePath.Length = ObjectName->Length - DeviceName.Length - sizeof(WCHAR);
236 RelativePath.MaximumLength = RelativePath.Length;
237
238 /* Query the DOS volume name */
239 RtlInitEmptyUnicodeString(&VolumeName, VolumeBuffer, sizeof(VolumeBuffer));
241 if (!NT_SUCCESS(Status))
242 {
243 DPRINT1("QueryDosVolumeNameForNtDeviceName failed: %lx\n", Status);
245 return 0;
246 }
247
248 if (VolumeType == VOLUME_NAME_DOS)
249 {
250 /* Calculate the final length and validate the buffer size */
251 FinalLength = ((VolumeName.Length + RelativePath.Length) / sizeof(WCHAR));
252 if (cchFilePath < FinalLength + 1)
253 {
255 return FinalLength + 1;
256 }
257
258 /* Construct the final name */
260 RtlCopyMemory(lpszFilePath + (VolumeName.Length / sizeof(WCHAR)),
261 RelativePath.Buffer,
262 RelativePath.Length);
263 lpszFilePath[FinalLength] = UNICODE_NULL;
264
265 /* Return the length of the name */
266 return FinalLength;
267 }
268 else if (VolumeType == VOLUME_NAME_GUID)
269 {
270 /* Query the GUID volume name */
272 VolumeBuffer,
273 ARRAYSIZE(VolumeBuffer));
274 if (!Success)
275 {
276 DPRINT1("GetVolumeNameForVolumeMountPointW failed: %d\n", GetLastError());
278 return 0;
279 }
280
281 /* Calculate the final length and validate the buffer size */
282 VolumeLength = wcslen(VolumeBuffer);
283 FinalLength = VolumeLength + (RelativePath.Length / sizeof(WCHAR));
284 if (cchFilePath < FinalLength + 1)
285 {
287 return FinalLength + 1;
288 }
289
290 /* Construct the final name */
291 RtlCopyMemory(lpszFilePath, VolumeBuffer, VolumeLength * sizeof(WCHAR));
292 RtlCopyMemory(lpszFilePath + VolumeLength,
293 RelativePath.Buffer,
294 RelativePath.Length);
295 lpszFilePath[FinalLength] = UNICODE_NULL;
296
297 /* This is based on Windows behavior */
299
300 return FinalLength;
301 }
302
303 DPRINT1("Invalid flags passed: %lx\n", dwFlags);
305 return 0;
306}
@ ObjectNameInformation
Definition: DriverTester.h:55
NTSTATUS NtQueryObject(IN HANDLE Handle, IN OBJECT_INFO_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength)
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
Definition: File.h:16
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define wcschr
Definition: compat.h:17
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define MAX_PATH
Definition: compat.h:34
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
static NTSTATUS QueryDosVolumeNameForNtDeviceName(_In_ PCUNICODE_STRING DeviceName, _Inout_ PUNICODE_STRING DosVolumeName)
#define L(x)
Definition: resources.c:13
@ Success
Definition: eventcreate.c:712
unsigned int BOOL
Definition: ntddk_ex.h:94
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
@ FileNameInformation
Definition: from_kernel.h:70
Status
Definition: gdiplustypes.h:25
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
@ FileNameInfo
Definition: minwinbase.h:306
BOOL WINAPI GetVolumeNameForVolumeMountPointW(IN LPCWSTR VolumeMountPoint, OUT LPWSTR VolumeName, IN DWORD VolumeNameLength)
Definition: mntpoint.c:496
#define VOLUME_NAME_GUID
#define VOLUME_NAME_NONE
#define VOLUME_NAME_NT
#define VOLUME_NAME_DOS
_In_ HANDLE hFile
Definition: mswsock.h:90
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
#define UNICODE_NULL
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned short USHORT
Definition: pedump.c:61
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:167
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint16_t * PWSTR
Definition: typedefs.h:56
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2439
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3281
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:228
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:64
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by GetFinalPathNameByHandleA().

◆ QueryDosVolumeNameForNtDeviceName()

static NTSTATUS QueryDosVolumeNameForNtDeviceName ( _In_ PCUNICODE_STRING  DeviceName,
_Inout_ PUNICODE_STRING  DosVolumeName 
)
static

Definition at line 19 of file GetFinalPathNameByHandle.c.

22{
23 static const UNICODE_STRING MupDevice = RTL_CONSTANT_STRING(L"\\Device\\Mup");
24 static const UNICODE_STRING LanManDevice = RTL_CONSTANT_STRING(L"\\Device\\LanmanRedirector");
25 static const UNICODE_STRING MountMgrDevice = RTL_CONSTANT_STRING(L"\\Device\\MountPointManager");
28 HANDLE MountMgrHandle;
33
34 /* Validate parameters */
35 if ((DeviceName == NULL) || (DeviceName->Buffer == NULL) || (DeviceName->Length == 0) ||
36 (DosVolumeName == NULL) || (DosVolumeName->Buffer == NULL) || (DosVolumeName->MaximumLength == 0))
37 {
40 }
41
42 /* Reset the output name */
43 DosVolumeName->Length = 0;
44
45 /* Check for network shares */
46 if (RtlEqualUnicodeString(DeviceName, &MupDevice, TRUE) ||
47 RtlEqualUnicodeString(DeviceName, &LanManDevice, TRUE))
48 {
49 /* For Mup or LanmanRedirector we use the UNC path format */
50 return RtlAppendUnicodeToString(DosVolumeName, L"\\\\?\\UNC\\");
51 }
52
53 /* Open a handle to the mount manager */
54 Status = NtCreateFile(&MountMgrHandle,
58 NULL,
62 0,
63 NULL,
64 0);
65 if (!NT_SUCCESS(Status))
66 {
67 DPRINT1("NtCreateFile failed: %lx\n", Status);
68 return Status;
69 }
70
71 /* Use the MountMgr to query the volume name */
72 TargetName->DeviceNameLength = DeviceName->Length;
73 RtlCopyMemory(TargetName->DeviceName, DeviceName->Buffer, DeviceName->Length);
74 Status = NtDeviceIoControlFile(MountMgrHandle,
75 NULL,
76 NULL,
77 NULL,
80 Buffer,
81 sizeof(Buffer),
82 Buffer,
83 sizeof(Buffer));
84 if (!NT_SUCCESS(Status))
85 {
86 DPRINT1("NtDeviceIoControlFile failed: %lx\n", Status);
87 goto Exit;
88 }
89
90 if ((IoStatusBlock.Information < sizeof(*VolumePaths)) ||
91 (IoStatusBlock.Information < (VolumePaths->MultiSzLength + sizeof(ULONG))))
92 {
93 DPRINT1("Invalid information returned: %lu\n", IoStatusBlock.Information);
96 goto Exit;
97 }
98
99 /* Construct the full volume path name from the first returned DOS volume */
100 if (!NT_SUCCESS(RtlAppendUnicodeToString(DosVolumeName, L"\\\\?\\")) ||
101 !NT_SUCCESS(RtlAppendUnicodeToString(DosVolumeName, VolumePaths->MultiSz) ||
102 !NT_SUCCESS(RtlAppendUnicodeToString(DosVolumeName, L"\\"))))
103 {
104 DPRINT1("RtlAppendUnicodeToString failed: %lx\n", Status);
105 goto Exit;
106 }
107
108 /* This is based on Windows behavior */
110
111Exit:
112 NtClose(MountMgrHandle);
113
114 return Status;
115}
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define FILE_OPEN_IF
Definition: from_kernel.h:56
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define ASSERT(a)
Definition: mode.c:44
struct _MOUNTMGR_TARGET_NAME * PMOUNTMGR_TARGET_NAME
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH
Definition: mountmgr.h:147
struct _MOUNTMGR_VOLUME_PATHS * PMOUNTMGR_VOLUME_PATHS
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define STANDARD_RIGHTS_READ
Definition: nt_native.h:65
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength)
#define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a)
static PCWSTR TargetName
Definition: ping.c:67
static void Exit(void)
Definition: sock.c:1330
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132

Referenced by GetFinalPathNameByHandleW().