ReactOS 0.4.15-dev-8061-g57b775e
volume.c File Reference
#include <k32.h>
#include <debug.h>
Include dependency graph for volume.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

BOOL WINAPI GetVolumeInformationA (IN LPCSTR lpRootPathName, IN LPSTR lpVolumeNameBuffer, IN DWORD nVolumeNameSize, OUT LPDWORD lpVolumeSerialNumber OPTIONAL, OUT LPDWORD lpMaximumComponentLength OPTIONAL, OUT LPDWORD lpFileSystemFlags OPTIONAL, OUT LPSTR lpFileSystemNameBuffer OPTIONAL, IN DWORD nFileSystemNameSize)
 
BOOL IsThisARootDirectory (IN HANDLE VolumeHandle, IN PUNICODE_STRING NtPathName)
 
BOOL WINAPI GetVolumeInformationW (IN LPCWSTR lpRootPathName, IN LPWSTR lpVolumeNameBuffer, IN DWORD nVolumeNameSize, OUT LPDWORD lpVolumeSerialNumber OPTIONAL, OUT LPDWORD lpMaximumComponentLength OPTIONAL, OUT LPDWORD lpFileSystemFlags OPTIONAL, OUT LPWSTR lpFileSystemNameBuffer OPTIONAL, IN DWORD nFileSystemNameSize)
 
BOOL WINAPI SetVolumeLabelA (IN LPCSTR lpRootPathName, IN LPCSTR lpVolumeName OPTIONAL)
 
BOOL WINAPI SetVolumeLabelW (IN LPCWSTR lpRootPathName, IN LPCWSTR lpVolumeName OPTIONAL)
 
HANDLE WINAPI FindFirstVolumeW (IN LPWSTR volume, IN DWORD len)
 
HANDLE WINAPI FindFirstVolumeA (IN LPSTR volume, IN DWORD len)
 
BOOL WINAPI FindVolumeClose (IN HANDLE hFindVolume)
 
BOOL WINAPI GetVolumePathNameA (IN LPCSTR lpszFileName, IN LPSTR lpszVolumePathName, IN DWORD cchBufferLength)
 
BOOL WINAPI GetVolumePathNameW (IN LPCWSTR lpszFileName, IN LPWSTR lpszVolumePathName, IN DWORD cchBufferLength)
 
BOOL WINAPI FindNextVolumeA (IN HANDLE handle, IN LPSTR volume, IN DWORD len)
 
BOOL WINAPI FindNextVolumeW (IN HANDLE handle, IN LPWSTR volume, IN DWORD len)
 
BOOL WINAPI GetVolumePathNamesForVolumeNameA (IN LPCSTR lpszVolumeName, IN LPSTR lpszVolumePathNames, IN DWORD cchBufferLength, OUT PDWORD lpcchReturnLength)
 
BOOL WINAPI GetVolumePathNamesForVolumeNameW (IN LPCWSTR lpszVolumeName, IN LPWSTR lpszVolumePathNames, IN DWORD cchBufferLength, OUT PDWORD lpcchReturnLength)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 23 of file volume.c.

Function Documentation

◆ FindFirstVolumeA()

HANDLE WINAPI FindFirstVolumeA ( IN LPSTR  volume,
IN DWORD  len 
)

Definition at line 708 of file volume.c.

710{
711 WCHAR *buffer = NULL;
713
714 buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, len * sizeof(WCHAR) );
715
716 if (!buffer)
717 {
720 }
721
723
725 {
726 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL ))
727 {
730 }
731 }
732 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
733 return handle;
734}
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define NULL
Definition: types.h:112
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define WideCharToMultiByte
Definition: compat.h:111
HANDLE WINAPI FindFirstVolumeW(IN LPWSTR volume, IN DWORD len)
Definition: volume.c:660
BOOL WINAPI FindVolumeClose(IN HANDLE hFindVolume)
Definition: volume.c:741
GLuint buffer
Definition: glext.h:5915
GLenum GLsizei len
Definition: glext.h:6722
__wchar_t WCHAR
Definition: xmlstorage.h:180

◆ FindFirstVolumeW()

HANDLE WINAPI FindFirstVolumeW ( IN LPWSTR  volume,
IN DWORD  len 
)

Definition at line 660 of file volume.c.

662{
663 DWORD size = 1024;
664 DWORD br;
668
669 for (;;)
670 {
672 MOUNTMGR_MOUNT_POINTS *output;
673
674 if (!(output = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
675 {
677 break;
678 }
679 memset( &input, 0, sizeof(input) );
680
682 output, size, &br, NULL ))
683 {
684 if (GetLastError() != ERROR_MORE_DATA) break;
685 size = output->Size;
686 RtlFreeHeap( RtlGetProcessHeap(), 0, output );
687 continue;
688 }
689 CloseHandle( mgr );
690 /* abuse the Size field to store the current index */
691 output->Size = 0;
692 if (!FindNextVolumeW( output, volume, len ))
693 {
694 RtlFreeHeap( RtlGetProcessHeap(), 0, output );
696 }
697 return (HANDLE)output;
698 }
699 CloseHandle( mgr );
701}
#define ERROR_MORE_DATA
Definition: dderror.h:13
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
BOOL WINAPI FindNextVolumeW(IN HANDLE handle, IN LPWSTR volume, IN DWORD len)
Definition: volume.c:1082
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizeiptr size
Definition: glext.h:5919
GLenum GLenum GLenum input
Definition: glext.h:9031
#define IOCTL_MOUNTMGR_QUERY_POINTS
Definition: mountmgr.h:30
#define MOUNTMGR_DOS_DEVICE_NAME
Definition: mountmgr.h:11
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define memset(x, y, z)
Definition: compat.h:39
DWORD WINAPI GetLastError(void)
Definition: except.c:1042

Referenced by CreateVolumeList(), and FindFirstVolumeA().

◆ FindNextVolumeA()

BOOL WINAPI FindNextVolumeA ( IN HANDLE  handle,
IN LPSTR  volume,
IN DWORD  len 
)

Definition at line 1055 of file volume.c.

1058{
1059 WCHAR *buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, len * sizeof(WCHAR));
1060 BOOL ret;
1061
1062 if (!buffer)
1063 {
1065 return FALSE;
1066 }
1067
1068 if ((ret = FindNextVolumeW( handle, buffer, len )))
1069 {
1070 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL )) ret = FALSE;
1071 }
1072
1073 RtlFreeHeap(RtlGetProcessHeap(), 0, buffer);
1074 return ret;
1075}
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
int ret

◆ FindNextVolumeW()

BOOL WINAPI FindNextVolumeW ( IN HANDLE  handle,
IN LPWSTR  volume,
IN DWORD  len 
)

Definition at line 1082 of file volume.c.

