ReactOS 0.4.16-dev-2274-gc61d98f
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/*
54 * @implemented
55 */
56BOOL
59 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
60{
64 UNICODE_STRING NtPathU;
65 PWSTR PathUBuffer, FilePart;
67 RTL_RELATIVE_NAME_U RelativeName;
69
70 /* Get relative name */
71 if (!RtlDosPathNameToRelativeNtPathName_U(lpPathName, &NtPathU, NULL, &RelativeName))
72 {
74 return FALSE;
75 }
76
77 /* Check if path length is < MAX_PATH (with space for file name).
78 * If not, prefix is required.
79 */
80 if (NtPathU.Length > (MAX_PATH - SFN_LENGTH) * sizeof(WCHAR) && lpPathName[0] != L'\\' &&
81 lpPathName[1] != L'\\' && lpPathName[2] != L'?' && lpPathName[3] != L'\\')
82 {
83 /* Get file name position and full path length */
84 Length = GetFullPathNameW(lpPathName, 0, NULL, &FilePart);
85 if (Length == 0)
86 {
87 RtlReleaseRelativeName(&RelativeName);
88 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU.Buffer);
90 return FALSE;
91 }
92
93 /* Keep place for 8.3 file name */
95 /* No prefix, so, must be smaller than MAX_PATH */
96 if (Length > MAX_PATH)
97 {
98 RtlReleaseRelativeName(&RelativeName);
99 RtlFreeHeap(GetProcessHeap(), 0, NtPathU.Buffer);
101 return FALSE;
102 }
103 }
104
105 /* Save buffer to allow later freeing */
106 PathUBuffer = NtPathU.Buffer;
107
108 /* If we have relative name (and root dir), use them instead */
109 if (RelativeName.RelativeName.Length != 0)
110 {
111 NtPathU.Length = RelativeName.RelativeName.Length;
112 NtPathU.MaximumLength = RelativeName.RelativeName.MaximumLength;
113 NtPathU.Buffer = RelativeName.RelativeName.Buffer;
114 }
115 else
116 {
117 RelativeName.ContainingDirectory = NULL;
118 }
119
121 &NtPathU,
123 RelativeName.ContainingDirectory,
124 (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));
125
130 NULL,
135 NULL,
136 0);
137
138 RtlReleaseRelativeName(&RelativeName);
139 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
140
141 if (NT_SUCCESS(Status))
142 {
144 return TRUE;
145 }
146
147 if (RtlIsDosDeviceName_U(lpPathName))
148 {
150 }
151
153 return FALSE;
154}
155
156/*
157 * @implemented
158 */
159BOOL
160WINAPI
161CreateDirectoryExW(IN LPCWSTR lpTemplateDirectory,
162 IN LPCWSTR lpNewDirectory,
163 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
164{
168 BOOL ReparsePoint = FALSE;
170 FILE_EA_INFORMATION FileEaInfo;
171 ULONG EaLength = 0, StreamSize;
174 PREPARSE_DATA_BUFFER ReparseDataBuffer;
175 HANDLE TemplateHandle, DirectoryHandle;
178 UNICODE_STRING NtPathU, NtTemplatePathU, NewDirectory;
179 RTL_RELATIVE_NAME_U RelativeName, TemplateRelativeName;
180 PWSTR TemplateBuffer, PathUBuffer, FilePart, SubstituteName;
181
182 /* Get relative name of the template */
183 if (!RtlDosPathNameToRelativeNtPathName_U(lpTemplateDirectory, &NtTemplatePathU, NULL, &TemplateRelativeName))
184 {
186 return FALSE;
187 }
188
189 /* Save buffer for further freeing */
190 TemplateBuffer = NtTemplatePathU.Buffer;
191
192 /* If we have relative name (and root dir), use them instead */
193 if (TemplateRelativeName.RelativeName.Length != 0)
194 {
195 NtTemplatePathU.Length = TemplateRelativeName.RelativeName.Length;
196 NtTemplatePathU.MaximumLength = TemplateRelativeName.RelativeName.MaximumLength;
197 NtTemplatePathU.Buffer = TemplateRelativeName.RelativeName.Buffer;
198 }
199 else
200 {
201 TemplateRelativeName.ContainingDirectory = NULL;
202 }
203
205 &NtTemplatePathU,
207 NULL,
208 NULL);
209
210 /* Open template directory */
211 Status = NtOpenFile(&TemplateHandle,
217 if (!NT_SUCCESS(Status))
218 {
220 {
221 RtlReleaseRelativeName(&TemplateRelativeName);
222 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
224 return FALSE;
225 }
226
227OpenWithoutReparseSupport:
228 /* Opening failed due to lacking reparse points support in the FSD, try without */
229 Status = NtOpenFile(&TemplateHandle,
235
236 if (!NT_SUCCESS(Status))
237 {
238 RtlReleaseRelativeName(&TemplateRelativeName);
239 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
241 return FALSE;
242 }
243
244 /* Request file attributes */
245 FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
246 Status = NtQueryInformationFile(TemplateHandle,
249 sizeof(FileBasicInfo),
251 if (!NT_SUCCESS(Status))
252 {
253 RtlReleaseRelativeName(&TemplateRelativeName);
254 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
255 CloseHandle(TemplateHandle);
257 return FALSE;
258
259 }
260 }
261 else
262 {
263 /* Request file attributes */
264 FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
265 Status = NtQueryInformationFile(TemplateHandle,
268 sizeof(FileBasicInfo),
270 if (!NT_SUCCESS(Status))
271 {
272 RtlReleaseRelativeName(&TemplateRelativeName);
273 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
274 CloseHandle(TemplateHandle);
276 return FALSE;
277
278 }
279
280 /* If it is a reparse point, then get information about it */
281 if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
282 {
283 Status = NtQueryInformationFile(TemplateHandle,
285 &FileTagInfo,
286 sizeof(FileTagInfo),
288 if (!NT_SUCCESS(Status))
289 {
290 RtlReleaseRelativeName(&TemplateRelativeName);
291 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
292 CloseHandle(TemplateHandle);
294 return FALSE;
295 }
296
297 /* Only mount points are supported, retry without if anything different */
298 if (FileTagInfo.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
299 {
300 CloseHandle(TemplateHandle);
301 goto OpenWithoutReparseSupport;
302 }
303
304 /* Mark we are playing with a reparse point */
305 ReparsePoint = TRUE;
306 }
307 }
308
309 /* Get relative name of the directory */
310 if (!RtlDosPathNameToRelativeNtPathName_U(lpNewDirectory, &NtPathU, NULL, &RelativeName))
311 {
312 RtlReleaseRelativeName(&TemplateRelativeName);
313 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
314 NtClose(TemplateHandle);
316 return FALSE;
317 }
318
319 /* Save its buffer for further freeing */
320 PathUBuffer = NtPathU.Buffer;
321
322 /* Template & directory can't be the same */
323 if (RtlEqualUnicodeString(&NtPathU,
324 &NtTemplatePathU,
325 TRUE))
326 {
327 RtlReleaseRelativeName(&RelativeName);
328 RtlReleaseRelativeName(&TemplateRelativeName);
329 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
330 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
331 NtClose(TemplateHandle);
333 return FALSE;
334 }
335
336 RtlReleaseRelativeName(&TemplateRelativeName);
337 RtlFreeHeap(RtlGetProcessHeap(), 0, TemplateBuffer);
338
339 /* Check if path length is < MAX_PATH (with space for file name).
340 * If not, prefix is required.
341 */
342 if (NtPathU.Length > (MAX_PATH - SFN_LENGTH) * sizeof(WCHAR) && lpNewDirectory[0] != L'\\' &&
343 lpNewDirectory[1] != L'\\' && lpNewDirectory[2] != L'?' && lpNewDirectory[3] != L'\\')
344 {
345 /* Get file name position and full path length */
346 Length = GetFullPathNameW(lpNewDirectory, 0, NULL, &FilePart);
347 if (Length == 0)
348 {
349 RtlReleaseRelativeName(&RelativeName);
350 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
351 CloseHandle(TemplateHandle);
353 return FALSE;
354 }
355
356 /* Keep place for 8.3 file name */
358 /* No prefix, so, must be smaller than MAX_PATH */
359 if (Length > MAX_PATH)
360 {
361 RtlReleaseRelativeName(&RelativeName);
362 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
363 CloseHandle(TemplateHandle);
365 return FALSE;
366 }
367 }
368
369 /* If we have relative name (and root dir), use them instead */
370 if (RelativeName.RelativeName.Length != 0)
371 {
372 NtPathU.Length = RelativeName.RelativeName.Length;
373 NtPathU.MaximumLength = RelativeName.RelativeName.MaximumLength;
374 NtPathU.Buffer = RelativeName.RelativeName.Buffer;
375 }
376 else
377 {
378 RelativeName.ContainingDirectory = NULL;
379 }
380
381 /* Get extended attributes */
382 Status = NtQueryInformationFile(TemplateHandle,
384 &FileEaInfo,
385 sizeof(FileEaInfo),
387 if (!NT_SUCCESS(Status))
388 {
389 RtlReleaseRelativeName(&RelativeName);
390 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
391 CloseHandle(TemplateHandle);
393 return FALSE;
394 }
395
396 /* Start reading extended attributes */
397 if (FileEaInfo.EaSize != 0)
398 {
399 for (EaLength = FileEaInfo.EaSize * 2; ; EaLength = EaLength * 2)
400 {
401 /* Allocate buffer for reading */
402 EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, EaLength);
403 if (!EaBuffer)
404 {
405 RtlReleaseRelativeName(&RelativeName);
406 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
407 CloseHandle(TemplateHandle);
409 return FALSE;
410 }
411
412 /* Query EAs */
413 Status = NtQueryEaFile(TemplateHandle,
415 EaBuffer,
416 EaLength,
417 FALSE,
418 NULL,
419 0,
420 NULL,
421 TRUE);
422 if (!NT_SUCCESS(Status))
423 {
424 RtlFreeHeap(RtlGetProcessHeap(), 0, EaBuffer);
426 }
427
428 /* If we don't fail because of too small buffer, stop here */
431 {
433 break;
434 }
435 }
436 }
437
439 &NtPathU,
441 RelativeName.ContainingDirectory,
442 (lpSecurityAttributes ? lpSecurityAttributes->lpSecurityDescriptor : NULL));
443
444 /* Ensure attributes are valid */
446
447 /* Create the new directory */
453 NULL,
454 FileBasicInfo.FileAttributes,
459 EaBuffer,
460 EaLength);
461 if (!NT_SUCCESS(Status))
462 {
464 {
465 /* If creation failed, it might be because FSD doesn't support reparse points
466 * Retry without asking for such support in case template is not a reparse point
467 */
468 if (!ReparsePoint)
469 {
475 NULL,
476 FileBasicInfo.FileAttributes,
481 EaBuffer,
482 EaLength);
483 }
484 else
485 {
486 RtlReleaseRelativeName(&RelativeName);
487 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
488 if (EaBuffer)
489 {
490 RtlFreeHeap(RtlGetProcessHeap(), 0, EaBuffer);
491 }
492 CloseHandle(TemplateHandle);
494 return FALSE;
495 }
496 }
497 }
498
499 RtlReleaseRelativeName(&RelativeName);
500 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
501 if (EaBuffer)
502 {
503 RtlFreeHeap(RtlGetProcessHeap(), 0, EaBuffer);
504 }
505
506 if (!NT_SUCCESS(Status))
507 {
508 NtClose(TemplateHandle);
509 if (RtlIsDosDeviceName_U(lpNewDirectory))
510 {
512 }
514 return FALSE;
515 }
516
517 /* If template is a reparse point, copy reparse data */
518 if (ReparsePoint)
519 {
520 ReparseDataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
522 if (!ReparseDataBuffer)
523 {
524 NtClose(TemplateHandle);
527 return FALSE;
528 }
529
530 /* First query data */
531 Status = NtFsControlFile(TemplateHandle,
532 NULL,
533 NULL,
534 NULL,
537 NULL,
538 0,
539 ReparseDataBuffer,
541 if (!NT_SUCCESS(Status))
542 {
543 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
544 NtClose(TemplateHandle);
547 return FALSE;
548 }
549
550 /* Once again, ensure it is a mount point */
551 if (ReparseDataBuffer->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
552 {
553 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
554 NtClose(TemplateHandle);
557 return FALSE;
558 }
559
560 /* Get volume name */
561 SubstituteName = (PWSTR)((ULONG_PTR)ReparseDataBuffer->MountPointReparseBuffer.PathBuffer +
562 ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
563 if (IS_VOLUME_NAME(SubstituteName, ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength))
564 {
565 /* Prepare to define a new mount point for that volume */
566 RtlInitUnicodeString(&NewDirectory, lpNewDirectory);
567 NewDirectory.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewDirectory.Length + 2 * sizeof(WCHAR));
568 if (!NewDirectory.Buffer)
569 {
571 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
572 NtClose(TemplateHandle);
574 return FALSE;
575 }
576
577 RtlCopyMemory(&NewDirectory.Buffer, lpNewDirectory, NewDirectory.Length);
578 if (NewDirectory.Buffer[NewDirectory.Length / sizeof(WCHAR)] != L'\\')
579 {
580 NewDirectory.Buffer[NewDirectory.Length / sizeof(WCHAR)] = L'\\';
581 NewDirectory.Buffer[(NewDirectory.Length / sizeof(WCHAR)) + 1] = UNICODE_NULL;
582 }
583
584 /* Define a new mount point for that volume */
585 SetVolumeMountPointW(NewDirectory.Buffer, SubstituteName);
586
587 RtlFreeHeap(RtlGetProcessHeap(), 0, NewDirectory.Buffer);
588 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
589 NtClose(TemplateHandle);
591 return TRUE;
592 }
593
594 /* Otherwise copy data raw */
596 NULL,
597 NULL,
598 NULL,
601 ReparseDataBuffer,
602 ReparseDataBuffer->ReparseDataLength +
603 FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer),
604 NULL,
605 0);
606
607 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
608 NtClose(TemplateHandle);
610
611 if (NT_SUCCESS(Status))
612 {
613 return TRUE;
614 }
615
617 return FALSE;
618 }
619 /* In case it's not a reparse point, handle streams on the file */
620 else
621 {
622 for (StreamSize = 0x1000; ; StreamSize = StreamSize * 2)
623 {
624 FileStreamInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, StreamSize);
625 if (!FileStreamInfo)
626 {
629 break;
630 }
631
632 /* Query stream information */
633 Status = NtQueryInformationFile(TemplateHandle,
636 StreamSize,
638 if (NT_SUCCESS(Status))
639 {
640 break;
641 }
642
643 RtlFreeHeap(RtlGetProcessHeap(), 0, FileStreamInfo);
645
646 /* If it failed, ensure that's not because of too small buffer */
649 {
650 break;
651 }
652 }
653
655 {
656 if (FileStreamInfo)
657 {
658 RtlFreeHeap(RtlGetProcessHeap(), 0, FileStreamInfo);
659 }
660
661 NtClose(TemplateHandle);
663 return TRUE;
664 }
665
666#if 1
667 /* FIXME: TODO */
668 DPRINT1("Warning: streams copying is unimplemented!\n");
669 RtlFreeHeap(RtlGetProcessHeap(), 0, FileStreamInfo);
670 NtClose(TemplateHandle);
672#endif
673 return TRUE;
674 }
675}
676
677/*
678 * @implemented
679 */
680BOOL
681WINAPI
683{
684 PUNICODE_STRING PathNameW;
685
686 PathNameW = Basep8BitStringToStaticUnicodeString(lpPathName);
687 if (!PathNameW)
688 {
689 return FALSE;
690 }
691
692 return RemoveDirectoryW(PathNameW->Buffer);
693}
694
695/*
696 * @implemented
697 */
698BOOL
699WINAPI
701{
706 UNICODE_STRING NtPathU, PathName;
707 RTL_RELATIVE_NAME_U RelativeName;
708 PWSTR PathUBuffer, SubstituteName;
710 PREPARSE_DATA_BUFFER ReparseDataBuffer;
711 FILE_DISPOSITION_INFORMATION FileDispInfo;
713
714 /* Get relative name */
715 if (!RtlDosPathNameToRelativeNtPathName_U(lpPathName, &NtPathU, NULL, &RelativeName))
716 {
718 return FALSE;
719 }
720
721 /* Save buffer to allow later freeing */
722 PathUBuffer = NtPathU.Buffer;
723
724 /* If we have relative name (and root dir), use them instead */
725 if (RelativeName.RelativeName.Length != 0)
726 {
727 NtPathU.Length = RelativeName.RelativeName.Length;
728 NtPathU.MaximumLength = RelativeName.RelativeName.MaximumLength;
729 NtPathU.Buffer = RelativeName.RelativeName.Buffer;
730 }
731 else
732 {
733 RelativeName.ContainingDirectory = NULL;
734 }
735
737 &NtPathU,
739 RelativeName.ContainingDirectory,
740 NULL);
741
742 /* Try to open directory */
750 if (!NT_SUCCESS(Status))
751 {
752 /* We only accept failure for reparse points not being supported */
754 {
755 goto Cleanup;
756 }
757
758 /* Try to open, with reparse points support */
766 if (!NT_SUCCESS(Status))
767 {
768 goto Cleanup;
769 }
770
771 /* Success, mark directory */
772 goto MarkFileForDelete;
773 }
774
775 /* Get information about file (and reparse point) */
778 &FileTagInfo,
779 sizeof(FileTagInfo),
781 if (!NT_SUCCESS(Status))
782 {
783 /* FSD might not support querying reparse points information */
786 {
787 goto CleanupHandle;
788 }
789
790 /* If that's the case, then just delete directory */
791 goto MarkFileForDelete;
792 }
793
794 /* If that's not a reparse point, nothing more to do than just delete */
795 if (!(FileTagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
796 {
797 goto MarkFileForDelete;
798 }
799
800 /* Check if that's a mount point */
801 if (FileTagInfo.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
802 {
803 /* It's not */
805
806 /* So, try to reopen directory, ignoring mount point */
814 if (NT_SUCCESS(Status))
815 {
816 /* It succeed, we can safely delete directory (and ignore reparse point) */
817 goto MarkFileForDelete;
818 }
819
820 /* If it failed, only allow case where IO mount point was ignored */
822 {
823 goto Cleanup;
824 }
825
826 /* Reopen with reparse point support */
834 if (NT_SUCCESS(Status))
835 {
836 /* And mark for delete */
837 goto MarkFileForDelete;
838 }
839
840 goto Cleanup;
841 }
842
843 /* Here, we have a mount point, prepare to query information about it */
844 ReparseDataBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0,
846 if (!ReparseDataBuffer)
847 {
848 RtlReleaseRelativeName(&RelativeName);
849 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
852 return FALSE;
853 }
854
855 /* Query */
858 NULL, 0,
859 ReparseDataBuffer,
862 NULL))
863 {
864 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
865 goto MarkFileForDelete;
866 }
867
868 /* Get volume name */
869 SubstituteName = (PWSTR)((ULONG_PTR)ReparseDataBuffer->MountPointReparseBuffer.PathBuffer +
870 ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameOffset);
871 if (!IS_VOLUME_NAME(SubstituteName, ReparseDataBuffer->MountPointReparseBuffer.SubstituteNameLength))
872 {
873 /* This is not a volume, we can safely delete */
874 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
875 goto MarkFileForDelete;
876 }
877
878 /* Prepare to delete mount point */
879 RtlInitUnicodeString(&PathName, lpPathName);
880 PathName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathName.Length + 2 * sizeof(WCHAR));
881 if (!PathName.Buffer)
882 {
883 RtlReleaseRelativeName(&RelativeName);
884 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
887 return FALSE;
888 }
889
890 RtlCopyMemory(PathName.Buffer, lpPathName, PathName.Length);
891 if (PathName.Buffer[(PathName.Length / sizeof(WCHAR)) - 1] != L'\\')
892 {
893 PathName.Buffer[PathName.Length / sizeof(WCHAR)] = L'\\';
894 PathName.Buffer[(PathName.Length / sizeof(WCHAR)) + 1] = UNICODE_NULL;
895 }
896
897 /* Delete mount point for that volume */
899 RtlFreeHeap(RtlGetProcessHeap(), 0, PathName.Buffer);
900 RtlFreeHeap(RtlGetProcessHeap(), 0, ReparseDataBuffer);
901
902 /* And mark directory for delete */
903MarkFileForDelete:
904 RtlReleaseRelativeName(&RelativeName);
905 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
906
907 /* Mark & set */
908 FileDispInfo.DeleteFile = TRUE;
911 &FileDispInfo,
915
916 if (!NT_SUCCESS(Status))
917 {
919 return FALSE;
920 }
921
922 return TRUE;
923
924CleanupHandle:
926
927Cleanup:
928 RtlReleaseRelativeName(&RelativeName);
929 RtlFreeHeap(RtlGetProcessHeap(), 0, PathUBuffer);
931 return FALSE;
932}
933
934/* 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:616
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#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:33
#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:682
BOOL WINAPI CreateDirectoryExW(IN LPCWSTR lpTemplateDirectory, IN LPCWSTR lpNewDirectory, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:161
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:58
BOOL WINAPI RemoveDirectoryW(IN LPCWSTR lpPathName)
Definition: dir.c:700
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
VOID WINAPI BaseMarkFileForDelete(IN HANDLE FileHandle, IN ULONG FileAttributes)
Definition: utils.c:877
PUNICODE_STRING WINAPI Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
Definition: utils.c:189
static const WCHAR Cleanup[]
Definition: register.c:80
#define L(x)
Definition: resources.c:13
IN PVCB IN PDIRENT OUT PULONG EaLength
Definition: fatprocs.h:879
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:2260
@ FileBasicInfo
Definition: minwinbase.h:304
@ FileStreamInfo
Definition: minwinbase.h:311
BOOL WINAPI SetVolumeMountPointW(IN LPCWSTR lpszVolumeMountPoint, IN LPCWSTR lpszVolumeName)
Definition: mntpoint.c:518
BOOL WINAPI DeleteVolumeMountPointW(IN LPCWSTR lpszVolumeMountPoint)
Definition: mntpoint.c:553
#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:3953
#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
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
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define STATUS_IO_REPARSE_TAG_NOT_HANDLED
Definition: ntstatus.h:879
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:753
#define FSCTL_SET_REPARSE_POINT
Definition: winioctl.h:754
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:167
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
WCHAR PathBuffer[1]
Definition: shellext.h:176
struct _REPARSE_DATA_BUFFER::@298::@301 MountPointReparseBuffer
USHORT ReparseDataLength
Definition: shellext.h:166
UNICODE_STRING RelativeName
Definition: rtltypes.h:1374
HANDLE ContainingDirectory
Definition: rtltypes.h:1375
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
_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:228
#define ERROR_FILENAME_EXCED_RANGE
Definition: winerror.h:385
_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:7216
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7234
#define FAILED_ACCESS_ACE_FLAG
Definition: setypes.h:754
const char * LPCSTR
Definition: xmlstorage.h:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
__wchar_t WCHAR
Definition: xmlstorage.h:180