ReactOS 0.4.16-dev-2274-gc61d98f
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 {
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 LPWSTR lpszVolumePathName,
753 IN DWORD cchBufferLength)
754{
755 BOOL MountPoint;
756 DWORD FullPathLen;
757 WCHAR OldFilePart;
758 UNICODE_STRING FullPath;
759 PWSTR FullPathBuf, FilePart, VolumeNameBuf;
760
761 /* Probe for full path len */
762 FullPathLen = GetFullPathNameW(lpszFileName, 0, NULL, NULL);
763 if (FullPathLen == 0)
764 {
765 return FALSE;
766 }
767
768 /* Allocate a big enough buffer to receive it */
769 FullPathBuf = RtlAllocateHeap(RtlGetProcessHeap(), 0, (FullPathLen + 10) * sizeof(WCHAR));
770 if (FullPathBuf == NULL)
771 {
773 return FALSE;
774 }
775
776 /* And get full path name */
777 if (GetFullPathNameW(lpszFileName, FullPathLen + 10, FullPathBuf, &FilePart) == 0)
778 {
779 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
780 return FALSE;
781 }
782
783 /* Make a string out of it */
784 RtlInitUnicodeString(&FullPath, FullPathBuf);
785 /* We will finish our string with '\', for ease of the parsing after */
786 if (FullPath.Buffer[(FullPath.Length / sizeof(WCHAR)) - 1] != L'\\')
787 {
788 FullPath.Length += sizeof(WCHAR);
789 FullPath.Buffer[(FullPath.Length / sizeof(WCHAR)) - 1] = L'\\';
790 FullPath.Buffer[FullPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
791 }
792
793 /* Allocate a buffer big enough to receive our volume name */
794 VolumeNameBuf = RtlAllocateHeap(RtlGetProcessHeap(), 0, 0x2000 * sizeof(WCHAR));
795 if (VolumeNameBuf == NULL)
796 {
797 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
799 return FALSE;
800 }
801
802 /* We don't care about file part: we added an extra backslash, so there's no
803 * file, we're back at the dir level.
804 * We'll recompute file part afterwards
805 */
806 FilePart = NULL;
807 /* Keep track of the letter we could drop to shorten the string */
808 OldFilePart = UNICODE_NULL;
809 /* As long as querying volume name fails, keep looping */
810 while (!BasepGetVolumeNameForVolumeMountPoint(FullPath.Buffer, VolumeNameBuf, 0x2000u, &MountPoint))
811 {
812 USHORT LastSlash;
813
814 /* Not a mount point, but opening returning access denied? Assume it's one, just not
815 * a reparse backed one (classic mount point, a device)!
816 */
817 if (!MountPoint && GetLastError() == ERROR_ACCESS_DENIED)
818 {
819 MountPoint = TRUE;
820 }
821
822 /* BasepGetVolumeNameForVolumeMountPoint failed, but returned a volume name.
823 * This can happen when we are given a reparse point where MountMgr could find associated
824 * volume name which is not a valid DOS volume
825 * A valid DOS name always starts with \\
826 */
827 if (VolumeNameBuf[0] != UNICODE_NULL && (FullPath.Buffer[0] != L'\\' || FullPath.Buffer[1] != L'\\'))
828 {
829 CHAR RootPathName[4];
830
831 /* Construct a simple <letter>:\ string to get drive type */
832 RootPathName[0] = FullPath.Buffer[0];
833 RootPathName[1] = ':';
834 RootPathName[2] = '\\';
835 RootPathName[3] = ANSI_NULL;
836
837 /* If we weren't given a drive letter actually, or if that's not a remote drive
838 * Note: in this code path, we're recursive and stop fail loop
839 */
840 if (FullPath.Buffer[1] != L':' || GetDriveTypeA(RootPathName) != DRIVE_REMOTE)
841 {
842 BOOL Ret;
843
844 /* We won't need the full path, we'll now work with the returned volume name */
845 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
846 /* If it wasn't an NT name which was returned */
847 if ((VolumeNameBuf[0] != L'\\') || (VolumeNameBuf[1] != L'?') ||
848 (VolumeNameBuf[2] != L'?') || (VolumeNameBuf[3] != L'\\'))
849 {
850 PWSTR GlobalPath;
851 UNICODE_STRING GlobalRoot;
852
853 /* Create a new name in the NT namespace (from Win32) */
854 RtlInitUnicodeString(&FullPath, VolumeNameBuf);
855 RtlInitUnicodeString(&GlobalRoot, L"\\\\?\\GLOBALROOT");
856
857 /* We allocate a buffer than can contain both the namespace and the volume name */
858 GlobalPath = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullPath.Length + GlobalRoot.Length);
859 if (GlobalPath == NULL)
860 {
861 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeNameBuf);
863 return FALSE;
864 }
865
866 /* Fill in the new query name */
867 RtlCopyMemory(GlobalPath, GlobalRoot.Buffer, GlobalRoot.Length);
868 RtlCopyMemory((PVOID)((ULONG_PTR)GlobalPath + GlobalRoot.Length), FullPath.Buffer, FullPath.Length);
869 GlobalPath[(FullPath.Length + GlobalRoot.Length) / sizeof(WCHAR)] = UNICODE_NULL;
870
871 /* Give it another try */
872 Ret = GetVolumePathNameW(GlobalPath, lpszVolumePathName, cchBufferLength);
873
874 RtlFreeHeap(RtlGetProcessHeap(), 0, GlobalPath);
875 }
876 else
877 {
878 /* If we don't have a drive letter in the Win32 name space \\.<letter>: */
879 if ((VolumeNameBuf[4] != UNICODE_NULL) && (VolumeNameBuf[5] != L':'))
880 {
881 /* Shit our starting \\ */
882 RtlInitUnicodeString(&FullPath, VolumeNameBuf);
883 RtlMoveMemory(VolumeNameBuf, (PVOID)((ULONG_PTR)VolumeNameBuf + (2 * sizeof(WCHAR))), FullPath.Length - (3 * sizeof(WCHAR)));
884 }
885 /* Otherwise, just make sure we're double \ at the being to query again with the
886 * proper namespace
887 */
888 else
889 {
890 VolumeNameBuf[1] = L'\\';
891 }
892
893 /* Give it another try */
894 Ret = GetVolumePathNameW(VolumeNameBuf, lpszVolumePathName, cchBufferLength);
895 }
896
897 /* And done! */
898 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeNameBuf);
899 return Ret;
900 }
901 }
902
903 /* No mount point but with a file part? Restore filepart and exit */
904 if (!MountPoint && FilePart != NULL)
905 {
906 FilePart[0] = OldFilePart;
907 RtlInitUnicodeString(&FullPath, FullPathBuf);
908 break;
909 }
910
911 /* We cannot go down the path any longer, too small */
912 if (FullPath.Length <= sizeof(WCHAR))
913 {
914 break;
915 }
916
917 /* Prepare the next split */
918 LastSlash = (FullPath.Length / sizeof(WCHAR)) - 2;
919 if (FullPath.Length / sizeof(WCHAR) != 2)
920 {
921 do
922 {
923 if (FullPath.Buffer[LastSlash] == L'\\')
924 {
925 break;
926 }
927
928 --LastSlash;
929 } while (LastSlash != 0);
930 }
931
932 /* We couldn't split path, quit */
933 if (LastSlash == 0)
934 {
935 break;
936 }
937
938 /* If that's a mount point, keep track of the directory name */
939 if (MountPoint)
940 {
941 FilePart = &FullPath.Buffer[LastSlash + 1];
942 OldFilePart = FilePart[0];
943 /* And null terminate the string */
944 FilePart[0] = UNICODE_NULL;
945 }
946 /* Otherwise, just null terminate the string */
947 else
948 {
949 FullPath.Buffer[LastSlash + 1] = UNICODE_NULL;
950 }
951
952 /* We went down a bit in the path, fix the string and retry */
953 RtlInitUnicodeString(&FullPath, FullPathBuf);
954 }
955
956 /* Once here, we'll return something from the full path buffer, so release
957 * output buffer
958 */
959 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeNameBuf);
960
961 /* Not a mount point, bail out */
962 if (!MountPoint && FilePart == NULL)
963 {
964 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
965 return FALSE;
966 }
967
968 /* Make sure we have enough room to copy our volume */
969 if ((cchBufferLength * sizeof(WCHAR)) < FullPath.Length + sizeof(UNICODE_NULL))
970 {
971 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
973 return FALSE;
974 }
975
976 /* Copy and null terminate */
977 RtlCopyMemory(lpszVolumePathName, FullPath.Buffer, FullPath.Length);
978 lpszVolumePathName[FullPath.Length / sizeof(WCHAR)] = UNICODE_NULL;
979
980 RtlFreeHeap(RtlGetProcessHeap(), 0, FullPathBuf);
981
982 /* Done! */
983 return TRUE;
984}
985
986/*
987 * @implemented
988 */
989BOOL
990WINAPI
993 IN DWORD len)
994{
995 WCHAR *buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, len * sizeof(WCHAR));
996 BOOL ret;
997
998 if (!buffer)
999 {
1001 return FALSE;
1002 }
1003
1004 if ((ret = FindNextVolumeW( handle, buffer, len )))
1005 {
1006 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, volume, len, NULL, NULL )) ret = FALSE;
1007 }
1008
1009 RtlFreeHeap(RtlGetProcessHeap(), 0, buffer);
1010 return ret;
1011}
1012
1013/*
1014 * @implemented
1015 */
1016BOOL
1017WINAPI
1020 IN DWORD len)
1021{
1023
1024 while (data->Size < data->NumberOfMountPoints)
1025 {
1026 static const WCHAR volumeW[] = {'\\','?','?','\\','V','o','l','u','m','e','{',};
1027 WCHAR *link = (WCHAR *)((char *)data + data->MountPoints[data->Size].SymbolicLinkNameOffset);
1028 DWORD size = data->MountPoints[data->Size].SymbolicLinkNameLength;
1029 data->Size++;
1030 /* skip non-volumes */
1031 if (size < sizeof(volumeW) || memcmp( link, volumeW, sizeof(volumeW) )) continue;
1032 if (size + sizeof(WCHAR) >= len * sizeof(WCHAR))
1033 {
1035 return FALSE;
1036 }
1037 memcpy( volume, link, size );
1038 volume[1] = '\\'; /* map \??\ to \\?\ */
1039 volume[size / sizeof(WCHAR)] = '\\'; /* Windows appends a backslash */
1040 volume[size / sizeof(WCHAR) + 1] = 0;
1041 DPRINT( "returning entry %u %s\n", data->Size - 1, volume );
1042 return TRUE;
1043 }
1045 return FALSE;
1046}
1047
1048/*
1049 * @implemented
1050 */
1051BOOL
1052WINAPI
1054 IN LPSTR lpszVolumePathNames,
1055 IN DWORD cchBufferLength,
1056 OUT PDWORD lpcchReturnLength)
1057{
1058 BOOL Ret;
1060 DWORD cchReturnLength;
1061 ANSI_STRING VolumePathName;
1062 PUNICODE_STRING VolumeNameU;
1063 UNICODE_STRING VolumePathNamesU;
1064
1065 /* Convert volume name to unicode */
1066 VolumeNameU = Basep8BitStringToStaticUnicodeString(lpszVolumeName);
1067 if (VolumeNameU == NULL)
1068 {
1069 return FALSE;
1070 }
1071
1072 /* Initialize the strings we'll use later on */
1073 VolumePathName.Length = 0;
1074 VolumePathName.MaximumLength = cchBufferLength;
1075 VolumePathName.Buffer = lpszVolumePathNames;
1076
1077 VolumePathNamesU.Length = 0;
1078 VolumePathNamesU.MaximumLength = sizeof(WCHAR) * cchBufferLength;
1079 /* If caller provided a non 0 sized string, allocate a buffer for our unicode string */
1080 if (VolumePathNamesU.MaximumLength != 0)
1081 {
1082 VolumePathNamesU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.MaximumLength);
1083 if (VolumePathNamesU.Buffer == NULL)
1084 {
1086 return FALSE;
1087 }
1088 }
1089 else
1090 {
1091 VolumePathNamesU.Buffer = NULL;
1092 }
1093
1094 /* Call the -W implementation */
1095 Ret = GetVolumePathNamesForVolumeNameW(VolumeNameU->Buffer, VolumePathNamesU.Buffer,
1096 cchBufferLength, &cchReturnLength);
1097 /* Call succeed, we'll return the total length */
1098 if (Ret)
1099 {
1100 VolumePathNamesU.Length = sizeof(WCHAR) * cchReturnLength;
1101 }
1102 else
1103 {
1104 /* Else, if we fail for anything else than too small buffer, quit */
1106 {
1107 if (VolumePathNamesU.Buffer != NULL)
1108 {
1109 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
1110 }
1111
1112 return FALSE;
1113 }
1114
1115 /* Otherwise, we'll just copy as much as we can */
1116 VolumePathNamesU.Length = sizeof(WCHAR) * cchBufferLength;
1117 }
1118
1119 /* Convert our output string back to ANSI */
1120 Status = RtlUnicodeStringToAnsiString(&VolumePathName, &VolumePathNamesU, FALSE);
1121 if (!NT_SUCCESS(Status))
1122 {
1124
1125 if (VolumePathNamesU.Buffer != NULL)
1126 {
1127 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
1128 }
1129
1130 return FALSE;
1131 }
1132
1133 /* If caller wants return length, two cases... */
1134 if (lpcchReturnLength != NULL)
1135 {
1136 /* We succeed: return the copied length */
1137 if (Ret)
1138 {
1139 *lpcchReturnLength = VolumePathName.Length;
1140 }
1141 /* We failed, return the size we would have loved having! */
1142 else
1143 {
1144 *lpcchReturnLength = sizeof(WCHAR) * cchReturnLength;
1145 }
1146 }
1147
1148 /* Release our buffer if allocated */
1149 if (VolumePathNamesU.Buffer != NULL)
1150 {
1151 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
1152 }
1153
1154 return Ret;
1155}
1156
1157
1158/*
1159 * @implemented
1160 */
1161BOOL
1162WINAPI
1164 IN LPWSTR lpszVolumePathNames,
1165 IN DWORD cchBufferLength,
1166 OUT PDWORD lpcchReturnLength)
1167{
1168 BOOL Ret;
1169 PWSTR MultiSz;
1171 HANDLE MountMgrHandle;
1174 PMOUNTMGR_VOLUME_PATHS VolumePaths;
1175 ULONG BufferSize, CharsInMgr, CharsInOutput, Paths;
1176
1177 /* First look that our volume name looks somehow correct */
1178 RtlInitUnicodeString(&VolumeName, lpszVolumeName);
1179 if (VolumeName.Buffer[(VolumeName.Length / sizeof(WCHAR)) - 1] != L'\\')
1180 {
1182 return FALSE;
1183 }
1184
1185 /* Validate it's a DOS volume name finishing with a backslash */
1187 {
1189 return FALSE;
1190 }
1191
1192 /* Allocate an input MOUNTMGR_TARGET_NAME */
1193 TargetName = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(USHORT));
1194 if (TargetName == NULL)
1195 {
1197 return FALSE;
1198 }
1199
1200 /* And fill it */
1201 RtlZeroMemory(TargetName, MAX_PATH * sizeof(WCHAR) + sizeof(USHORT));
1202 TargetName->DeviceNameLength = VolumeName.Length - sizeof(WCHAR);
1203 RtlCopyMemory(TargetName->DeviceName, VolumeName.Buffer, TargetName->DeviceNameLength);
1204 TargetName->DeviceName[1] = L'?';
1205
1206 /* Open the mount manager */
1207 MountMgrHandle = CreateFileW(MOUNTMGR_DOS_DEVICE_NAME, 0,
1211 if (MountMgrHandle == INVALID_HANDLE_VALUE)
1212 {
1213 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetName);
1214 return FALSE;
1215 }
1216
1217 /* Allocate an initial output buffer, just to get length */
1218 VolumePaths = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(MOUNTMGR_VOLUME_PATHS));
1219 if (VolumePaths == NULL)
1220 {
1221 CloseHandle(MountMgrHandle);
1222 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetName);
1224 return FALSE;
1225 }
1226
1227 /* Query the paths */
1229 TargetName, MAX_PATH * sizeof(WCHAR) + sizeof(USHORT),
1230 VolumePaths, sizeof(MOUNTMGR_VOLUME_PATHS), &BytesReturned,
1231 NULL);
1232 /* Loop until we can query everything */
1233 while (!Ret)
1234 {
1235 /* If failed for another reason than too small buffer, fail */
1237 {
1238 CloseHandle(MountMgrHandle);
1239 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetName);
1240 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePaths);
1241 return FALSE;
1242 }
1243
1244 /* Get the required length */
1245 BufferSize = VolumePaths->MultiSzLength + sizeof(MOUNTMGR_VOLUME_PATHS);
1246
1247 /* And reallocate our output buffer (big enough this time) */
1248 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePaths);
1249 VolumePaths = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
1250 if (VolumePaths == NULL)
1251 {
1252 CloseHandle(MountMgrHandle);
1253 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetName);
1255 return FALSE;
1256 }
1257
1258 /* Query again the mount mgr */
1260 TargetName, MAX_PATH * sizeof(WCHAR) + sizeof(USHORT),
1261 VolumePaths, BufferSize, &BytesReturned, NULL);
1262 }
1263
1264 /* We're done, no need for input nor mount mgr any longer */
1265 CloseHandle(MountMgrHandle);
1266 RtlFreeHeap(RtlGetProcessHeap(), 0, TargetName);
1267
1268 /* Initialize:
1269 - Number of paths we saw (useful to count extra \‍)
1270 - Progress in mount mgr output
1271 - Progress in output buffer
1272 - Direct buffer to returned MultiSz
1273 */
1274 Paths = 0;
1275 CharsInMgr = 0;
1276 CharsInOutput = 0;
1277 MultiSz = VolumePaths->MultiSz;
1278
1279 /* If we have an output buffer */
1280 if (cchBufferLength != 0)
1281 {
1282 /* Loop on the output to recopy it back to the caller
1283 * Note that we loop until -1 not to handle last 0 (will be done later on)
1284 */
1285 for (; (CharsInMgr < VolumePaths->MultiSzLength / sizeof(WCHAR) - 1) && (CharsInOutput < cchBufferLength);
1286 ++CharsInMgr, ++CharsInOutput)
1287 {
1288 /* When we reach the end of a path */
1289 if (MultiSz[CharsInMgr] == UNICODE_NULL)
1290 {
1291 /* On path done (count), add an extra \ at the end */
1292 ++Paths;
1293 lpszVolumePathNames[CharsInOutput] = L'\\';
1294 ++CharsInOutput;
1295 /* Make sure we don't overflow */
1296 if (CharsInOutput == cchBufferLength)
1297 {
1298 break;
1299 }
1300 }
1301
1302 /* Copy the char to the caller
1303 * So, in case we're in the end of a path, we wrote two chars to
1304 * the output buffer: \\ and \0
1305 */
1306 lpszVolumePathNames[CharsInOutput] = MultiSz[CharsInMgr];
1307 }
1308 }
1309
1310 /* If output buffer was too small (ie, we couldn't parse all the input buffer) */
1311 if (CharsInMgr < VolumePaths->MultiSzLength / sizeof(WCHAR) - 1)
1312 {
1313 /* Keep looping on it, to count the number of extra \ that will be required
1314 * So that on the next call, caller can allocate enough space
1315 */
1316 for (; CharsInMgr < VolumePaths->MultiSzLength / sizeof(WCHAR) - 1; ++CharsInMgr)
1317 {
1318 if (MultiSz[CharsInMgr] == UNICODE_NULL)
1319 {
1320 ++Paths;
1321 }
1322 }
1323 }
1324
1325 /* If we couldn't write as much as we wanted to the output buffer
1326 * This handles the case where we could write everything excepted the
1327 * terminating \0 for multi SZ
1328 */
1329 if (CharsInOutput >= cchBufferLength)
1330 {
1331 /* Fail and set appropriate error code */
1332 Ret = FALSE;
1334 /* If caller wants to know how many chars to allocate, return it */
1335 if (lpcchReturnLength != NULL)
1336 {
1337 /* It's amount of extra \ + number of chars in MultiSz (including double \0) */
1338 *lpcchReturnLength = Paths + (VolumePaths->MultiSzLength / sizeof(WCHAR));
1339 }
1340 }
1341 else
1342 {
1343 /* It succeed so terminate the multi SZ (second \0) */
1344 lpszVolumePathNames[CharsInOutput] = UNICODE_NULL;
1345 Ret = TRUE;
1346
1347 /* If caller wants the amount of chars written, return it */
1348 if (lpcchReturnLength != NULL)
1349 {
1350 /* Including the terminating \0 we just added */
1351 *lpcchReturnLength = CharsInOutput + 1;
1352 }
1353 }
1354
1355 /* Free last bits */
1356 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePaths);
1357
1358 /* And return */
1359 return Ret;
1360}
1361
1362/* EOF */
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:616
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
const WCHAR * link
Definition: db.cpp:998
#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:1018
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 GetVolumePathNameW(IN LPCWSTR lpszFileName, IN LPWSTR lpszVolumePathName, IN DWORD cchBufferLength)
Definition: volume.c:751
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:991
BOOL WINAPI GetVolumePathNamesForVolumeNameA(IN LPCSTR lpszVolumeName, IN LPSTR lpszVolumePathNames, IN DWORD cchBufferLength, OUT PDWORD lpcchReturnLength)
Definition: volume.c:1053
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:1163
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:226
PUNICODE_STRING WINAPI Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
Definition: utils.c:189
#define SYMBOLIC_LINK_QUERY
Definition: volume.c:47
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
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
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
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
@ FileNameInfo
Definition: minwinbase.h:306
#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
#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:3953
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 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
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
DWORD * PDWORD
Definition: pedump.c:68
unsigned short USHORT
Definition: pedump.c:61
static PCWSTR TargetName
Definition: ping.c:67
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
_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:277
#define WINAPI
Definition: msvc.h:6
struct _FILE_FS_VOLUME_INFORMATION FILE_FS_VOLUME_INFORMATION
#define ERROR_BAD_LENGTH
Definition: winerror.h:249
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:228
#define ERROR_NO_MORE_FILES
Definition: winerror.h:243
#define ERROR_DIR_NOT_ROOT
Definition: winerror.h:338
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:385
const char * LPCSTR
Definition: xmlstorage.h:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char * LPSTR
Definition: xmlstorage.h:182
char CHAR
Definition: xmlstorage.h:175
_Inout_ PUNICODE_STRING LinkTarget
Definition: zwfuncs.h:292