1085{
1087
1088 while (data->Size < data->NumberOfMountPoints)
1089 {
1090 static const WCHAR volumeW[] = {'\\','?','?','\\','V','o','l','u','m','e','{',};
1091 WCHAR *link = (WCHAR *)((char *)data + data->MountPoints[data->Size].SymbolicLinkNameOffset);
1092 DWORD size = data->MountPoints[data->Size].SymbolicLinkNameLength;
1093 data->Size++;
1094 /* skip non-volumes */
1095 if (size < sizeof(volumeW) || memcmp( link, volumeW, sizeof(volumeW) )) continue;
1096 if (size + sizeof(WCHAR) >= len * sizeof(WCHAR))
1097 {
1099 return FALSE;
1100 }
1101 memcpy( volume, link, size );
1102 volume[1] = '\\'; /* map \??\ to \\?\ */
1103 volume[size / sizeof(WCHAR)] = '\\'; /* Windows appends a backslash */
1104 volume[size / sizeof(WCHAR) + 1] = 0;
1105 DPRINT( "returning entry %u %s\n", data->Size - 1, volume );
1106 return TRUE;
1107 }
1109 return FALSE;
1110}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
const WCHAR * link
Definition: db.cpp:997
#define TRUE
Definition: types.h:120
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define DPRINT
Definition: sndvol32.h:71
#define ERROR_NO_MORE_FILES
Definition: winerror.h:121
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263

Referenced by CreateVolumeList(), FindFirstVolumeW(), and FindNextVolumeA().

◆ FindVolumeClose()

BOOL WINAPI FindVolumeClose ( IN HANDLE  hFindVolume)

Definition at line 741 of file volume.c.

742{
743 return RtlFreeHeap(RtlGetProcessHeap(), 0, hFindVolume);
744}

Referenced by CreateVolumeList(), and FindFirstVolumeA().

◆ GetVolumeInformationA()

BOOL WINAPI GetVolumeInformationA ( IN LPCSTR  lpRootPathName,
IN LPSTR  lpVolumeNameBuffer,
IN DWORD  nVolumeNameSize,
OUT LPDWORD lpVolumeSerialNumber  OPTIONAL,
OUT LPDWORD lpMaximumComponentLength  OPTIONAL,
OUT LPDWORD lpFileSystemFlags  OPTIONAL,
OUT LPSTR lpFileSystemNameBuffer  OPTIONAL,
IN DWORD  nFileSystemNameSize 
)

Definition at line 32 of file volume.c.

40{
41 BOOL Ret;
43 PUNICODE_STRING RootPathNameU;
44 ANSI_STRING VolumeName, FileSystemName;
45 UNICODE_STRING VolumeNameU, FileSystemNameU;
46
47 /* If no root path provided, default to \ */
48 if (lpRootPathName == NULL)
49 {
50 lpRootPathName = "\\";
51 }
52
53 /* Convert root path to unicode */
54 RootPathNameU = Basep8BitStringToStaticUnicodeString(lpRootPathName);
55 if (RootPathNameU == NULL)
56 {
57 return FALSE;
58 }
59
60 /* Init all our STRINGS (U/A) */
61 VolumeNameU.Buffer = NULL;
62 VolumeNameU.MaximumLength = 0;
63 FileSystemNameU.Buffer = NULL;
64 FileSystemNameU.MaximumLength = 0;
65
66 VolumeName.Buffer = lpVolumeNameBuffer;
67 VolumeName.MaximumLength = nVolumeNameSize + 1;
68 FileSystemName.Buffer = lpFileSystemNameBuffer;
69 FileSystemName.MaximumLength = nFileSystemNameSize + 1;
70
71 /* Assume failure for now */
72 Ret = FALSE;
73
74 /* If caller wants volume name, allocate a buffer to receive it */
75 if (lpVolumeNameBuffer != NULL)
76 {
77 VolumeNameU.MaximumLength = sizeof(WCHAR) * (nVolumeNameSize + 1);
78 VolumeNameU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
79 VolumeNameU.MaximumLength);
80 if (VolumeNameU.Buffer == NULL)
81 {
83 goto CleanAndQuit;
84 }
85 }
86
87 /* If caller wants file system name, allocate a buffer to receive it */
88 if (lpFileSystemNameBuffer != NULL)
89 {
90 FileSystemNameU.MaximumLength = sizeof(WCHAR) * (nFileSystemNameSize + 1);
91 FileSystemNameU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
92 FileSystemNameU.MaximumLength);
93 if (FileSystemNameU.Buffer == NULL)
94 {
96 goto CleanAndQuit;
97 }
98 }
99
100 /* Call W */
101 Ret = GetVolumeInformationW(RootPathNameU->Buffer, VolumeNameU.Buffer,
102 nVolumeNameSize, lpVolumeSerialNumber,
103 lpMaximumComponentLength, lpFileSystemFlags,
104 FileSystemNameU.Buffer, nFileSystemNameSize);
105 /* If it succeed, convert back to ANSI */
106 if (Ret)
107 {
108 if (lpVolumeNameBuffer != NULL)
109 {
110 RtlInitUnicodeString(&VolumeNameU, VolumeNameU.Buffer);
112 if (!NT_SUCCESS(Status))
113 {
115 Ret = FALSE;
116
117 goto CleanAndQuit;
118 }
119 }
120
121 if (lpFileSystemNameBuffer != NULL)
122 {
123 RtlInitUnicodeString(&FileSystemNameU, FileSystemNameU.Buffer);
124 Status = RtlUnicodeStringToAnsiString(&FileSystemName, &FileSystemNameU, FALSE);
125 if (!NT_SUCCESS(Status))
126 {
128 Ret = FALSE;
129
130 goto CleanAndQuit;
131 }
132 }
133 }
134
135 /* Clean and quit */
136CleanAndQuit:
137 if (VolumeNameU.Buffer != NULL)
138 {
139 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeNameU.Buffer);
140 }
141
142 if (FileSystemNameU.Buffer != NULL)
143 {
144 RtlFreeHeap(RtlGetProcessHeap(), 0, FileSystemNameU.Buffer);
145 }
146
147 return Ret;
148}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOL WINAPI GetVolumeInformationW(IN LPCWSTR lpRootPathName, IN LPWSTR lpVolumeNameBuffer, IN DWORD nVolumeNameSize, OUT LPDWORD lpVolumeSerialNumber OPTIONAL, OUT LPDWORD lpMaximumComponentLength OPTIONAL, OUT LPDWORD lpFileSystemFlags OPTIONAL, OUT LPWSTR lpFileSystemNameBuffer OPTIONAL, IN DWORD nFileSystemNameSize)
Definition: volume.c:226
PUNICODE_STRING WINAPI Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
Definition: utils.c:188
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
Status
Definition: gdiplustypes.h:25
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
USHORT MaximumLength
Definition: env_spec_w32.h:377
USHORT MaximumLength
Definition: env_spec_w32.h:370

