ReactOS 0.4.15-dev-8413-gc1c91f2
volume.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/file/volume.c
5 * PURPOSE: File volume functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * Erik Bos, Alexandre Julliard :
8 * GetLogicalDriveStringsA,
9 * GetLogicalDriveStringsW, GetLogicalDrives
10 * Pierre Schweitzer (pierre@reactos.org)
11 * UPDATE HISTORY:
12 * Created 01/11/98
13 */
14//WINE copyright notice:
15/*
16 * DOS drives handling functions
17 *
18 * Copyright 1993 Erik Bos
19 * Copyright 1996 Alexandre Julliard
20 */
21
22#include <k32.h>
23#define NDEBUG
24#include <debug.h>
25
26
27/*
28 * @implemented
29 */
30BOOL
33 IN LPSTR lpVolumeNameBuffer,
34 IN DWORD nVolumeNameSize,
35 OUT LPDWORD lpVolumeSerialNumber OPTIONAL,
36 OUT LPDWORD lpMaximumComponentLength OPTIONAL,
37 OUT LPDWORD lpFileSystemFlags OPTIONAL,
38 OUT LPSTR lpFileSystemNameBuffer OPTIONAL,
39 IN DWORD nFileSystemNameSize)
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}
149
150/*
151 * @implemented
152 */
153BOOL
155 IN PUNICODE_STRING NtPathName)
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}
220
221/*
222 * @implemented
223 */
224BOOL
225WINAPI
227 IN LPWSTR lpVolumeNameBuffer,
228 IN DWORD nVolumeNameSize,
229 OUT LPDWORD lpVolumeSerialNumber OPTIONAL,
230 OUT LPDWORD lpMaximumComponentLength OPTIONAL,
231 OUT LPDWORD lpFileSystemFlags OPTIONAL,
232 OUT LPWSTR lpFileSystemNameBuffer OPTIONAL,
233 IN DWORD nFileSystemNameSize)
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}
457
458/*
459 * @implemented
460 */
461BOOL
462WINAPI
463SetVolumeLabelA(IN LPCSTR lpRootPathName,
464 IN LPCSTR lpVolumeName OPTIONAL) /* NULL if deleting label */
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}
497
498/*
499 * @implemented
500 */
501BOOL
502WINAPI
504 IN LPCWSTR lpVolumeName OPTIONAL) /* NULL if deleting label */
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}
654
655/*
656 * @implemented (Wine 13 sep 2008)
657 */
658HANDLE
659WINAPI
661 IN DWORD len)
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}
702
703/*
704 * @implemented (Wine 13 sep 2008)
705 */
706HANDLE
707WINAPI
709 IN DWORD len)
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}
735
736/*
737 * @implemented (Wine 13 sep 2008)
738 */
739BOOL
740WINAPI
742{
743 return RtlFreeHeap(RtlGetProcessHeap(), 0, hFindVolume);
744}
745
746/*
747 * @implemented
748 */
749BOOL
750WINAPI
752 IN LPSTR lpszVolumePathName,
753 IN DWORD cchBufferLength)
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}
809
810/*
811 * @implemented
812 */
813BOOL
814WINAPI
816 IN LPWSTR lpszVolumePathName,
817 IN DWORD cchBufferLength)
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}
1049
1050/*
1051 * @implemented
1052 */
1053BOOL
1054WINAPI
1056 IN LPSTR volume,
1057 IN DWORD len)
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}
1076
1077/*
1078 * @implemented
1079 */
1080BOOL
1081WINAPI
1084 IN DWORD len)
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}
1111
1112/*
1113 * @implemented
1114 */
1115BOOL
1116WINAPI
1118 IN LPSTR lpszVolumePathNames,
1119 IN DWORD cchBufferLength,
1120 OUT PDWORD lpcchReturnLength)
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}
1220
1221
1222/*
1223 * @implemented
1224 */
1225BOOL
1226WINAPI
1228 IN LPWSTR lpszVolumePathNames,
1229 IN DWORD cchBufferLength,
1230 OUT PDWORD lpcchReturnLength)
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}
1425
1426/* EOF */
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG _In_ ULONG _Out_ PULONG ReturnedLength
Definition: batclass.h:188
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
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
const WCHAR * link
Definition: db.cpp:997
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define BufferSize
Definition: mmc.h:75
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 NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define CloseHandle
Definition: compat.h:739
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define WideCharToMultiByte
Definition: compat.h:111
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define FILE_SHARE_READ
Definition: compat.h:136
UINT WINAPI GetDriveTypeA(IN LPCSTR lpRootPathName)
Definition: disk.c:468
BOOL WINAPI FindNextVolumeW(IN HANDLE handle, IN LPWSTR volume, IN DWORD len)
Definition: volume.c:1082
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
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: volume.c:32
HANDLE WINAPI FindFirstVolumeW(IN LPWSTR volume, IN DWORD len)
Definition: volume.c:660
BOOL WINAPI GetVolumePathNameA(IN LPCSTR lpszFileName, IN LPSTR lpszVolumePathName, IN DWORD cchBufferLength)
Definition: volume.c:751
BOOL WINAPI GetVolumePathNameW(IN LPCWSTR lpszFileName, IN LPWSTR lpszVolumePathName, IN DWORD cchBufferLength)
Definition: volume.c:815
BOOL WINAPI FindVolumeClose(IN HANDLE hFindVolume)
Definition: volume.c:741
BOOL IsThisARootDirectory(IN HANDLE VolumeHandle, IN PUNICODE_STRING NtPathName)
Definition: volume.c:154
HANDLE WINAPI FindFirstVolumeA(IN LPSTR volume, IN DWORD len)
Definition: volume.c:708
BOOL WINAPI FindNextVolumeA(IN HANDLE handle, IN LPSTR volume, IN DWORD len)
Definition: volume.c:1055
BOOL WINAPI GetVolumePathNamesForVolumeNameA(IN LPCSTR lpszVolumeName, IN LPSTR lpszVolumePathNames, IN DWORD cchBufferLength, OUT PDWORD lpcchReturnLength)
Definition: volume.c:1117
BOOL WINAPI SetVolumeLabelA(IN LPCSTR lpRootPathName, IN LPCSTR lpVolumeName OPTIONAL)
Definition: volume.c:463
BOOL WINAPI GetVolumePathNamesForVolumeNameW(IN LPCWSTR lpszVolumeName, IN LPWSTR lpszVolumePathNames, IN DWORD cchBufferLength, OUT PDWORD lpcchReturnLength)
Definition: volume.c:1227
BOOL WINAPI SetVolumeLabelW(IN LPCWSTR lpRootPathName, IN LPCWSTR lpVolumeName OPTIONAL)
Definition: volume.c:503
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
PUNICODE_STRING WINAPI Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
Definition: utils.c:188
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
_Must_inspect_result_ _Out_ PHANDLE VolumeHandle
Definition: fltkernel.h:2283
@ FileNameInformation
Definition: from_kernel.h:70
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
struct _FILE_FS_ATTRIBUTE_INFORMATION FILE_FS_ATTRIBUTE_INFORMATION
@ FileFsLabelInformation
Definition: from_kernel.h:220
@ FileFsAttributeInformation
Definition: from_kernel.h:223
@ FileFsVolumeInformation
Definition: from_kernel.h:219
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
Status
Definition: gdiplustypes.h:25
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
GLenum GLsizei len
Definition: glext.h:6722
GLenum GLenum GLenum input
Definition: glext.h:9031
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlSetThreadErrorMode(DWORD, LPDWORD)
struct _FILE_NAME_INFORMATION FILE_NAME_INFORMATION
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
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
BOOL WINAPI GetVolumeNameForVolumeMountPointW(IN LPCWSTR VolumeMountPoint, OUT LPWSTR VolumeName, IN DWORD VolumeNameLength)
Definition: mntpoint.c:496
BOOL BasepGetVolumeNameForVolumeMountPoint(IN LPCWSTR lpszMountPoint, OUT LPWSTR lpszVolumeName, IN DWORD cchBufferLength, OUT LPBOOL IsAMountPoint)
Definition: mntpoint.c:398
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS
Definition: mountmgr.h:149
#define IOCTL_MOUNTMGR_QUERY_POINTS
Definition: mountmgr.h:49
#define MOUNTMGR_DOS_DEVICE_NAME
Definition: mountmgr.h:37
struct _MOUNTMGR_VOLUME_PATHS MOUNTMGR_VOLUME_PATHS
#define MOUNTMGR_IS_DOS_VOLUME_NAME_WB(s)
Definition: mountmgr.h:154
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
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define SYMBOLIC_LINK_QUERY
Definition: nt_native.h:1265
#define FILE_WRITE_DATA
Definition: nt_native.h:631
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define UNICODE_NULL
#define ANSI_NULL
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define L(x)
Definition: ntvdm.h:50
DWORD * PDWORD
Definition: pedump.c:68
unsigned short USHORT
Definition: pedump.c:61
static PCWSTR TargetName
Definition: ping.c:67
struct _FILE_FS_VOLUME_INFORMATION FILE_FS_VOLUME_INFORMATION
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:167
#define memset(x, y, z)
Definition: compat.h:39
NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass)
#define DPRINT
Definition: sndvol32.h:73
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
USHORT MaximumLength
Definition: env_spec_w32.h:377
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * LPDWORD
Definition: typedefs.h:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
int ret
_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
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define DRIVE_REMOTE
Definition: winbase.h:253
#define WINAPI
Definition: msvc.h:6
#define ERROR_BAD_LENGTH
Definition: winerror.h:127
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define ERROR_NO_MORE_FILES
Definition: winerror.h:121
#define ERROR_DIR_NOT_ROOT
Definition: winerror.h:216
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292