ReactOS 0.4.15-dev-7788-g1ad9096
dir.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/dir.c
5 * PURPOSE: Directory functions
6 * PROGRAMMER: Pierre Schweitzer (pierre@reactos.org)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <k32.h>
12#define NDEBUG
13#include <debug.h>
14
15/* Short File Name length in chars (8.3) */
16#define SFN_LENGTH 12
17
18/* Match a volume name like:
19 * \\?\Volume{GUID}
20 */
21#define IS_VOLUME_NAME(s, l) \
22 ((l == 96 || (l == 98 && s[48] == '\\')) && \
23 s[0] == '\\'&& (s[1] == '?' || s[1] == '\\') && \
24 s[2] == '?' && s[3] == '\\' && s[4] == 'V' && \
25 s[5] == 'o' && s[6] == 'l' && s[7] == 'u' && \
26 s[8] == 'm' && s[9] == 'e' && s[10] == '{' && \
27 s[19] == '-' && s[24] == '-' && s[29] == '-' && \
28 s[34] == '-' && s[47] == '}')
29
30/* FUNCTIONS *****************************************************************/
31
32/*
33 * @implemented
34 */
35BOOL
38 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
39{
40 PUNICODE_STRING PathNameW;
41
42 PathNameW = Basep8BitStringToStaticUnicodeString(lpPathName);
43 if (!PathNameW)
44 {
45 return FALSE;
46 }
47
48 return CreateDirectoryW(PathNameW->Buffer,
49 lpSecurityAttributes);
50}
51
52/*
53 * @implemented
54 */
55BOOL
57CreateDirectoryExA(IN LPCSTR lpTemplateDirectory,
58 IN LPCSTR lpNewDirectory,
59 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
60{
61 PUNICODE_STRING TemplateDirectoryW;
62 UNICODE_STRING NewDirectoryW;
63 BOOL ret;
64
65 TemplateDirectoryW = Basep8BitStringToStaticUnicodeString(lpTemplateDirectory);
66 if (!TemplateDirectoryW)
67 {
68 return FALSE;
69 }
70
71 if (!Basep8BitStringToDynamicUnicodeString(&NewDirectoryW, lpNewDirectory))
72 {
73 return FALSE;
74 }
75
76 ret = CreateDirectoryExW(TemplateDirectoryW->Buffer,
77 NewDirectoryW.Buffer,
78 lpSecurityAttributes);
79
80 RtlFreeUnicodeString(&NewDirectoryW);
81
82 return ret;
83}
84
85/*
86 * @implemented
87 */
88BOOL
91 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
92{
96 UNICODE_STRING NtPathU;
97 PWSTR PathUBuffer, FilePart;
99 RTL_RELATIVE_NAME_U RelativeName;
101
102 /* Get relative name */
103 if (!RtlDosPathNameToRelativeNtPathName_U(lpPathName, &NtPathU, NULL, &RelativeName))
104 {
106 return FALSE;
107 }
108
109 /* Check if path length is < MAX_PATH (with space for file name).
110 * If not, prefix is required.
111 */
112 if (NtPathU.Length > (MAX_PATH - SFN_LENGTH) * sizeof(WCHAR) && lpPathName[0] != L'\\' &&
113 lpPathName[1] != L'\\' && lpPathName[2] != L'?' && lpPathName[3] != L'\\')
114 {
115 /* Get file name position and full path length */
116 Length = GetFullPathNameW(lpPathName, 0, NULL, &FilePart);
117 if (Length == 0)
118 {
119 RtlReleaseRelativeName(&RelativeName);
120 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU.Buffer);
122 return FALSE;
123 }
124
125 /* Keep place for 8.3 file name */
127 /* No prefix, so, must be smaller than MAX_PATH */
128 if (Length > MAX_PATH)
129 {
130 RtlReleaseRelativeName(&RelativeName);
131 RtlFreeHeap(GetProcessHeap(), 0, NtPathU.Buffer);
133 return FALSE;
134 }
135 }
136
137 /* Save buffer to allow later freeing */
138 PathUBuffer = NtPathU.Buffer;
139
140 /* If we have relative name (and root dir), use them instead */
141 if (RelativeName.RelativeName.Length != 0)
142 {
143 NtPathU.Length = RelativeName.RelativeName.Length;
144 NtPathU.MaximumLength = RelativeName.RelativeName.MaximumLength;
145 NtPathU.Buffer = RelativeName.RelativeName.Buffer;
146 }
147 else
148 {
149 RelativeName.ContainingDirectory = NULL;
150 }
151
153 &NtPathU,
155 RelativeName.ContainingDirectory,
156 (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));
157
162 NULL,
167 NULL,
168 0);
169
170 RtlReleaseRelativeName(&RelativeName);
171 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
172
173 if (NT_SUCCESS(Status))
174 {
176 return TRUE;
177 }
178
179 if (RtlIsDosDeviceName_U(lpPathName))
180 {
182 }
183
185 return FALSE;
186}
187
188/*
189 * @implemented
190 */
191BOOL
192WINAPI
193CreateDirectoryExW(IN LPCWSTR lpTemplateDirectory,
194 IN LPCWSTR lpNewDirectory,
195 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
196{
200 BOOL ReparsePoint = FALSE;
202 FILE_EA_INFORMATION FileEaInfo;
203 ULONG EaLength = 0, StreamSize;
205 FILE_BASIC_INFORMATION FileBasicInfo;
206 PREPARSE_DATA_BUFFER ReparseDataBuffer;
207 HANDLE TemplateHandle, DirectoryHandle;
208 PFILE_STREAM_INFORMATION FileStreamInfo;
210 UNICODE_STRING NtPathU, NtTemplatePathU, NewDirectory;
211 RTL_RELATIVE_NAME_U RelativeName, TemplateRelativeName;
212 PWSTR TemplateBuffer, PathUBuffer, FilePart, SubstituteName;
213
214 /* Get relative name of the template */
215 if (!RtlDosPathNameToRelativeNtPathName_U(lpTemplateDirectory, &NtTemplatePathU, NULL, &TemplateRelativeName))
216 {
218 return FALSE;
219 }
220
221 /* Save buffer for further freeing */
222 TemplateBuffer = NtTemplatePathU.Buffer;
223
224 /* If we have relative name (and root dir), use them instead */
225 if (TemplateRelativeName.RelativeName.Length != 0)
226 {
227 NtTemplatePathU.Length = TemplateRelativeName.RelativeName.Length;
228 NtTemplatePathU.MaximumLength = TemplateRelativeName.RelativeName.MaximumLength;
229 NtTemplatePathU.Buffer = TemplateRelativeName.RelativeName.Buffer;
230 }
231 else
232 {
233 TemplateRelativeName.ContainingDirectory = NULL;
234 }
235
237 &NtTemplatePathU,
239 NULL,
240 NULL);
241
242 /* Open template directory */
243 Status = NtOpenFile(&TemplateHandle,
249 if (!NT_SUCCESS(Status))
250 {
252 {
253 RtlReleaseRelativeName(&TemplateRelativeName);
254 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
256 return FALSE;
257 }
258
259OpenWithoutReparseSupport:
260 /* Opening failed due to lacking reparse points support in the FSD, try without */
261 Status = NtOpenFile(&TemplateHandle,
267
268 if (!NT_SUCCESS(Status))
269 {
270 RtlReleaseRelativeName(&TemplateRelativeName);
271 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
273 return FALSE;
274 }
275
276 /* Request file attributes */
278 Status = NtQueryInformationFile(TemplateHandle,
280 &FileBasicInfo,
281 sizeof(FileBasicInfo),
283 if (!NT_SUCCESS(Status))
284 {
285 RtlReleaseRelativeName(&TemplateRelativeName);
286 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
287 CloseHandle(TemplateHandle);
289 return FALSE;
290
291 }
292 }
293 else
294 {
295 /* Request file attributes */
297 Status = NtQueryInformationFile(TemplateHandle,
299 &FileBasicInfo,
300 sizeof(FileBasicInfo),
302 if (!NT_SUCCESS(Status))
303 {
304 RtlReleaseRelativeName(&TemplateRelativeName);
305 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
306 CloseHandle(TemplateHandle);
308 return FALSE;
309
310 }
311
312 /* If it is a reparse point, then get information about it */
314 {
315 Status = NtQueryInformationFile(TemplateHandle,
317 &FileTagInfo,
318 sizeof(FileTagInfo),
320 if (!NT_SUCCESS(Status))
321 {
322 RtlReleaseRelativeName(&TemplateRelativeName);
323 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
324 CloseHandle(TemplateHandle);
326 return FALSE;
327 }
328
329 /* Only mount points are supported, retry without if anything different */
330 if (FileTagInfo.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
331 {
332 CloseHandle(TemplateHandle);
333 goto OpenWithoutReparseSupport;
334 }
335
336 /* Mark we are playing with a reparse point */
337 ReparsePoint = TRUE;
338 }
339 }
340
341 /* Get relative name of the directory */
342 if (!RtlDosPathNameToRelativeNtPathName_U(lpNewDirectory, &NtPathU, NULL, &RelativeName))
343 {
344 RtlReleaseRelativeName(&TemplateRelativeName);
345 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
346 NtClose(TemplateHandle);
348 return FALSE;
349 }
350
351 /* Save its buffer for further freeing */
352 PathUBuffer = NtPathU.Buffer;
353
354 /* Template & directory can't be the same */
355 if (RtlEqualUnicodeString(&NtPathU,
356 &NtTemplatePathU,
357 TRUE))
358 {
359 RtlReleaseRelativeName(&RelativeName);
360 RtlReleaseRelativeName(&TemplateRelativeName);
361 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
362 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
363 NtClose(TemplateHandle);
365 return FALSE;
366 }
367
368 RtlReleaseRelativeName(&TemplateRelativeName);
369 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
370
371 /* Check if path length is < MAX_PATH (with space for file name).
372 * If not, prefix is required.
373 */
374 if (NtPathU.Length > (MAX_PATH - SFN_LENGTH) * sizeof(WCHAR) && lpNewDirectory[0] != L'\\' &&
375 lpNewDirectory[1] != L'\\' && lpNewDirectory[2] != L'?' && lpNewDirectory[3] != L'\\')
376 {
377 /* Get file name position and full path length */
378 Length = GetFullPathNameW(lpNewDirectory, 0, NULL, &FilePart);
379 if (Length == 0)
380 {
381 RtlReleaseRelativeName(&RelativeName);
382 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
383 CloseHandle(TemplateHandle);
385 return FALSE;
386 }
387
388 /* Keep place for 8.3 file name */
390 /* No prefix, so, must be smaller than MAX_PATH */
391 if (Length > MAX_PATH)
392 {
393 RtlReleaseRelativeName(&RelativeName);
394 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
395 CloseHandle(TemplateHandle);
397 return FALSE;
398 }
399 }
400
401 /* If we have relative name (and root dir), use them instead */
402 if (RelativeName.RelativeName.Length != 0)
403 {
404 NtPathU.Length = RelativeName.RelativeName.Length;
405 NtPathU.MaximumLength = RelativeName.RelativeName.MaximumLength;
406 NtPathU.Buffer = RelativeName.RelativeName.Buffer;
407 }
408 else
409 {
410 RelativeName.ContainingDirectory = NULL;
411 }
412
413 /* Get extended attributes */
414 Status = NtQueryInformationFile(TemplateHandle,
416 &FileEaInfo,
417 sizeof(FileEaInfo),
419 if (!NT_SUCCESS(Status))
420 {
421 RtlReleaseRelativeName(&RelativeName);
422 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
423 CloseHandle(TemplateHandle);
425 return FALSE;
426 }
427
428 /* Start reading extended attributes */
429 if (FileEaInfo.EaSize != 0)
430 {
431 for (EaLength = FileEaInfo.EaSize * 2; ; EaLength = EaLength * 2)
432 {
433 /* Allocate buffer for reading */
434 EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, EaLength);
435 if (!EaBuffer)
436 {
437 RtlReleaseRelativeName(&RelativeName);
438 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
439 CloseHandle(TemplateHandle);
441 return FALSE;
442 }
443
444 /* Query EAs */
445 Status = NtQueryEaFile(TemplateHandle,
447 EaBuffer,
448 EaLength,
449 FALSE,
450 NULL,
451 0,
452 NULL,
453 TRUE);
454 if (!NT_SUCCESS(Status))
455 {
456 RtlFreeHeap(RtlGetProcessHeap(), 0, EaBuffer);
458 }
459
460 /* If we don't fail because of too small buffer, stop here */
463 {
465 break;
466 }
467 }
468 }
469
471 &NtPathU,
473 RelativeName.ContainingDirectory,
474 (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));
475
476 /* Ensure attributes are valid */
478
479 /* Create the new directory */
485 NULL,
486 FileBasicInfo.FileAttributes,
491 EaBuffer,
492 EaLength);
493 if (!NT_SUCCESS(Status))
494 {
496 {
497 /* If creation failed, it might be because FSD doesn't support reparse points
498 * Retry without asking for such support in case template is not a reparse point
499 */
500 if (!ReparsePoint)
501 {
507 NULL,
508 FileBasicInfo.FileAttributes,
513 EaBuffer,
514 EaLength);
515 }
516 else
517 {
518 RtlReleaseRelativeName(&RelativeName);
519 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
520 if (EaBuffer)
521 {
522 RtlFreeHeap(RtlGetProcessHeap(), 0, EaBuffer);
523 }
524 CloseHandle(TemplateHandle);
526 return FALSE;
527 }
528 }
529 }
530
531 RtlReleaseRelativeName(&RelativeName);
532 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
533 if (EaBuffer)
534 {
535 RtlFreeHeap(RtlGetProcessHeap(), 0, EaBuffer);
536 }
537
538 if (!NT_SUCCESS(Status))
539 {
540 NtClose(TemplateHandle);
541 if (RtlIsDosDeviceName_U(lpNewDirectory))
542 {
544 }
546 return FALSE;
547 }
548
549 /* If template is a reparse point, copy reparse data */
550 if (ReparsePoint)
551 {
552 ReparseDataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
554 if (!ReparseDataBuffer)
555 {
556 NtClose(TemplateHandle);
559 return FALSE;
560 }
561
562 /* First query data */
563 Status = NtFsControlFile(TemplateHandle,
564 NULL,
565 NULL,
566 NULL,
569 NULL,
570 0,
571 ReparseDataBuffer,
573 if (!NT_SUCCESS(Status))
574 {
575 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
576 NtClose(TemplateHandle);
579 return FALSE;
580 }
581
582 /* Once again, ensure it is a mount point */
583 if (ReparseDataBuffer->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
584 {
585 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
586 NtClose(TemplateHandle);
589 return FALSE;
590 }
591
592 /* Get volume name */
593 SubstituteName = (PWSTR)((ULONG_PTR)ReparseDataBuffer->MountPointReparseBuffer.PathBuffer +
594 ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
595 if (IS_VOLUME_NAME(SubstituteName, ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength))
596 {
597 /* Prepare to define a new mount point for that volume */
598 RtlInitUnicodeString(&NewDirectory, lpNewDirectory);
599 NewDirectory.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewDirectory.Length + 2 * sizeof(WCHAR));
600 if (!NewDirectory.Buffer)
601 {
603 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
604 NtClose(TemplateHandle);
606 return FALSE;
607 }
608
609 RtlCopyMemory(&NewDirectory.Buffer, lpNewDirectory, NewDirectory.Length);
610 if (NewDirectory.Buffer[NewDirectory.Length / sizeof(WCHAR)] != L'\\')
611 {
612 NewDirectory.Buffer[NewDirectory.Length / sizeof(WCHAR)] = L'\\';
613 NewDirectory.Buffer[(NewDirectory.Length / sizeof(WCHAR)) + 1] = UNICODE_NULL;
614 }
615
616 /* Define a new mount point for that volume */
617 SetVolumeMountPointW(NewDirectory.Buffer, SubstituteName);
618
619 RtlFreeHeap(RtlGetProcessHeap(), 0, NewDirectory.Buffer);
620 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
621 NtClose(TemplateHandle);
623 return TRUE;
624 }
625
626 /* Otherwise copy data raw */
628 NULL,
629 NULL,
630 NULL,
633 ReparseDataBuffer,
634 ReparseDataBuffer->ReparseDataLength +
635 FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer),
636 NULL,
637 0);
638
639 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
640 NtClose(TemplateHandle);
642
643 if (NT_SUCCESS(Status))
644 {
645 return TRUE;
646 }
647
649 return FALSE;
650 }
651 /* In case it's not a reparse point, handle streams on the file */
652 else
653 {
654 for (StreamSize = 0x1000; ; StreamSize = StreamSize * 2)
655 {
656 FileStreamInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, StreamSize);
657 if (!FileStreamInfo)
658 {
661 break;
662 }
663
664 /* Query stream information */
665 Status = NtQueryInformationFile(TemplateHandle,
667 FileStreamInfo,
668 StreamSize,
670 if (NT_SUCCESS(Status))
671 {
672 break;
673 }
674
675 RtlFreeHeap(RtlGetProcessHeap(), 0, FileStreamInfo);
676 FileStreamInfo = NULL;
677
678 /* If it failed, ensure that's not because of too small buffer */
681 {
682 break;
683 }
684 }
685
687 {
688 if (FileStreamInfo)
689 {
690 RtlFreeHeap(RtlGetProcessHeap(), 0, FileStreamInfo);
691 }
692
693 NtClose(TemplateHandle);
695 return TRUE;
696 }
697
698#if 1
699 /* FIXME: TODO */
700 DPRINT1("Warning: streams copying is unimplemented!\n");
701 RtlFreeHeap(RtlGetProcessHeap(), 0, FileStreamInfo);
702 NtClose(TemplateHandle);
704#endif
705 return TRUE;
706 }
707}
708
709/*
710 * @implemented
711 */
712BOOL
713WINAPI
715{
716 PUNICODE_STRING PathNameW;
717
718 PathNameW = Basep8BitStringToStaticUnicodeString(lpPathName);
719 if (!PathNameW)
720 {
721 return FALSE;
722 }
723
724 return RemoveDirectoryW(PathNameW->Buffer);
725}
726
727/*
728 * @implemented
729 */
730BOOL
731WINAPI
733{
738 UNICODE_STRING NtPathU, PathName;
739 RTL_RELATIVE_NAME_U RelativeName;
740 PWSTR PathUBuffer, SubstituteName;
742 PREPARSE_DATA_BUFFER ReparseDataBuffer;
743 FILE_DISPOSITION_INFORMATION FileDispInfo;
745
746 /* Get relative name */
747 if (!RtlDosPathNameToRelativeNtPathName_U(lpPathName, &NtPathU, NULL, &RelativeName))
748 {
750 return FALSE;
751 }
752
753 /* Save buffer to allow later freeing */
754 PathUBuffer = NtPathU.Buffer;
755
756 /* If we have relative name (and root dir), use them instead */
757 if (RelativeName.RelativeName.Length != 0)
758 {
759 NtPathU.Length = RelativeName.RelativeName.Length;
760 NtPathU.MaximumLength = RelativeName.RelativeName.MaximumLength;
761 NtPathU.Buffer = RelativeName.RelativeName.Buffer;
762 }
763 else
764 {
765 RelativeName.ContainingDirectory = NULL;
766 }
767
769 &NtPathU,
771 RelativeName.ContainingDirectory,
772 NULL);
773
774 /* Try to open directory */
782 if (!NT_SUCCESS(Status))
783 {
784 /* We only accept failure for reparse points not being supported */
786 {
787 goto Cleanup;
788 }
789
790 /* Try to open, with reparse points support */
798 if (!NT_SUCCESS(Status))
799 {
800 goto Cleanup;
801 }
802
803 /* Success, mark directory */
804 goto MarkFileForDelete;
805 }
806
807 /* Get information about file (and reparse point) */
810 &FileTagInfo,
811 sizeof(FileTagInfo),
813 if (!NT_SUCCESS(Status))
814 {
815 /* FSD might not support querying reparse points information */
818 {
819 goto CleanupHandle;
820 }
821
822 /* If that's the case, then just delete directory */
823 goto MarkFileForDelete;
824 }
825
826 /* If that's not a reparse point, nothing more to do than just delete */
827 if (!(FileTagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
828 {
829 goto MarkFileForDelete;
830 }
831
832 /* Check if that's a mount point */
833 if (FileTagInfo.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
834 {
835 /* It's not */
837
838 /* So, try to reopen directory, ignoring mount point */
846 if (NT_SUCCESS(Status))
847 {
848 /* It succeed, we can safely delete directory (and ignore reparse point) */
849 goto MarkFileForDelete;
850 }
851
852 /* If it failed, only allow case where IO mount point was ignored */
854 {
855 goto Cleanup;
856 }
857
858 /* Reopen with reparse point support */
866 if (NT_SUCCESS(Status))
867 {
868 /* And mark for delete */
869 goto MarkFileForDelete;
870 }
871
872 goto Cleanup;
873 }
874
875 /* Here, we have a mount point, prepare to query information about it */
876 ReparseDataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
878 if (!ReparseDataBuffer)
879 {
880 RtlReleaseRelativeName(&RelativeName);
881 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
884 return FALSE;
885 }
886
887 /* Query */
890 NULL, 0,
891 ReparseDataBuffer,
894 NULL))
895 {
896 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
897 goto MarkFileForDelete;
898 }
899
900 /* Get volume name */
901 SubstituteName = (PWSTR)((ULONG_PTR)ReparseDataBuffer->MountPointReparseBuffer.PathBuffer +
902 ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
903 if (!IS_VOLUME_NAME(SubstituteName, ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength))
904 {
905 /* This is not a volume, we can safely delete */
906 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
907 goto MarkFileForDelete;
908 }
909
910 /* Prepare to delete mount point */
911 RtlInitUnicodeString(&PathName, lpPathName);
912 PathName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathName.Length + 2 * sizeof(WCHAR));
913 if (!PathName.Buffer)
914 {
915 RtlReleaseRelativeName(&RelativeName);
916 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
919 return FALSE;
920 }
921
922 RtlCopyMemory(&PathName.Buffer, lpPathName, PathName.Length);
923 if (PathName.Buffer[PathName.Length / sizeof(WCHAR)] != L'\\')
924 {
925 PathName.Buffer[PathName.Length / sizeof(WCHAR)] = L'\\';
926 PathName.Buffer[(PathName.Length / sizeof(WCHAR)) + 1] = UNICODE_NULL;
927 }
928
929 /* Delete mount point for that volume */
931 RtlFreeHeap(RtlGetProcessHeap(), 0, PathName.Buffer);
932 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
933
934 /* And mark directory for delete */
935MarkFileForDelete:
936 RtlReleaseRelativeName(&RelativeName);
937 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
938
939 /* Mark & set */
940 FileDispInfo.DeleteFile = TRUE;
943 &FileDispInfo,
947
948 if (!NT_SUCCESS(Status))
949 {
951 return FALSE;
952 }
953
954 return TRUE;
955
956CleanupHandle:
958
959Cleanup:
960 RtlReleaseRelativeName(&RelativeName);
961 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
963 return FALSE;
964}
965
966/* EOF */
static HANDLE DirectoryHandle
Definition: ObType.c:48
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define DPRINT1
Definition: precomp.h:8
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
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
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:32
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define SetLastError(x)
Definition: compat.h:752
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
#define ERROR_INVALID_NAME
Definition: compat.h:103
#define IS_VOLUME_NAME(s, l)
Definition: dir.c:21
#define SFN_LENGTH
Definition: dir.c:16
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:714
BOOL WINAPI CreateDirectoryExW(IN LPCWSTR lpTemplateDirectory, IN LPCWSTR lpNewDirectory, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:193
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
BOOL WINAPI CreateDirectoryExA(IN LPCSTR lpTemplateDirectory, IN LPCSTR lpNewDirectory, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:57
BOOL WINAPI RemoveDirectoryW(IN LPCWSTR lpPathName)
Definition: dir.c:732
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
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
VOID WINAPI BaseMarkFileForDelete(IN HANDLE FileHandle, IN ULONG FileAttributes)
Definition: utils.c:876
PUNICODE_STRING WINAPI Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
Definition: utils.c:188
static const WCHAR Cleanup[]
Definition: register.c:80
IN PVCB IN PDIRENT OUT PULONG EaLength
Definition: fatprocs.h:878
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
@ FileAttributeTagInformation
Definition: from_kernel.h:96
@ FileEaInformation
Definition: from_kernel.h:68
@ FileStreamInformation
Definition: from_kernel.h:83
@ FileBasicInformation
Definition: from_kernel.h:65
@ FileDispositionInformation
Definition: from_kernel.h:74
#define FILE_CREATE
Definition: from_kernel.h:55
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
Status
Definition: gdiplustypes.h:25
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSTATUS NTAPI NtQueryEaFile(IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN BOOLEAN ReturnSingleEntry, IN PVOID EaList OPTIONAL, IN ULONG EaListLength, IN PULONG EaIndex OPTIONAL, IN BOOLEAN RestartScan)
Definition: iofunc.c:2256
BOOL WINAPI SetVolumeMountPointW(IN LPCWSTR lpszVolumeMountPoint, IN LPCWSTR lpszVolumeName)
Definition: mntpoint.c:583
BOOL WINAPI DeleteVolumeMountPointW(IN LPCWSTR lpszVolumeMountPoint)
Definition: mntpoint.c:618
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSYSAPI ULONG NTAPI RtlIsDosDeviceName_U(_In_ PCWSTR Name)
VOID NTAPI RtlReleaseRelativeName(_In_ PRTL_RELATIVE_NAME_U RelativeName)
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_U(_In_ PCWSTR DosName, _Out_ PUNICODE_STRING NtName, _Out_ PCWSTR *PartName, _Out_ PRTL_RELATIVE_NAME_U RelativeName)
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 FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_ATTRIBUTE_VALID_FLAGS
Definition: nt_native.h:714
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_LIST_DIRECTORY
Definition: nt_native.h:629
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
NTSYSAPI NTSTATUS NTAPI NtSetInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
Definition: iofunc.c:3096
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
#define FILE_READ_EA
Definition: nt_native.h:638
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define DELETE
Definition: nt_native.h:57
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength)
#define FILE_ADD_FILE
Definition: nt_native.h:632
NTSYSAPI NTSTATUS NTAPI NtFsControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_IO_REPARSE_TAG_NOT_HANDLED
Definition: ntstatus.h:757
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define L(x)
Definition: ntvdm.h:50
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:97
#define FSCTL_SET_REPARSE_POINT
Definition: winioctl.h:98
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
struct _REPARSE_DATA_BUFFER::@318::@321 MountPointReparseBuffer
WCHAR PathBuffer[1]
Definition: shellext.h:176
USHORT ReparseDataLength
Definition: shellext.h:166
UNICODE_STRING RelativeName
Definition: rtltypes.h:1380
HANDLE ContainingDirectory
Definition: rtltypes.h:1381
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint16_t * PWSTR
Definition: typedefs.h:56
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_NOT_A_DIRECTORY
Definition: udferr_usr.h:169
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#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
#define WINAPI
Definition: msvc.h:6
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:263
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Out_ PIO_STATUS_BLOCK _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG _In_ ULONG _In_ ULONG _In_opt_ PVOID EaBuffer
Definition: iofuncs.h:845
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE
Definition: iotypes.h:7213
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7231
#define FAILED_ACCESS_ACE_FLAG
Definition: setypes.h:754
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185