Referenced by CDrivesFolder::CompareIDs(), DrivesContextMenuCallback(), CDrivesFolder::GetDetailsOf(), and TestGetVolumeInformationA().

◆ GetVolumeInformationW()

BOOL WINAPI GetVolumeInformationW ( IN LPCWSTR  lpRootPathName,
IN LPWSTR  lpVolumeNameBuffer,
IN DWORD  nVolumeNameSize,
OUT LPDWORD lpVolumeSerialNumber  OPTIONAL,
OUT LPDWORD lpMaximumComponentLength  OPTIONAL,
OUT LPDWORD lpFileSystemFlags  OPTIONAL,
OUT LPWSTR lpFileSystemNameBuffer  OPTIONAL,
IN DWORD  nFileSystemNameSize 
)

Definition at line 226 of file volume.c.

234{
235 BOOL Ret;
238 LPCWSTR RootPathName;
239 UNICODE_STRING NtPathName;
244 ULONG OldMode, VolumeInfoSize, VolumeAttrSize;
245
246 /* If no root path provided, default to \ */
247 if (lpRootPathName == NULL)
248 {
249 RootPathName = L"\\";
250 }
251 else
252 {
253 RootPathName = lpRootPathName;
254 }
255
256 /* Convert length to bytes */
257 nVolumeNameSize *= sizeof(WCHAR);
258 nFileSystemNameSize *= sizeof(WCHAR);
259
260 /* Convert to NT name */
261 if (!RtlDosPathNameToNtPathName_U(RootPathName, &NtPathName, NULL, NULL))
262 {
264 return FALSE;
265 }
266
267 /* Check we really end with a backslash */
268 if (NtPathName.Buffer[(NtPathName.Length / sizeof(WCHAR)) - 1] != L'\\')
269 {
270 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
272 return FALSE;
273 }
274
275 /* Try to open the received path */
278 NULL, NULL);
279
280 /* No errors to the user */
283 RtlSetThreadErrorMode(OldMode, NULL);
284 if (!NT_SUCCESS(Status))
285 {
286 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
288 return FALSE;
289 }
290
291 /* Check whether that's a root directory */
292 if (!IsThisARootDirectory(VolumeHandle, &NtPathName))
293 {
294 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
297 return FALSE;
298 }
299
300 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer);
301
302 /* Assume we don't need to query FileFsVolumeInformation */
304 /* If user wants volume name, allocate a buffer to query it */
305 if (lpVolumeNameBuffer != NULL)
306 {
307 VolumeInfoSize = nVolumeNameSize + sizeof(FILE_FS_VOLUME_INFORMATION);
308 }
309 /* If user just wants the serial number, allocate a dummy buffer */
310 else if (lpVolumeSerialNumber != NULL)
311 {
312 VolumeInfoSize = MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_VOLUME_INFORMATION);
313 }
314 /* Otherwise, nothing to query */
315 else
316 {
317 VolumeInfoSize = 0;
318 }
319
320 /* If we're to query, allocate a big enough buffer */
321 if (VolumeInfoSize != 0)
322 {
323 VolumeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumeInfoSize);
324 if (VolumeInfo == NULL)
325 {
328 return FALSE;
329 }
330 }
331
332 /* Assume we don't need to query FileFsAttributeInformation */
333 VolumeAttr = NULL;
334 /* If user wants filesystem name, allocate a buffer to query it */
335 if (lpFileSystemNameBuffer != NULL)
336 {
337 VolumeAttrSize = nFileSystemNameSize + sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
338 }
339 /* If user just wants max compo len or flags, allocate a dummy buffer */
340 else if (lpMaximumComponentLength != NULL || lpFileSystemFlags != NULL)
341 {
342 VolumeAttrSize = MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
343 }
344 else
345 {
346 VolumeAttrSize = 0;
347 }
348
349 /* If we're to query, allocate a big enough buffer */
350 if (VolumeAttrSize != 0)
351 {
352 VolumeAttr = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumeAttrSize);
353 if (VolumeAttr == NULL)
354 {
355 if (VolumeInfo != NULL)
356 {
357 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeInfo);
358 }
359
362 return FALSE;
363 }
364 }
365
366 /* Assume we'll fail */
367 Ret = FALSE;
368
369 /* If we're to query FileFsVolumeInformation, do it now! */
370 if (VolumeInfo != NULL)
371 {
373 if (!NT_SUCCESS(Status))
374 {
376 goto CleanAndQuit;
377 }
378 }
379
380 /* If we're to query FileFsAttributeInformation, do it now! */
381 if (VolumeAttr != NULL)
382 {
384 if (!NT_SUCCESS(Status))
385 {
387 goto CleanAndQuit;
388 }
389 }
390
391 /* If user wants volume name */
392 if (lpVolumeNameBuffer != NULL)
393 {
394 /* Check its buffer can hold it (+ 0) */
395 if (VolumeInfo->VolumeLabelLength >= nVolumeNameSize)
396 {
398 goto CleanAndQuit;
399 }
400
401 /* Copy and zero */
402 RtlCopyMemory(lpVolumeNameBuffer, VolumeInfo->VolumeLabel, VolumeInfo->VolumeLabelLength);
403 lpVolumeNameBuffer[VolumeInfo->VolumeLabelLength / sizeof(WCHAR)] = UNICODE_NULL;
404 }
405
406 /* If user wants wants serial number, return it */
407 if (lpVolumeSerialNumber != NULL)
408 {
409 *lpVolumeSerialNumber = VolumeInfo->VolumeSerialNumber;
410 }
411
412 /* If user wants filesystem name */
413 if (lpFileSystemNameBuffer != NULL)
414 {
415 /* Check its buffer can hold it (+ 0) */
416 if (VolumeAttr->FileSystemNameLength >= nFileSystemNameSize)
417 {
419 goto CleanAndQuit;
420 }
421
422 /* Copy and zero */
423 RtlCopyMemory(lpFileSystemNameBuffer, VolumeAttr->FileSystemName, VolumeAttr->FileSystemNameLength);
424 lpFileSystemNameBuffer[VolumeAttr->FileSystemNameLength / sizeof(WCHAR)] = UNICODE_NULL;
425 }
426
427 /* If user wants wants max compo len, return it */
428 if (lpMaximumComponentLength != NULL)
429 {
430 *lpMaximumComponentLength = VolumeAttr->MaximumComponentNameLength;
431 }
432
433 /* If user wants wants FS flags, return them */
434 if (lpFileSystemFlags != NULL)
435 {
436 *lpFileSystemFlags = VolumeAttr->FileSystemAttributes;
437 }
438
439 /* We did it! */
440 Ret = TRUE;
441
442CleanAndQuit:
444
445 if (VolumeInfo != NULL)
446 {
447 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeInfo);
448 }
449
450 if (VolumeAttr != NULL)
451 {
452 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeAttr);
453 }
454
455 return Ret;
456}
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define MAX_PATH
Definition: compat.h:34
BOOL IsThisARootDirectory(IN HANDLE VolumeHandle, IN PUNICODE_STRING NtPathName)
Definition: volume.c:154
_Must_inspect_result_ _Out_ PHANDLE VolumeHandle
Definition: fltkernel.h:2283
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
struct _FILE_FS_ATTRIBUTE_INFORMATION FILE_FS_ATTRIBUTE_INFORMATION
@ FileFsAttributeInformation
Definition: from_kernel.h:223
@ FileFsVolumeInformation
Definition: from_kernel.h:219
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlSetThreadErrorMode(DWORD, LPDWORD)
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(_In_opt_z_ PCWSTR DosPathName, _Out_ PUNICODE_STRING NtPathName, _Out_opt_ PCWSTR *NtFileNamePart, _Out_opt_ PRTL_RELATIVE_NAME_U DirectoryInfo)
#define RTL_SEM_FAILCRITICALERRORS
Definition: rtltypes.h:74
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3952
#define SYNCHRONIZE
Definition: nt_native.h:61
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define UNICODE_NULL
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define L(x)
Definition: ntvdm.h:50
struct _FILE_FS_VOLUME_INFORMATION FILE_FS_VOLUME_INFORMATION
NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass)
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
#define ERROR_BAD_LENGTH
Definition: winerror.h:127
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define ERROR_DIR_NOT_ROOT
Definition: winerror.h:216
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185

Referenced by AddVolumeToList(), ChkDskNow(), drive_get_FileSystem(), drive_get_SerialNumber(), drive_get_VolumeName(), get_filesystem(), get_volumename(), get_volumeserialnumber(), CDrivesFolder::GetDisplayNameOf(), GetDriveNameWithLetter(), GetVolumeInformationA(), CDrvDefExt::InitGeneralPage(), InitializeFormatDriveDlg(), InitializeRecycleBinDlg(), IsLFNDriveW(), msi_dialog_vcl_add_drives(), my_open(), DriveVolume::Open(), RecycleBin5_Constructor(), ShellLink_GetVolumeInfo(), source_matches_volume(), test_junction_points(), TestGetVolumeInformationW(), TRASH_CanTrashFile(), and wmain().

◆ GetVolumePathNameA()

BOOL WINAPI GetVolumePathNameA ( IN LPCSTR  lpszFileName,
IN LPSTR  lpszVolumePathName,
IN DWORD  cchBufferLength 
)

Definition at line 751 of file volume.c.

754{
755 BOOL Ret;
756 PUNICODE_STRING FileNameU;
757 ANSI_STRING VolumePathName;
758 UNICODE_STRING VolumePathNameU;
759
760 /* Convert file name to unicode */
761 FileNameU = Basep8BitStringToStaticUnicodeString(lpszFileName);
762 if (FileNameU == NULL)
763 {
764 return FALSE;
765 }
766
767 /* Initialize all the strings we'll need */
768 VolumePathName.Buffer = lpszVolumePathName;
769 VolumePathName.Length = 0;
770 VolumePathName.MaximumLength = cchBufferLength - 1;
771
772 VolumePathNameU.Length = 0;
773 VolumePathNameU.MaximumLength = (cchBufferLength - 1) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
774 /* Allocate a buffer for calling the -W */
775 VolumePathNameU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumePathNameU.MaximumLength);
776 if (VolumePathNameU.Buffer == NULL)
777 {
779 return FALSE;
780 }
781
782 /* Call the -W implementation */
783 Ret = GetVolumePathNameW(FileNameU->Buffer, VolumePathNameU.Buffer, cchBufferLength);
784 /* If it succeed */
785 if (Ret)
786 {
788
789 /* Convert back to ANSI */
790 RtlInitUnicodeString(&VolumePathNameU, VolumePathNameU.Buffer);
791 Status = RtlUnicodeStringToAnsiString(&VolumePathName, &VolumePathNameU, FALSE);
792 /* If conversion failed, just set error code and fail the rest */
793 if (!NT_SUCCESS(Status))
794 {
796 Ret = FALSE;
797 }
798 /* Otherwise, null terminate the string (it's OK, we computed -1) */
799 else
800 {
801 VolumePathName.Buffer[VolumePathName.Length] = ANSI_NULL;
802 }
803 }
804
805 /* Free the buffer allocated for -W call */
806 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNameU.Buffer);
807 return Ret;
808}
BOOL WINAPI GetVolumePathNameW(IN LPCWSTR lpszFileName, IN LPWSTR lpszVolumePathName, IN DWORD cchBufferLength)
Definition: volume.c:815
#define ANSI_NULL

◆ GetVolumePathNamesForVolumeNameA()

BOOL WINAPI GetVolumePathNamesForVolumeNameA ( IN LPCSTR  lpszVolumeName,
IN LPSTR  lpszVolumePathNames,
IN DWORD  cchBufferLength,
OUT PDWORD  lpcchReturnLength 
)

Definition at line 1117 of file volume.c.

1121{
1122 BOOL Ret;
1124 DWORD cchReturnLength;
1125 ANSI_STRING VolumePathName;
1126 PUNICODE_STRING VolumeNameU;
1127 UNICODE_STRING VolumePathNamesU;
1128
1129 /* Convert volume name to unicode */
1130 VolumeNameU = Basep8BitStringToStaticUnicodeString(lpszVolumeName);
1131 if (VolumeNameU == NULL)
1132 {
1133 return FALSE;
1134 }
1135
1136 /* Initialize the strings we'll use later on */
1137 VolumePathName.Length = 0;
1138 VolumePathName.MaximumLength = cchBufferLength;
1139 VolumePathName.Buffer = lpszVolumePathNames;
1140
1141 VolumePathNamesU.Length = 0;
1142 VolumePathNamesU.MaximumLength = sizeof(WCHAR) * cchBufferLength;
1143 /* If caller provided a non 0 sized string, allocate a buffer for our unicode string */
1144 if (VolumePathNamesU.MaximumLength != 0)
1145 {
1146 VolumePathNamesU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.MaximumLength);
1147 if (VolumePathNamesU.Buffer == NULL)
1148 {
1150 return FALSE;
1151 }
1152 }
1153 else
1154 {
1155 VolumePathNamesU.Buffer = NULL;
1156 }
1157
1158 /* Call the -W implementation */
1159 Ret = GetVolumePathNamesForVolumeNameW(VolumeNameU->Buffer, VolumePathNamesU.Buffer,
1160 cchBufferLength, &cchReturnLength);
1161 /* Call succeed, we'll return the total length */
1162 if (Ret)
1163 {
1164 VolumePathNamesU.Length = sizeof(WCHAR) * cchReturnLength;
1165 }
1166 else
1167 {
1168 /* Else, if we fail for anything else than too small buffer, quit */
1170 {
1171 if (VolumePathNamesU.Buffer != NULL)
1172 {
1173 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
1174 }
1175
1176 return FALSE;
1177 }
1178
1179 /* Otherwise, we'll just copy as much as we can */
1180 VolumePathNamesU.Length = sizeof(WCHAR) * cchBufferLength;
1181 }
1182
1183 /* Convert our output string back to ANSI */
1184 Status = RtlUnicodeStringToAnsiString(&VolumePathName, &VolumePathNamesU, FALSE);
1185 if (!NT_SUCCESS(Status))
1186 {
1188
1189 if (VolumePathNamesU.Buffer != NULL)
1190 {
1191 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
1192 }
1193
1194 return FALSE;
1195 }
1196
1197 /* If caller wants return length, two cases... */
1198 if (lpcchReturnLength != NULL)
1199 {
1200 /* We succeed: return the copied length */
1201 if (Ret)
1202 {
1203 *lpcchReturnLength = VolumePathName.Length;
1204 }
1205 /* We failed, return the size we would have loved having! */
1206 else
1207 {
1208 *lpcchReturnLength = sizeof(WCHAR) * cchReturnLength;
1209 }
1210 }
1211
1212 /* Release our buffer if allocated */
1213 if (VolumePathNamesU.Buffer != NULL)
1214 {
1215 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
1216 }
1217
1218 return Ret;
1219}
BOOL WINAPI GetVolumePathNamesForVolumeNameW(IN LPCWSTR lpszVolumeName, IN LPWSTR lpszVolumePathNames, IN DWORD cchBufferLength, OUT PDWORD lpcchReturnLength)
Definition: volume.c:1227

◆ GetVolumePathNamesForVolumeNameW()

BOOL WINAPI GetVolumePathNamesForVolumeNameW ( IN LPCWSTR  lpszVolumeName,
IN LPWSTR  lpszVolumePathNames,
IN DWORD  cchBufferLength,
OUT PDWORD  lpcchReturnLength 
)

Definition at line 1227 of file volume.c.

1231{
1232 BOOL Ret;
1233 PWSTR MultiSz;
1235 HANDLE MountMgrHandle;
1238 PMOUNTMGR_VOLUME_PATHS VolumePaths;
1239 ULONG BufferSize, CharsInMgr, CharsInOutput, Paths;
1240
1241 /* First look that our volume name looks somehow correct */
1242 RtlInitUnicodeString(&VolumeName, lpszVolumeName);
1243 if (VolumeName.Buffer[(VolumeName.Length / sizeof(WCHAR)) - 1] != L'\\')
1244 {
1246 return FALSE;
1247 }
1248
1249 /* Validate it's a DOS volume name finishing with a backslash */
1251 {
1253 return FALSE;
1254 }
1255
1256 /* Allocate an input MOUNTMGR_TARGET_NAME */
1257 TargetName = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(USHORT));
1258 if (TargetName == NULL)
1259 {
1261 return FALSE;
1262 }
1263
1264 /* And fill it */
1265 RtlZeroMemory(TargetName, MAX_PATH * sizeof(WCHAR) + sizeof(USHORT));
1266 TargetName->DeviceNameLength = VolumeName.Length - sizeof(WCHAR);
1267 RtlCopyMemory(TargetName->DeviceName, VolumeName.Buffer, TargetName->DeviceNameLength);
1268 TargetName->DeviceName[1] = L'?';
1269
1270 /* Open the mount manager */
1271 MountMgrHandle = CreateFileW(MOUNTMGR_DOS_DEVICE_NAME, 0,
1275 if (MountMgrHandle == INVALID_HANDLE_VALUE)
1276 {
1277 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetName);
1278 return FALSE;
1279 }
1280
1281 /* Allocate an initial output buffer, just to get length */
1282 VolumePaths = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(MOUNTMGR_VOLUME_PATHS));
1283 if (VolumePaths == NULL)
1284 {
1285 CloseHandle(MountMgrHandle);
1286 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetName);
1288 return FALSE;
1289 }
1290
1291 /* Query the paths */
1293 TargetName, MAX_PATH * sizeof(WCHAR) + sizeof(USHORT),
1294 VolumePaths, sizeof(MOUNTMGR_VOLUME_PATHS), &BytesReturned,
1295 NULL);
1296 /* Loop until we can query everything */
1297 while (!Ret)
1298 {
1299 /* If failed for another reason than too small buffer, fail */
1301 {
1302 CloseHandle(MountMgrHandle);
1303 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetName);
1304 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePaths);
1305 return FALSE;
1306 }
1307
1308 /* Get the required length */
1309 BufferSize = VolumePaths->MultiSzLength + sizeof(MOUNTMGR_VOLUME_PATHS);
1310
1311 /* And reallocate our output buffer (big enough this time) */
1312 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePaths);
1313 VolumePaths = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
1314 if (VolumePaths == NULL)
1315 {
1316 CloseHandle(MountMgrHandle);
1317 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetName);
1319 return FALSE;
1320 }
1321
1322 /* Query again the mount mgr */
1324 TargetName, MAX_PATH * sizeof(WCHAR) + sizeof(USHORT),
1325 VolumePaths, BufferSize, &BytesReturned, NULL);
1326 }
1327
1328 /* We're done, no need for input nor mount mgr any longer */
1329 CloseHandle(MountMgrHandle);
1330 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetName);
1331
1332 /* Initialize:
1333 - Number of paths we saw (useful to count extra \‍)
1334 - Progress in mount mgr output
1335 - Progress in output buffer
1336 - Direct buffer to returned MultiSz
1337 */
1338 Paths = 0;
1339 CharsInMgr = 0;
1340 CharsInOutput = 0;
1341 MultiSz = VolumePaths->MultiSz;
1342
1343 /* If we have an output buffer */
1344 if (cchBufferLength != 0)
1345 {
1346 /* Loop on the output to recopy it back to the caller
1347 * Note that we loop until -1 not to handle last 0 (will be done later on)
1348 */
1349 for (; (CharsInMgr < VolumePaths->MultiSzLength / sizeof(WCHAR) - 1) && (CharsInOutput < cchBufferLength);
1350 ++CharsInMgr, ++CharsInOutput)
1351 {
1352 /* When we reach the end of a path */
1353 if (MultiSz[CharsInMgr] == UNICODE_NULL)
1354 {
1355 /* On path done (count), add an extra \ at the end */
1356 ++Paths;
1357 lpszVolumePathNames[CharsInOutput] = L'\\';
1358 ++CharsInOutput;
1359 /* Make sure we don't overflow */
1360 if (CharsInOutput == cchBufferLength)
1361 {
1362 break;
1363 }
1364 }
1365
1366 /* Copy the char to the caller
1367 * So, in case we're in the end of a path, we wrote two chars to
1368 * the output buffer: \\ and \0
1369 */
1370 lpszVolumePathNames[CharsInOutput] = MultiSz[CharsInMgr];
1371 }
1372 }
1373
1374 /* If output buffer was too small (ie, we couldn't parse all the input buffer) */
1375 if (CharsInMgr < VolumePaths->MultiSzLength / sizeof(WCHAR) - 1)
1376 {
1377 /* Keep looping on it, to count the number of extra \ that will be required
1378 * So that on the next call, caller can allocate enough space
1379 */
1380 for (; CharsInMgr < VolumePaths->MultiSzLength / sizeof(WCHAR) - 1; ++CharsInMgr)
1381 {
1382 if (MultiSz[CharsInMgr] == UNICODE_NULL)
1383 {
1384 ++Paths;
1385 }
1386 }
1387 }
1388
1389 /* If we couldn't write as much as we wanted to the output buffer
1390 * This handles the case where we could write everything excepted the
1391 * terminating \0 for multi SZ
1392 */
1393 if (CharsInOutput >= cchBufferLength)
1394 {
1395 /* Fail and set appropriate error code */
1396 Ret = FALSE;
1398 /* If caller wants to know how many chars to allocate, return it */
1399 if (lpcchReturnLength != NULL)
1400 {
1401 /* It's amount of extra \ + number of chars in MultiSz (including double \0) */
1402 *lpcchReturnLength = Paths + (VolumePaths->MultiSzLength / sizeof(WCHAR));
1403 }
1404 }
1405 else
1406 {
1407 /* It succeed so terminate the multi SZ (second \0) */
1408 lpszVolumePathNames[CharsInOutput] = UNICODE_NULL;
1409 Ret = TRUE;
1410
1411 /* If caller wants the amount of chars written, return it */
1412 if (lpcchReturnLength != NULL)
1413 {
1414 /* Including the terminating \0 we just added */
1415 *lpcchReturnLength = CharsInOutput + 1;
1416 }
1417 }
1418
1419 /* Free last bits */
1420 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePaths);
1421
1422 /* And return */
1423 return Ret;
1424}
#define BufferSize
Definition: mmc.h:75
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS
Definition: mountmgr.h:129
struct _MOUNTMGR_VOLUME_PATHS MOUNTMGR_VOLUME_PATHS
#define MOUNTMGR_IS_DOS_VOLUME_NAME_WB(s)
Definition: mountmgr.h:134
unsigned short USHORT
Definition: pedump.c:61
static PCWSTR TargetName
Definition: ping.c:67
uint16_t * PWSTR
Definition: typedefs.h:56
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_ ULONG _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesReturned
Definition: wdfiotarget.h:1052
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254

Referenced by AddVolumeToList(), and GetVolumePathNamesForVolumeNameA().

◆ GetVolumePathNameW()

BOOL WINAPI GetVolumePathNameW ( IN LPCWSTR  lpszFileName,
IN LPWSTR  lpszVolumePathName,
IN DWORD  cchBufferLength 
)

Definition at line 815 of file volume.c.

818{
819 BOOL MountPoint;
820 DWORD FullPathLen;
821 WCHAR OldFilePart;
822 UNICODE_STRING FullPath;
823 PWSTR FullPathBuf, FilePart, VolumeNameBuf;
824
825 /* Probe for full path len */
826 FullPathLen = GetFullPathNameW(lpszFileName, 0, NULL, NULL);
827 if (FullPathLen == 0)
828 {
829 return FALSE;
830 }
831
832 /* Allocate a big enough buffer to receive it */
833 FullPathBuf = RtlAllocateHeap(RtlGetProcessHeap(), 0, (FullPathLen + 10) * sizeof(WCHAR));
834 if (FullPathBuf == NULL)
835 {
837 return FALSE;
838 }
839
840 /* And get full path name */
841 if (GetFullPathNameW(lpszFileName, FullPathLen + 10, FullPathBuf, &FilePart) == 0)
842 {
843 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
844 return FALSE;
845 }
846
847 /* Make a string out of it */
848 RtlInitUnicodeString(&FullPath, FullPathBuf);
849 /* We will finish our string with '\', for ease of the parsing after */
850 if (FullPath.Buffer[(FullPath.Length / sizeof(WCHAR)) - 1] != L'\\')
851 {
852 FullPath.Length += sizeof(WCHAR);
853 FullPath.Buffer[(FullPath.Length / sizeof(WCHAR)) - 1] = L'\\';
854 FullPath.Buffer[FullPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
855 }
856
857 /* Allocate a buffer big enough to receive our volume name */
858 VolumeNameBuf = RtlAllocateHeap(RtlGetProcessHeap(), 0, 0x2000 * sizeof(WCHAR));
859 if (VolumeNameBuf == NULL)
860 {
861 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
863 return FALSE;
864 }
865
866 /* We don't care about file part: we added an extra backslash, so there's no
867 * file, we're back at the dir level.
868 * We'll recompute file part afterwards
869 */
870 FilePart = NULL;
871 /* Keep track of the letter we could drop to shorten the string */
872 OldFilePart = UNICODE_NULL;
873 /* As long as querying volume name fails, keep looping */
874 while (!BasepGetVolumeNameForVolumeMountPoint(FullPath.Buffer, VolumeNameBuf, 0x2000u, &MountPoint))
875 {
876 USHORT LastSlash;
877
878 /* Not a mount point, but opening returning access denied? Assume it's one, just not
879 * a reparse backed one (classic mount point, a device)!
880 */
881 if (!MountPoint && GetLastError() == ERROR_ACCESS_DENIED)
882 {
883 MountPoint = TRUE;
884 }
885
886 /* BasepGetVolumeNameForVolumeMountPoint failed, but returned a volume name.
887 * This can happen when we are given a reparse point where MountMgr could find associated
888 * volume name which is not a valid DOS volume
889 * A valid DOS name always starts with \\
890 */
891 if (VolumeNameBuf[0] != UNICODE_NULL && (FullPath.Buffer[0] != L'\\' || FullPath.Buffer[1] != L'\\'))
892 {
893 CHAR RootPathName[4];
894
895 /* Construct a simple <letter>:\ string to get drive type */
896 RootPathName[0] = FullPath.Buffer[0];
897 RootPathName[1] = ':';
898 RootPathName[2] = '\\';
899 RootPathName[3] = ANSI_NULL;
900
901 /* If we weren't given a drive letter actually, or if that's not a remote drive
902 * Note: in this code path, we're recursive and stop fail loop
903 */
904 if (FullPath.Buffer[1] != L':' || GetDriveTypeA(RootPathName) != DRIVE_REMOTE)
905 {
906 BOOL Ret;
907
908 /* We won't need the full path, we'll now work with the returned volume name */
909 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
910 /* If it wasn't an NT name which was returned */
911 if ((VolumeNameBuf[0] != L'\\') || (VolumeNameBuf[1] != L'?') ||
912 (VolumeNameBuf[2] != L'?') || (VolumeNameBuf[3] != L'\\'))
913 {
914 PWSTR GlobalPath;
915 UNICODE_STRING GlobalRoot;
916
917 /* Create a new name in the NT namespace (from Win32) */
918 RtlInitUnicodeString(&FullPath, VolumeNameBuf);
919 RtlInitUnicodeString(&GlobalRoot, L"\\\\?\\GLOBALROOT");
920
921 /* We allocate a buffer than can contain both the namespace and the volume name */
922 GlobalPath = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullPath.Length + GlobalRoot.Length);
923 if (GlobalPath == NULL)
924 {
925 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeNameBuf);
927 return FALSE;
928 }
929
930 /* Fill in the new query name */
931 RtlCopyMemory(GlobalPath, GlobalRoot.Buffer, GlobalRoot.Length);
932 RtlCopyMemory((PVOID)((ULONG_PTR)GlobalPath + GlobalRoot.Length), FullPath.Buffer, FullPath.Length);
933 GlobalPath[(FullPath.Length + GlobalRoot.Length) / sizeof(WCHAR)] = UNICODE_NULL;
934
935 /* Give it another try */
936 Ret = GetVolumePathNameW(GlobalPath, lpszVolumePathName, cchBufferLength);
937
938 RtlFreeHeap(RtlGetProcessHeap(), 0, GlobalPath);
939 }
940 else
941 {
942 /* If we don't have a drive letter in the Win32 name space \\.<letter>: */
943 if ((VolumeNameBuf[4] != UNICODE_NULL) && (VolumeNameBuf[5] != L':'))
944 {
945 /* Shit our starting \\ */
946 RtlInitUnicodeString(&FullPath, VolumeNameBuf);
947 RtlMoveMemory(VolumeNameBuf, (PVOID)((ULONG_PTR)VolumeNameBuf + (2 * sizeof(WCHAR))), FullPath.Length - (3 * sizeof(WCHAR)));
948 }
949 /* Otherwise, just make sure we're double \ at the being to query again with the
950 * proper namespace
951 */
952 else
953 {
954 VolumeNameBuf[1] = L'\\';
955 }
956
957 /* Give it another try */
958 Ret = GetVolumePathNameW(VolumeNameBuf, lpszVolumePathName, cchBufferLength);
959 }
960
961 /* And done! */
962 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeNameBuf);
963 return Ret;
964 }
965 }
966
967 /* No mount point but with a file part? Restore filepart and exit */
968 if (!MountPoint && FilePart != NULL)
969 {
970 FilePart[0] = OldFilePart;
971 RtlInitUnicodeString(&FullPath, FullPathBuf);
972 break;
973 }
974
975 /* We cannot go down the path any longer, too small */
976 if (FullPath.Length <= sizeof(WCHAR))
977 {
978 break;
979 }
980
981 /* Prepare the next split */
982 LastSlash = (FullPath.Length / sizeof(WCHAR)) - 2;
983 if (FullPath.Length / sizeof(WCHAR) != 2)
984 {
985 do
986 {
987 if (FullPath.Buffer[LastSlash] == L'\\')
988 {
989 break;
990 }
991
992 --LastSlash;
993 } while (LastSlash != 0);
994 }
995
996 /* We couldn't split path, quit */
997 if (LastSlash == 0)
998 {
999 break;
1000 }
1001
1002 /* If that's a mount point, keep track of the directory name */
1003 if (MountPoint)
1004 {
1005 FilePart = &FullPath.Buffer[LastSlash + 1];
1006 OldFilePart = FilePart[0];
1007 /* And null terminate the string */
1008 FilePart[0] = UNICODE_NULL;
1009 }
1010 /* Otherwise, just null terminate the string */
1011 else
1012 {
1013 FullPath.Buffer[LastSlash + 1] = UNICODE_NULL;
1014 }
1015
1016 /* We went down a bit in the path, fix the string and retry */
1017 RtlInitUnicodeString(&FullPath, FullPathBuf);
1018 }
1019
1020 /* Once here, we'll return something from the full path buffer, so release
1021 * output buffer
1022 */
1023 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeNameBuf);
1024
1025 /* Not a mount point, bail out */
1026 if (!MountPoint && FilePart == NULL)
1027 {
1028 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
1029 return FALSE;
1030 }
1031
1032 /* Make sure we have enough room to copy our volume */
1033 if ((cchBufferLength * sizeof(WCHAR)) < FullPath.Length + sizeof(UNICODE_NULL))
1034 {
1035 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
1037 return FALSE;
1038 }
1039
1040 /* Copy and null terminate */
1041 RtlCopyMemory(lpszVolumePathName, FullPath.Buffer, FullPath.Length);
1042 lpszVolumePathName[FullPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
1043
1044 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
1045
1046 /* Done! */
1047 return TRUE;
1048}
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
UINT WINAPI GetDriveTypeA(IN LPCSTR lpRootPathName)
Definition: disk.c:468
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
BOOL BasepGetVolumeNameForVolumeMountPoint(IN LPCWSTR lpszMountPoint, OUT LPWSTR lpszVolumeName, IN DWORD cchBufferLength, OUT LPBOOL IsAMountPoint)
Definition: mntpoint.c:398
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define DRIVE_REMOTE
Definition: winbase.h:253
char CHAR
Definition: xmlstorage.h:175

Referenced by BtrfsSend::AddClone(), BtrfsSend::BrowseParent(), BtrfsRecv::cmd_clone(), BtrfsRecv::cmd_snapshot(), get_volume_path_parent(), GetVolumePathNameA(), GetVolumePathNameW(), RecycleBinGeneric_RecycleBin_DeleteFile(), BtrfsContextMenu::reflink_copy(), ReflinkCopyW(), show_reflink_paste(), and test_GetFinalPathNameByHandleW().

◆ IsThisARootDirectory()

BOOL IsThisARootDirectory ( IN HANDLE  VolumeHandle,
IN PUNICODE_STRING  NtPathName 
)

Definition at line 154 of file volume.c.

156{
159 struct
160 {
163 } FileNameInfo;
164
165 /* If we have a handle, query the name */
166 if (VolumeHandle)
167 {
168 Status = NtQueryInformationFile(VolumeHandle, &IoStatusBlock, &FileNameInfo, sizeof(FileNameInfo), FileNameInformation);
169 if (!NT_SUCCESS(Status))
170 {
171 return FALSE;
172 }
173
174 /* Check we properly end with a \ */
175 if (FileNameInfo.FileName[FileNameInfo.FileNameLength / sizeof(WCHAR) - 1] != L'\\')
176 {
177 return FALSE;
178 }
179 }
180
181 /* If we have a path */
182 if (NtPathName != NULL)
183 {
184 HANDLE LinkHandle;
185 WCHAR Buffer[512];
189
190 NtPathName->Length -= sizeof(WCHAR);
191
194 NULL, NULL);
195
196 /* Try to see whether that's a symbolic name */
198 NtPathName->Length += sizeof(WCHAR);
199 if (!NT_SUCCESS(Status))
200 {
201 return FALSE;
202 }
203
204 /* If so, query the target */
206 LinkTarget.Length = 0;
208
210 NtClose(LinkHandle);
211 /* A root directory (NtName) is a symbolic link */
212 if (!NT_SUCCESS(Status))
213 {
214 return FALSE;
215 }
216 }
217
218 return TRUE;
219}
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG _In_ ULONG _Out_ PULONG ReturnedLength
Definition: batclass.h:188
Definition: bufpool.h:45
@ FileNameInformation
Definition: from_kernel.h:70
struct _FILE_NAME_INFORMATION FILE_NAME_INFORMATION
#define SYMBOLIC_LINK_QUERY
Definition: nt_native.h:1265
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292

Referenced by GetDriveTypeW(), GetVolumeInformationW(), and SetVolumeLabelW().

◆ SetVolumeLabelA()

BOOL WINAPI SetVolumeLabelA ( IN LPCSTR  lpRootPathName,
IN LPCSTR lpVolumeName  OPTIONAL 
)

Definition at line 463 of file volume.c.

465{
466 BOOL Ret;
467 UNICODE_STRING VolumeNameU;
468 PUNICODE_STRING RootPathNameU;
469
470 if (lpRootPathName == NULL)
471 {
472 lpRootPathName = "\\";
473 }
474
475 RootPathNameU = Basep8BitStringToStaticUnicodeString(lpRootPathName);
476 if (RootPathNameU == NULL)
477 {
478 return FALSE;
479 }
480
481 if (lpVolumeName != NULL)
482 {
483 if (!Basep8BitStringToDynamicUnicodeString(&VolumeNameU, lpVolumeName))
484 {
485 return FALSE;
486 }
487 }
488 else
489 {
490 VolumeNameU.Buffer = NULL;
491 }
492
493 Ret = SetVolumeLabelW(RootPathNameU->Buffer, VolumeNameU.Buffer);
494 RtlFreeUnicodeString(&VolumeNameU);
495 return Ret;
496}
BOOL WINAPI SetVolumeLabelW(IN LPCWSTR lpRootPathName, IN LPCWSTR lpVolumeName OPTIONAL)
Definition: volume.c:503
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)

◆ SetVolumeLabelW()

BOOL WINAPI SetVolumeLabelW ( IN LPCWSTR  lpRootPathName,
IN LPCWSTR lpVolumeName  OPTIONAL 
)

Definition at line 503 of file volume.c.

505{
506 BOOL Ret;
508 PWSTR VolumeRoot;
510 WCHAR VolumeGuid[MAX_PATH];
513 PFILE_FS_LABEL_INFORMATION FsLabelInfo;
514 UNICODE_STRING VolumeName, NtVolumeName;
515
516 /* If no root path provided, default to \ */
517 VolumeRoot = L"\\";
518
519 /* If user wants to set a label, make it a string */
520 if (lpVolumeName != NULL)
521 {
522 RtlInitUnicodeString(&VolumeName, lpVolumeName);
523 }
524 else
525 {
526 VolumeName.Length = 0;
529 }
530
531 /* If we received a volume, try to get its GUID name */
532 if (lpRootPathName != NULL)
533 {
534 Ret = GetVolumeNameForVolumeMountPointW(lpRootPathName, VolumeGuid, MAX_PATH);
535 }
536 else
537 {
538 Ret = FALSE;
539 }
540
541 /* If we got the GUID name, use it */
542 if (Ret)
543 {
544 VolumeRoot = VolumeGuid;
545 }
546 else
547 {
548 /* Otherwise, use the name provided by the caller */
549 if (lpRootPathName != NULL)
550 {
551 VolumeRoot = (PWSTR)lpRootPathName;
552 }
553 }
554
555 /* Convert to a NT path */
556 if (!RtlDosPathNameToNtPathName_U(VolumeRoot, &NtVolumeName, NULL, NULL))
557 {
559 return FALSE;
560 }
561
562
563 /* Check we really end with a backslash */
564 if (NtVolumeName.Buffer[(NtVolumeName.Length / sizeof(WCHAR)) - 1] != L'\\')
565 {
566 RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
568 return FALSE;
569 }
570
571 /* Try to open the root directory */
574
579 if (!NT_SUCCESS(Status))
580 {
581 RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
583 return FALSE;
584 }
585
586 /* Validate it's really a root path */
588 {
589 RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
592 return FALSE;
593 }
594
595 /* Done */
597
598 /* Now, open the volume to perform the label change */
599 NtVolumeName.Length -= sizeof(WCHAR);
602
607
608 RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
609
610 if (!NT_SUCCESS(Status))
611 {
613 return FALSE;
614 }
615
616 /* Assume success */
617 Ret = TRUE;
618
619 /* Allocate a buffer that can hold new label and its size */
620 FsLabelInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FILE_FS_LABEL_INFORMATION) + VolumeName.Length);
621 if (FsLabelInfo != NULL)
622 {
623 /* Copy name and set its size */
625 FsLabelInfo->VolumeLabelLength = VolumeName.Length;
626
627 /* And finally, set new label */
629 }
630 else
631 {
632 /* Allocation failed */
634 }
635
636 /* In case of failure, set status and mark failure */
637 if (!NT_SUCCESS(Status))
638 {
640 Ret = FALSE;
641 }
642
643 /* We're done */
645
646 /* Free buffer if required */
647 if (FsLabelInfo != NULL)
648 {
649 RtlFreeHeap(RtlGetProcessHeap(), 0, FsLabelInfo);
650 }
651
652 return Ret;
653}
@ FileFsLabelInformation
Definition: from_kernel.h:220
NTSTATUS NTAPI NtSetVolumeInformationFile(IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass)
Definition: iofunc.c:4438
BOOL WINAPI GetVolumeNameForVolumeMountPointW(IN LPCWSTR VolumeMountPoint, OUT LPWSTR VolumeName, IN DWORD VolumeNameLength)
Definition: mntpoint.c:496
#define FILE_WRITE_DATA
Definition: nt_native.h:631

Referenced by CDrvDefExt::GeneralPageProc(), CDrivesFolder::SetNameOf(), SetVolumeLabelA(), and wmain().