ReactOS 0.4.16-dev-340-g0540c21
move.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/move.c
5 * PURPOSE: Directory functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * Gerhard W. Gruber (sparhawk_at_gmx.at)
8 * Dmitry Philippov (shedon@mail.ru)
9 * Pierre Schweitzer (pierre@reactos.org)
10 */
11
12/* INCLUDES *****************************************************************/
13
14#include <k32.h>
15#include <malloc.h>
16
17#define NDEBUG
18#include <debug.h>
20
21/* GLOBALS *****************************************************************/
22
23/* DEFINES *****************************************************************/
25{
30
31/* FUNCTIONS ****************************************************************/
32
89 _In_ PUNICODE_STRING ExistingPath,
90 _In_ PUNICODE_STRING NewPath,
91 _In_ INT KeyId,
92 _In_ BOOL CreateIfNotFound)
93{
94#define STRING_LENGTH 0x400
97 PVOID Buffer, BufferBegin;
99 PWSTR PendingOperations, BufferWrite;
100 ULONG DataSize, BufferLength, StringLength = STRING_LENGTH;
101 UNICODE_STRING SessionManagerString, PendingOperationsString;
102 /* +6 because a INT shouldn't take more than 6 chars. Especially given the call path */
103 WCHAR PendingOperationsBuffer[sizeof(L"PendingFileRenameOperations") / sizeof(WCHAR) + 6];
104
105 RtlInitUnicodeString(&SessionManagerString,
106 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager");
107
108 /* Select appropriate key for adding our file */
109 if (KeyId == 1)
110 {
111 PendingOperations = L"PendingFileRenameOperations";
112 }
113 else
114 {
115 RtlStringCbPrintfW(PendingOperationsBuffer,
116 sizeof(PendingOperationsBuffer),
117 L"PendingFileRenameOperations%d", KeyId);
118 PendingOperations = PendingOperationsBuffer;
119 }
120 RtlInitUnicodeString(&PendingOperationsString, PendingOperations);
121
123 &SessionManagerString,
125 NULL, NULL);
126
127 /* Open parent key */
133 {
138 }
139
140 if (!NT_SUCCESS(Status))
141 {
142 return Status;
143 }
144
145 /* Reserve enough to read previous string + to append ours with required null chars */
146 BufferLength = NewPath->Length + ExistingPath->Length + STRING_LENGTH + 3 * sizeof(UNICODE_NULL);
147
148 while (TRUE)
149 {
150 /* Allocate output buffer */
151 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
152 if (Buffer == NULL)
153 {
155 return STATUS_NO_MEMORY;
156 }
157
159 &PendingOperationsString,
161 Buffer, StringLength, &DataSize);
163 {
164 break;
165 }
166
167 /* If buffer was too small, reallocate one which is big enough */
168 StringLength = DataSize;
169 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
170 BufferLength = ExistingPath->Length + StringLength + NewPath->Length + 3 * sizeof(UNICODE_NULL);
171 /* Check we didn't overflow */
172 if (BufferLength < StringLength)
173 {
176 }
177 }
178
179 /* Check if it existed; if not, create only IF asked to */
180 if (!NT_SUCCESS(Status) && (Status != STATUS_OBJECT_NAME_NOT_FOUND || !CreateIfNotFound))
181 {
183 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
184 return Status;
185 }
186
187 if (!NT_SUCCESS(Status))
188 {
189 /* We didn't find any: we create, so use complete buffer */
190 BufferBegin = Buffer;
191 BufferWrite = Buffer;
192 }
193 else
194 {
196
197 /* Get data, the buffer beginning, and where data should be appended
198 * (minus NULL char: this is REG_MULTI_SZ, it already includes double
199 * termination, but we keep only one). */
200 BufferBegin = PartialInfo->Data;
201 BufferWrite = (PWSTR)((ULONG_PTR)PartialInfo->Data + PartialInfo->DataLength - sizeof(UNICODE_NULL));
202 }
203
204 /* First copy existing */
205 RtlCopyMemory(BufferWrite, ExistingPath->Buffer, ExistingPath->Length);
206 BufferWrite += ExistingPath->Length / sizeof(WCHAR);
207 /* And append null char */
208 *BufferWrite = UNICODE_NULL;
209 ++BufferWrite;
210 /* Append destination */
211 RtlCopyMemory(BufferWrite, NewPath->Buffer, NewPath->Length);
212 BufferWrite += NewPath->Length / sizeof(WCHAR);
213 /* And append two null char (end of string) */
214 *BufferWrite = UNICODE_NULL;
215 ++BufferWrite;
216 *BufferWrite = UNICODE_NULL;
217
218 /* Set new value */
220 &PendingOperationsString,
221 0, REG_MULTI_SZ, BufferBegin,
222 (ULONG_PTR)BufferWrite - (ULONG_PTR)BufferBegin + sizeof(WCHAR));
223
225 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
226
227 return Status;
228}
229
230
231/*
232 * @implemented
233 */
234DWORD
235WINAPI
237 IN HANDLE NewHandle,
238 OUT PWSTR ComputerName,
239 IN OUT PULONG ComputerNameLength)
240{
241 BOOL Query = FALSE;
243 PWSTR AbsolutePath, EndOfName;
244 USHORT AbsolutePathLength, NameLength;
246 WCHAR DeviceName[] = {'A', ':', '\0'}; /* Init to something, will be set later */
247 UNICODE_STRING UncString = RTL_CONSTANT_STRING(L"\\??\\UNC\\");
248 UNICODE_STRING GlobalString = RTL_CONSTANT_STRING(L"\\??\\");
249
250 DPRINT("BasepGetComputerNameFromNtPath(%wZ, %p, %p, %lu)\n",
251 NewPath, NewHandle, ComputerName, ComputerNameLength);
252
253 /* If it's an UNC path */
254 if (RtlPrefixUnicodeString(&UncString, NewPath, TRUE))
255 {
256 /* Check for broken caller */
257 if (NewPath->Length <= UncString.Length)
258 {
259 return ERROR_BAD_PATHNAME;
260 }
261
262 /* Skip UNC prefix */
263 AbsolutePath = &NewPath->Buffer[UncString.Length / sizeof(WCHAR)];
264 AbsolutePathLength = NewPath->Length - UncString.Length;
265
266 /* And query DFS */
267 Query = TRUE;
268 }
269 /* Otherwise, we have to be in global (NT path!), with drive letter */
270 else if (RtlPrefixUnicodeString(&GlobalString, NewPath, TRUE) && NewPath->Buffer[5] == ':')
271 {
272 /* Path is like that: \??\C:\Complete Path\To File.ext */
273 /* Get the letter and upcase it if required */
274 Letter = NewPath->Buffer[4];
275 if (Letter >= 'a' && Letter <= 'z')
276 {
277 Letter -= ('a' - 'A');
278 }
279 DeviceName[0] = Letter;
280
281 /* Query the associated DOS device */
283 {
284 return GetLastError();
285 }
286
287 /* If that's a network share */
288 if (TargetDevice == wcsstr(TargetDevice, L"\\Device\\LanmanRedirector\\;"))
289 {
290 /* Path is like that: \Device\LanmanRedirector\;C:0000000000000000\Complete Path\To File.ext */
291 /* Check we have the correct drive letter */
292 if (TargetDevice[26] == DeviceName[0] &&
293 TargetDevice[27] == ':')
294 {
295 /* Check for the path begin, computer name is before */
296 PWSTR Path = wcschr(&TargetDevice[28], L'\\');
297 if (Path == NULL)
298 {
299 return ERROR_BAD_PATHNAME;
300 }
301
302 AbsolutePath = Path + 1;
303 AbsolutePathLength = sizeof(WCHAR) * (ARRAYSIZE(TargetDevice) - (AbsolutePath - TargetDevice));
304 }
305 else
306 {
307 return ERROR_BAD_PATHNAME;
308 }
309 }
310 /* If it's a local device */
311 else if (TargetDevice == wcsstr(TargetDevice, L"\\Device\\Harddisk")
312 || TargetDevice == wcsstr(TargetDevice, L"\\Device\\CdRom")
313 || TargetDevice == wcsstr(TargetDevice, L"\\Device\\Floppy"))
314 {
315 /* Just query the computer name */
316 if (!GetComputerNameW(ComputerName, ComputerNameLength))
317 {
318 return GetLastError();
319 }
320
321 return ERROR_SUCCESS;
322 }
323 /* If it's a DFS share */
324 else if (TargetDevice == wcsstr(TargetDevice, L"\\Device\\WinDfs\\"))
325 {
326 /* Obviously, query DFS */
327 Query = TRUE;
328 }
329 else
330 {
331 return ERROR_BAD_PATHNAME;
332 }
333 }
334 else
335 {
336 return ERROR_BAD_PATHNAME;
337 }
338
339 /* Query DFS, currently not implemented - shouldn't be missing in ReactOS yet ;-) */
340 if (Query)
341 {
342 UNIMPLEMENTED_DBGBREAK("Querying DFS not implemented!\n");
343 AbsolutePath = NULL;
344 AbsolutePathLength = 0;
345 }
346
347 /* Now, properly extract the computer name from the full path */
348 EndOfName = AbsolutePath;
349 if (AbsolutePathLength)
350 {
351 for (NameLength = 0; NameLength < AbsolutePathLength; NameLength += sizeof(WCHAR))
352 {
353 /* Look for the next \, it will be the end of computer name */
354 if (EndOfName[0] == L'\\')
355 {
356 break;
357 }
358 /* Computer name cannot contain ., if we get to that point, something went wrong... */
359 else if (EndOfName[0] == L'.')
360 {
361 return ERROR_BAD_PATHNAME;
362 }
363
364 ++EndOfName;
365 }
366 }
367
368 NameLength = EndOfName - AbsolutePath;
369 /* Check we didn't overflow and that our computer name isn't ill-formed */
370 if (NameLength >= AbsolutePathLength || NameLength >= MAX_COMPUTERNAME_LENGTH * sizeof(WCHAR))
371 {
372 return ERROR_BAD_PATHNAME;
373 }
374
375 /* Check we can fit */
376 if (NameLength + sizeof(UNICODE_NULL) > *ComputerNameLength * sizeof(WCHAR))
377 {
379 }
380
381 /* Write, zero and done! */
382 RtlCopyMemory(ComputerName, AbsolutePath, NameLength);
383 *ComputerNameLength = NameLength / sizeof(WCHAR);
384 ComputerName[NameLength / sizeof(WCHAR)] = UNICODE_NULL;
385
386 return ERROR_SUCCESS;
387}
388
389
390/*
391 * @implemented
392 */
394WINAPI
397 IN HANDLE NewHandle,
398 IN PUNICODE_STRING NewPath)
399{
401 ULONG ComputerNameLength, FileAttributes;
402 WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
403 OEM_STRING ComputerNameStringA;
404 CHAR ComputerNameStringBuffer[MAX_PATH + 1];
405 UNICODE_STRING ComputerNameStringW;
407 FILE_BASIC_INFORMATION FileBasicInfo;
408 HANDLE hFullWrite;
409 struct
410 {
412 CHAR Buffer[(MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR)];
413 } FileTrackingInfo;
414
415 DPRINT("BasepNotifyTrackingService(%p, %p, %p, %wZ)\n",
416 *ExistingHandle, ObjectAttributes, NewHandle, NewPath);
417
419 ComputerNameLength = ARRAYSIZE(ComputerName);
420
421 /* Attempt to get computer name of target handle */
422 if (BasepGetComputerNameFromNtPath(NewPath, NewHandle, ComputerName, &ComputerNameLength))
423 {
424 /* If we failed to get it, we will just notify with the handle */
425 FileTrackingInfo.ObjectInformationLength = 0;
426 }
427 else
428 {
429 /* Convert the retrieved computer name to ANSI and attach it to the notification */
430 RtlInitEmptyAnsiString(&ComputerNameStringA,
431 ComputerNameStringBuffer,
432 sizeof(ComputerNameStringBuffer));
433
434 RtlInitUnicodeString(&ComputerNameStringW, ComputerName);
435 Status = RtlUnicodeStringToOemString(&ComputerNameStringA, &ComputerNameStringW, FALSE);
436 if (!NT_SUCCESS(Status))
437 {
438 return Status;
439 }
440
441 RtlCopyMemory(FileTrackingInfo.ObjectInformation, ComputerNameStringA.Buffer, ComputerNameStringA.Length);
442 FileTrackingInfo.ObjectInformation[ComputerNameStringA.Length] = ANSI_NULL;
443 FileTrackingInfo.ObjectInformationLength = ComputerNameStringA.Length + 1;
444 }
445
446 /* Attach the handle we moved */
447 FileTrackingInfo.DestinationFile = NewHandle;
448
449 /* Final, notify */
450 Status = NtSetInformationFile(*ExistingHandle,
452 &FileTrackingInfo,
453 sizeof(FileTrackingInfo),
456 {
457 return Status;
458 }
459
460 /* If we get here, we got access denied error, this comes from a
461 * read-only flag. So, close the file, in order to reopen it with enough
462 * rights to remove said flag and reattempt notification.
463 */
464 CloseHandle(*ExistingHandle);
465
466 /* Reopen it, to be able to change the destination file attributes */
467 Status = NtOpenFile(ExistingHandle,
473 if (!NT_SUCCESS(Status))
474 {
475 *ExistingHandle = INVALID_HANDLE_VALUE;
476 return Status;
477 }
478
479 /* Get the file attributes */
480 Status = NtQueryInformationFile(*ExistingHandle,
482 &FileBasicInfo,
483 sizeof(FileBasicInfo),
485 if (!NT_SUCCESS(Status))
486 {
487 return Status;
488 }
489
490 /* Get rid of the read only flag */
491 FileAttributes = FileBasicInfo.FileAttributes & ~FILE_ATTRIBUTE_READONLY;
492 RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
493 FileBasicInfo.FileAttributes = FileAttributes;
494
495 /* Attempt... */
496 Status = NtSetInformationFile(*ExistingHandle,
498 &FileBasicInfo,
499 sizeof(FileBasicInfo),
501 if (!NT_SUCCESS(Status))
502 {
503 return Status;
504 }
505
506 /* Now, reopen with maximum accesses to notify */
507 Status = NtOpenFile(&hFullWrite,
513 if (NT_SUCCESS(Status))
514 {
515 NtClose(*ExistingHandle);
516 *ExistingHandle = hFullWrite;
517
518 /* Full success, notify! */
519 Status = NtSetInformationFile(*ExistingHandle,
521 &FileTrackingInfo,
522 sizeof(FileTrackingInfo),
524 }
525
526 /* If opening with full access failed or if notify failed, restore read-only */
527 if (!NT_SUCCESS(Status))
528 {
530
531 Status = NtSetInformationFile(*ExistingHandle,
533 &FileBasicInfo,
534 sizeof(FileBasicInfo),
536 }
537
538 /* We're done */
539 return Status;
540}
541
542
543/*
544 * @implemented
545 */
547WINAPI
549 OUT PUNICODE_STRING RelativeNtName,
550 OUT LPWSTR * NtName,
556{
557 RTL_RELATIVE_NAME_U RelativeName;
561 ULONG IntShareAccess;
562 BOOLEAN HasRelative = FALSE;
563
565 {
566 /* Zero output */
567 RtlInitEmptyUnicodeString(RelativeNtName, NULL, 0);
568 *NtName = NULL;
569
570 if (!RtlDosPathNameToRelativeNtPathName_U(File, RelativeNtName, NULL, &RelativeName))
571 {
574 }
575
576 HasRelative = TRUE;
577 *NtName = RelativeNtName->Buffer;
578
579 if (RelativeName.RelativeName.Length)
580 {
581 RelativeNtName->Length = RelativeName.RelativeName.Length;
582 RelativeNtName->MaximumLength = RelativeName.RelativeName.MaximumLength;
583 RelativeNtName->Buffer = RelativeName.RelativeName.Buffer;
584 }
585 else
586 {
587 RelativeName.ContainingDirectory = NULL;
588 }
589
591 RelativeNtName,
593 RelativeName.ContainingDirectory,
594 NULL);
595 /* Force certain flags here, given ops we'll do */
596 IntShareAccess = ShareAccess | FILE_SHARE_READ | FILE_SHARE_WRITE;
598
599 /* We'll try to read reparse tag */
604 IntShareAccess,
606 if (NT_SUCCESS(Status))
607 {
608 /* Attempt the read */
611 &TagInfo,
612 sizeof(TagInfo),
614
615 /* Return if failure with a status that wouldn't mean the FSD cannot support reparse points */
616 if (!NT_SUCCESS(Status) &&
618 {
620 }
621
622 if (NT_SUCCESS(Status))
623 {
624 /* This cannot happen on mount points */
627 {
629 }
630 }
631
634
635 IntShareAccess = ShareAccess | FILE_SHARE_READ | FILE_SHARE_DELETE;
636 }
638 {
639 IntShareAccess = ShareAccess | FILE_SHARE_READ | FILE_SHARE_WRITE;
640 }
641 else
642 {
644 }
645
646 /* Reattempt to open normally, following reparse point if needed */
651 IntShareAccess,
653 }
655 {
656 if (HasRelative)
657 {
658 RtlReleaseRelativeName(&RelativeName);
659 }
660 }
661 _SEH2_END;
662
663 return Status;
664}
665
666
667/*
668 * @implemented
669 */
670DWORD
671WINAPI
673 IN LARGE_INTEGER TotalBytesTransferred,
674 IN LARGE_INTEGER StreamSize,
675 IN LARGE_INTEGER StreamBytesTransferred,
676 IN DWORD dwStreamNumber,
677 IN DWORD dwCallbackReason,
678 IN HANDLE hSourceFile,
679 IN HANDLE hDestinationFile,
680 IN LPVOID lpData OPTIONAL)
681{
682 DWORD Ret = 0;
684
685 if (Context->Flags & MOVEFILE_WRITE_THROUGH)
686 {
687 if (!dwCallbackReason)
688 {
689 if (StreamBytesTransferred.QuadPart == StreamSize.QuadPart)
690 {
691 FlushFileBuffers(hDestinationFile);
692 }
693 }
694 }
695
696 if (Context->UserRoutine)
697 {
698 Ret = Context->UserRoutine(TotalFileSize,
699 TotalBytesTransferred,
700 StreamSize,
701 StreamBytesTransferred,
702 dwStreamNumber,
703 dwCallbackReason,
704 hSourceFile,
705 hDestinationFile,
706 Context->UserData);
707 }
708
709 return Ret;
710}
711
712
713/*
714 * @implemented
715 */
716BOOL
717WINAPI
719 IN LPCWSTR lpNewFileName,
720 IN LPPROGRESS_ROUTINE lpProgressRoutine,
721 IN LPVOID lpData,
723{
725 PWSTR NewBuffer;
727 COPY_PROGRESS_CONTEXT CopyContext;
729 PFILE_RENAME_INFORMATION RenameInfo;
730 UNICODE_STRING NewPathU, ExistingPathU;
732 HANDLE SourceHandle = INVALID_HANDLE_VALUE, NewHandle, ExistingHandle;
733 BOOL Ret = FALSE, ReplaceIfExists, DelayUntilReboot, AttemptReopenWithoutReparse;
734
735 DPRINT("MoveFileWithProgressW(%S, %S, %p, %p, %x)\n",
736 lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, dwFlags);
737
738 NewPathU.Buffer = NULL;
739 ExistingPathU.Buffer = NULL;
740
742 {
743 /* Don't allow renaming to a disk */
744 if (lpNewFileName && RtlIsDosDeviceName_U(lpNewFileName))
745 {
748 }
749
750 ReplaceIfExists = !!(dwFlags & MOVEFILE_REPLACE_EXISTING);
751
752 /* Get file path */
753 if (!RtlDosPathNameToNtPathName_U(lpExistingFileName, &ExistingPathU, NULL, NULL))
754 {
757 }
758
759 /* Sanitize input */
760 DelayUntilReboot = !!(dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT);
761 if (DelayUntilReboot && (dwFlags & MOVEFILE_CREATE_HARDLINK))
762 {
765 }
766
767 /* Unless we manage a proper opening, we'll attempt to reopen without reparse support */
768 AttemptReopenWithoutReparse = TRUE;
770 &ExistingPathU,
772 NULL,
773 NULL);
774 /* Attempt to open source file */
781 if (!NT_SUCCESS(Status))
782 {
783 /* If we failed and the file doesn't exist, don't attempt to reopen without reparse */
784 if (DelayUntilReboot &&
786 {
787 /* Here we don't fail completely, as we postpone the operation to reboot.
788 * File might exist afterwards, and we don't need a handle here. */
790 AttemptReopenWithoutReparse = FALSE;
791 }
792 /* If we failed for any reason than unsupported reparse, fail completely */
794 {
797 }
798 }
799 else
800 {
801 /* We managed to open, so query information */
804 &TagInfo,
805 sizeof(TagInfo),
807 if (!NT_SUCCESS(Status))
808 {
809 /* Do not tolerate any other error than something related to not supported operation */
811 {
814 }
815
816 /* Not a reparse point, no need to reopen, it's fine */
817 AttemptReopenWithoutReparse = FALSE;
818 }
819 /* Validate the reparse point (do we support it?) */
820 else if ((TagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
822 {
825 }
826 else
827 {
828 /* Mount point, let's rename it */
829 AttemptReopenWithoutReparse = FALSE;
830 }
831 }
832
833 /* Simply reopen if required */
834 if (AttemptReopenWithoutReparse)
835 {
842 if (!NT_SUCCESS(Status))
843 {
846 }
847 }
848
849 /* Nullify string if we're to use it */
850 if (DelayUntilReboot && !lpNewFileName)
851 {
852 RtlInitUnicodeString(&NewPathU, NULL);
853 }
854 /* Check whether path exists */
855 else if (!RtlDosPathNameToNtPathName_U(lpNewFileName, &NewPathU, NULL, NULL))
856 {
859 }
860
861 /* Handle postponed renaming */
862 if (DelayUntilReboot)
863 {
864 /* If new file exists and we're allowed to replace, then mark the path with ! */
865 if (ReplaceIfExists && NewPathU.Length)
866 {
867 NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewPathU.Length + sizeof(WCHAR));
868 if (NewBuffer == NULL)
869 {
872 }
873
874 NewBuffer[0] = L'!';
875 RtlCopyMemory(&NewBuffer[1], NewPathU.Buffer, NewPathU.Length);
876 NewPathU.Length += sizeof(WCHAR);
877 NewPathU.MaximumLength += sizeof(WCHAR);
878 RtlFreeHeap(RtlGetProcessHeap(), 0, NewPathU.Buffer);
879 NewPathU.Buffer = NewBuffer;
880 }
881
882 /* Check whether 'copy' renaming is allowed if required */
883 if ((RtlDetermineDosPathNameType_U(lpExistingFileName) == RtlPathTypeUncAbsolute) ||
885 {
887 }
888 else
889 {
890 /* First, probe 2nd key to see whether it exists - if so, it will be appended there */
891 Status = BasepMoveFileDelayed(&ExistingPathU, &NewPathU, 2, FALSE);
893 {
894 /* If doesn't exist, append to first key first, creating it if it doesn't exist */
895 Status = BasepMoveFileDelayed(&ExistingPathU, &NewPathU, 1, TRUE);
897 {
898 /* If it failed because it's too big, then create 2nd key and put it there */
899 Status = BasepMoveFileDelayed(&ExistingPathU, &NewPathU, 2, TRUE);
900 }
901 }
902 }
903
904 /* If we failed at some point, return the error */
905 if (!NT_SUCCESS(Status))
906 {
909 }
910
911 Ret = TRUE;
913 }
914
915 /* At that point, we MUST have a source handle */
917
918 /* Allocate renaming buffer and fill it */
919 RenameInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0,
920 NewPathU.Length + sizeof(FILE_RENAME_INFORMATION));
921 if (RenameInfo == NULL)
922 {
925 }
926
927 RtlCopyMemory(&RenameInfo->FileName, NewPathU.Buffer, NewPathU.Length);
928 RenameInfo->ReplaceIfExists = ReplaceIfExists;
929 RenameInfo->RootDirectory = NULL;
930 RenameInfo->FileNameLength = NewPathU.Length;
931
932 /* Attempt to rename the file */
935 RenameInfo,
936 NewPathU.Length + sizeof(FILE_RENAME_INFORMATION),
939 RtlFreeHeap(RtlGetProcessHeap(), 0, RenameInfo);
940 if (NT_SUCCESS(Status))
941 {
942 /* If it succeed, all fine, quit */
943 Ret = TRUE;
945 }
946 /* If we failed for any other reason than not the same device, fail.
947 * If we failed because of different devices, only allow renaming if user allowed copy.
948 */
950 {
951 /* ReactOS HACK! To be removed once all FSD have proper renaming support.
952 * Just leave status to error and leave. */
954 {
955 DPRINT1("Forcing copy, renaming not supported by FSD\n");
956 }
957 else
958 {
961 }
962 }
963
964 /* Close source file */
967
968 /* Issue the copy of the file */
969 CopyContext.Flags = dwFlags;
970 CopyContext.UserRoutine = lpProgressRoutine;
971 CopyContext.UserData = lpData;
972 NewHandle = INVALID_HANDLE_VALUE;
973 ExistingHandle = INVALID_HANDLE_VALUE;
974
975 Ret = BasepCopyFileExW(lpExistingFileName,
976 lpNewFileName,
978 &CopyContext,
979 NULL,
980 (!ReplaceIfExists ? COPY_FILE_FAIL_IF_EXISTS : 0)
982 0,
983 &ExistingHandle,
984 &NewHandle);
985 if (!Ret)
986 {
987 /* If it failed, don't leak any handle */
988 if (ExistingHandle != INVALID_HANDLE_VALUE)
989 {
990 CloseHandle(ExistingHandle);
991 ExistingHandle = INVALID_HANDLE_VALUE;
992 }
993 }
994 else if (ExistingHandle != INVALID_HANDLE_VALUE)
995 {
996 if (NewHandle != INVALID_HANDLE_VALUE)
997 {
998 /* If copying succeed, notify */
999 Status = BasepNotifyTrackingService(&ExistingHandle,
1001 NewHandle,
1002 &NewPathU);
1003 if (!NT_SUCCESS(Status))
1004 {
1005 /* Fail in case it had to succeed */
1007 {
1008 if (NewHandle != INVALID_HANDLE_VALUE)
1009 CloseHandle(NewHandle);
1010 NewHandle = INVALID_HANDLE_VALUE;
1011 DeleteFileW(lpNewFileName);
1012 Ret = FALSE;
1014 }
1015 }
1016 }
1017
1018 CloseHandle(ExistingHandle);
1019 ExistingHandle = INVALID_HANDLE_VALUE;
1020 }
1021
1022 /* In case copy worked, close file */
1023 if (NewHandle != INVALID_HANDLE_VALUE)
1024 {
1025 CloseHandle(NewHandle);
1026 NewHandle = INVALID_HANDLE_VALUE;
1027 }
1028
1029 /* If it succeed, delete source file */
1030 if (Ret)
1031 {
1032 if (!DeleteFileW(lpExistingFileName))
1033 {
1034 /* Reset file attributes if required */
1035 SetFileAttributesW(lpExistingFileName, FILE_ATTRIBUTE_NORMAL);
1036 DeleteFileW(lpExistingFileName);
1037 }
1038 }
1039 }
1041 {
1044
1045 RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingPathU.Buffer);
1046 RtlFreeHeap(RtlGetProcessHeap(), 0, NewPathU.Buffer);
1047 }
1048 _SEH2_END;
1049
1050 return Ret;
1051}
1052
1053
1054/*
1055 * @implemented
1056 */
1057BOOL
1058WINAPI
1060 IN LPCSTR lpNewFileName OPTIONAL,
1061 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
1062 IN LPVOID lpData OPTIONAL,
1064{
1065 BOOL Ret;
1066 UNICODE_STRING ExistingFileNameW, NewFileNameW;
1067
1068 if (!Basep8BitStringToDynamicUnicodeString(&ExistingFileNameW, lpExistingFileName))
1069 {
1070 return FALSE;
1071 }
1072
1073 if (lpNewFileName)
1074 {
1075 if (!Basep8BitStringToDynamicUnicodeString(&NewFileNameW, lpNewFileName))
1076 {
1077 RtlFreeUnicodeString(&ExistingFileNameW);
1078 return FALSE;
1079 }
1080 }
1081 else
1082 {
1083 NewFileNameW.Buffer = NULL;
1084 }
1085
1086 Ret = MoveFileWithProgressW(ExistingFileNameW.Buffer,
1087 NewFileNameW.Buffer,
1088 lpProgressRoutine,
1089 lpData,
1090 dwFlags);
1091
1092 RtlFreeUnicodeString(&ExistingFileNameW);
1093 RtlFreeUnicodeString(&NewFileNameW);
1094
1095 return Ret;
1096}
1097
1098
1099/*
1100 * @implemented
1101 */
1102BOOL
1103WINAPI
1104MoveFileW(IN LPCWSTR lpExistingFileName,
1105 IN LPCWSTR lpNewFileName)
1106{
1107 return MoveFileWithProgressW(lpExistingFileName,
1108 lpNewFileName,
1109 NULL,
1110 NULL,
1112}
1113
1114
1115/*
1116 * @implemented
1117 */
1118BOOL
1119WINAPI
1120MoveFileExW(IN LPCWSTR lpExistingFileName,
1121 IN LPCWSTR lpNewFileName OPTIONAL,
1123{
1124 return MoveFileWithProgressW(lpExistingFileName,
1125 lpNewFileName,
1126 NULL,
1127 NULL,
1128 dwFlags);
1129}
1130
1131
1132/*
1133 * @implemented
1134 */
1135BOOL
1136WINAPI
1137MoveFileA(IN LPCSTR lpExistingFileName,
1138 IN LPCSTR lpNewFileName)
1139{
1140 return MoveFileWithProgressA(lpExistingFileName,
1141 lpNewFileName,
1142 NULL,
1143 NULL,
1145}
1146
1147
1148/*
1149 * @implemented
1150 */
1151BOOL
1152WINAPI
1153MoveFileExA(IN LPCSTR lpExistingFileName,
1154 IN LPCSTR lpNewFileName OPTIONAL,
1156{
1157 return MoveFileWithProgressA(lpExistingFileName,
1158 lpNewFileName,
1159 NULL,
1160 NULL,
1161 dwFlags);
1162}
1163
1164/*
1165 * @implemented
1166 */
1167BOOL
1168WINAPI
1169ReplaceFileA(IN LPCSTR lpReplacedFileName,
1170 IN LPCSTR lpReplacementFileName,
1171 IN LPCSTR lpBackupFileName OPTIONAL,
1172 IN DWORD dwReplaceFlags,
1173 IN LPVOID lpExclude,
1174 IN LPVOID lpReserved)
1175{
1176 BOOL Ret;
1177 UNICODE_STRING ReplacedFileNameW, ReplacementFileNameW, BackupFileNameW;
1178
1179 if (!lpReplacedFileName || !lpReplacementFileName || lpExclude || lpReserved ||
1180 (dwReplaceFlags & ~(REPLACEFILE_WRITE_THROUGH | REPLACEFILE_IGNORE_MERGE_ERRORS)))
1181 {
1183 return FALSE;
1184 }
1185
1186 if (!Basep8BitStringToDynamicUnicodeString(&ReplacedFileNameW, lpReplacedFileName))
1187 {
1188 return FALSE;
1189 }
1190
1191 if (!Basep8BitStringToDynamicUnicodeString(&ReplacementFileNameW, lpReplacementFileName))
1192 {
1193 RtlFreeUnicodeString(&ReplacedFileNameW);
1194 return FALSE;
1195 }
1196
1197 if (lpBackupFileName)
1198 {
1199 if (!Basep8BitStringToDynamicUnicodeString(&BackupFileNameW, lpBackupFileName))
1200 {
1201 RtlFreeUnicodeString(&ReplacementFileNameW);
1202 RtlFreeUnicodeString(&ReplacedFileNameW);
1203 return FALSE;
1204 }
1205 }
1206 else
1207 {
1208 BackupFileNameW.Buffer = NULL;
1209 }
1210
1211 Ret = ReplaceFileW(ReplacedFileNameW.Buffer,
1212 ReplacementFileNameW.Buffer,
1213 BackupFileNameW.Buffer,
1214 dwReplaceFlags, 0, 0);
1215
1216 if (lpBackupFileName)
1217 {
1218 RtlFreeUnicodeString(&BackupFileNameW);
1219 }
1220 RtlFreeUnicodeString(&ReplacementFileNameW);
1221 RtlFreeUnicodeString(&ReplacedFileNameW);
1222
1223 return Ret;
1224}
1225
1226/*
1227 * @unimplemented
1228 */
1229BOOL
1230WINAPI
1232 LPCWSTR lpReplacedFileName,
1233 LPCWSTR lpReplacementFileName,
1234 LPCWSTR lpBackupFileName,
1235 DWORD dwReplaceFlags,
1236 LPVOID lpExclude,
1237 LPVOID lpReserved
1238 )
1239{
1240 HANDLE hReplaced = NULL, hReplacement = NULL;
1241 UNICODE_STRING NtReplacedName = { 0, 0, NULL };
1242 UNICODE_STRING NtReplacementName = { 0, 0, NULL };
1245 BOOL Ret = FALSE;
1248 PVOID Buffer = NULL ;
1249
1250 if (dwReplaceFlags)
1251 FIXME("Ignoring flags %x\n", dwReplaceFlags);
1252
1253 /* First two arguments are mandatory */
1254 if (!lpReplacedFileName || !lpReplacementFileName)
1255 {
1257 return FALSE;
1258 }
1259
1260 /* Back it up */
1261 if(lpBackupFileName)
1262 {
1263 if(!CopyFileW(lpReplacedFileName, lpBackupFileName, FALSE))
1264 {
1265 Error = GetLastError();
1266 goto Cleanup ;
1267 }
1268 }
1269
1270 /* Open the "replaced" file for reading and writing */
1271 if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &NtReplacedName, NULL, NULL)))
1272 {
1274 goto Cleanup;
1275 }
1276
1278 &NtReplacedName,
1280 NULL,
1281 NULL);
1282
1283 Status = NtOpenFile(&hReplaced,
1289
1290 if (!NT_SUCCESS(Status))
1291 {
1294 else
1296 goto Cleanup;
1297 }
1298
1299 /* Blank it */
1300 SetEndOfFile(hReplaced) ;
1301
1302 /*
1303 * Open the replacement file for reading, writing, and deleting
1304 * (deleting is needed when finished)
1305 */
1306 if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName, &NtReplacementName, NULL, NULL)))
1307 {
1309 goto Cleanup;
1310 }
1311
1313 &NtReplacementName,
1315 NULL,
1316 NULL);
1317
1318 Status = NtOpenFile(&hReplacement,
1322 0,
1324
1325 if (!NT_SUCCESS(Status))
1326 {
1328 goto Cleanup;
1329 }
1330
1331 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 0x10000) ;
1332 if (!Buffer)
1333 {
1335 goto Cleanup ;
1336 }
1337 while (Status != STATUS_END_OF_FILE)
1338 {
1339 Status = NtReadFile(hReplacement, NULL, NULL, NULL, &IoStatusBlock, Buffer, 0x10000, NULL, NULL) ;
1340 if (NT_SUCCESS(Status))
1341 {
1344 if (!NT_SUCCESS(Status))
1345 {
1347 goto Cleanup;
1348 }
1349 }
1350 else if (Status != STATUS_END_OF_FILE)
1351 {
1353 goto Cleanup;
1354 }
1355 }
1356
1357 Ret = TRUE;
1358
1359 /* Perform resource cleanup */
1360Cleanup:
1361 if (hReplaced) NtClose(hReplaced);
1362 if (hReplacement) NtClose(hReplacement);
1363 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1364
1365 if (NtReplacementName.Buffer)
1366 RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName.Buffer);
1367 if (NtReplacedName.Buffer)
1368 RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName.Buffer);
1369
1370 /* If there was an error, set the error code */
1371 if(!Ret)
1372 {
1373 TRACE("ReplaceFileW failed (error=%lu)\n", Error);
1375 }
1376 return Ret;
1377}
1378
1379
1380/*
1381 * @implemented
1382 */
1383BOOL
1384WINAPI
1386{
1387 ACCESS_MASK SourceAccess;
1388 UNICODE_STRING NtSource, NtDestination;
1389 LPWSTR RelativeSource, RelativeDestination;
1390 HANDLE SourceHandle, DestinationHandle;
1391 OBJECT_ATTRIBUTES ObjectAttributesSource, ObjectAttributesDestination;
1392 NTSTATUS Status, OldStatus = STATUS_SUCCESS;
1393 ACCESS_MASK DestAccess;
1395 FILE_BASIC_INFORMATION SourceInformation, DestinationInformation;
1396 FILE_DISPOSITION_INFORMATION FileDispositionInfo;
1397
1398 DPRINT("PrivMoveFileIdentityW(%S, %S, %x)\n", lpSource, lpDestination, dwFlags);
1399
1401 RtlInitEmptyUnicodeString(&NtSource, NULL, 0);
1402 RelativeSource = NULL;
1403 DestinationHandle = INVALID_HANDLE_VALUE;
1404 RtlInitEmptyUnicodeString(&NtDestination, NULL, 0);
1405 RelativeDestination = NULL;
1406
1407 /* FILE_WRITE_DATA is required for later on notification */
1408 SourceAccess = FILE_READ_ATTRIBUTES | FILE_WRITE_DATA;
1410 {
1411 SourceAccess |= DELETE;
1412 }
1413
1414 _SEH2_TRY
1415 {
1416 /* We will loop twice:
1417 * First we attempt to open with FILE_WRITE_DATA for notification.
1418 * If it fails and we have flag for non-trackable files, we retry
1419 * without FILE_WRITE_DATA.
1420 * If that one fails, then, we quit for real.
1421 */
1422 while (TRUE)
1423 {
1424 Status = BasepOpenFileForMove(lpSource,
1425 &NtSource,
1426 &RelativeSource,
1427 &SourceHandle,
1428 &ObjectAttributesSource,
1429 SourceAccess,
1432 if (NT_SUCCESS(Status))
1433 {
1434 break;
1435 }
1436
1437 /* If we already attempted the opening without FILE_WRITE_DATA
1438 * or if we cannot move on non-trackable files, fail.
1439 */
1440 if (!(SourceAccess & FILE_WRITE_DATA) || !(dwFlags & PRIV_ALLOW_NON_TRACKABLE))
1441 {
1443 }
1444
1445 if (RelativeSource)
1446 {
1447 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSource);
1448 RelativeSource = NULL;
1449 }
1450
1452 {
1455 }
1456
1457 SourceAccess &= ~FILE_WRITE_DATA;
1458
1459 /* Remember fist failure in the path */
1460 if (NT_SUCCESS(OldStatus))
1461 {
1462 OldStatus = Status;
1463 }
1464 }
1465
1466 DestAccess = FILE_WRITE_ATTRIBUTES;
1467 /* If we could preserve FILE_WRITE_DATA for source, attempt to
1468 * get it for destination, still for notification purposes. */
1469 if (SourceAccess & FILE_WRITE_DATA)
1470 {
1471 DestAccess |= FILE_WRITE_DATA;
1472 }
1473
1474 /* cf comment for first loop */
1475 while (TRUE)
1476 {
1477 Status = BasepOpenFileForMove(lpDestination,
1478 &NtDestination,
1479 &RelativeDestination,
1480 &DestinationHandle,
1481 &ObjectAttributesDestination,
1482 DestAccess,
1485 if (NT_SUCCESS(Status))
1486 {
1487 break;
1488 }
1489
1490 /* If we already attempted the opening without FILE_WRITE_DATA
1491 * or if we cannot move on non-trackable files, fail.
1492 */
1493 if (!(DestAccess & FILE_WRITE_DATA) || !(dwFlags & PRIV_ALLOW_NON_TRACKABLE))
1494 {
1496 }
1497
1498 if (RelativeDestination)
1499 {
1500 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeDestination);
1501 RelativeDestination = NULL;
1502 }
1503
1504 if (DestinationHandle != INVALID_HANDLE_VALUE)
1505 {
1506 NtClose(DestinationHandle);
1507 DestinationHandle = INVALID_HANDLE_VALUE;
1508 }
1509
1510 DestAccess &= ~FILE_WRITE_DATA;
1511
1512 /* Remember fist failure in the path */
1513 if (NT_SUCCESS(OldStatus))
1514 {
1515 OldStatus = Status;
1516 }
1517 }
1518
1519 /* Get the creation time from source */
1522 &SourceInformation,
1523 sizeof(SourceInformation),
1525 if (NT_SUCCESS(Status))
1526 {
1527 /* Then, prepare to set it for destination */
1528 RtlZeroMemory(&DestinationInformation, sizeof(DestinationInformation));
1529 DestinationInformation.CreationTime.QuadPart = SourceInformation.CreationTime.QuadPart;
1530
1531 /* And set it, that's all folks! */
1532 Status = NtSetInformationFile(DestinationHandle,
1534 &DestinationInformation,
1535 sizeof(DestinationInformation),
1537 }
1538
1539 if (!NT_SUCCESS(Status))
1540 {
1542 {
1544 }
1545
1546 /* Remember the failure for later notification */
1547 if (NT_SUCCESS(OldStatus))
1548 {
1549 OldStatus = Status;
1550 }
1551 }
1552
1553 /* If we could open with FILE_WRITE_DATA both source and destination,
1554 * then, notify
1555 */
1556 if (DestAccess & FILE_WRITE_DATA && SourceAccess & FILE_WRITE_DATA)
1557 {
1559 &ObjectAttributesSource,
1560 DestinationHandle,
1561 &NtDestination);
1562 if (!NT_SUCCESS(Status))
1563 {
1565 {
1566 if (NT_SUCCESS(OldStatus))
1567 OldStatus = Status;
1568
1569 /* Reset status, we allow non trackable files */
1571 }
1572 }
1573 }
1574 }
1576 {
1577 if (RelativeSource)
1578 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSource);
1579
1580 if (RelativeDestination)
1581 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeDestination);
1582 }
1583 _SEH2_END;
1584
1585 /* If caller asked for source deletion, if everything succeed, proceed */
1587 {
1588 FileDispositionInfo.DeleteFile = TRUE;
1589
1592 &FileDispositionInfo,
1593 sizeof(FileDispositionInfo),
1595 }
1596
1597 /* Cleanup/close portion */
1598 if (DestinationHandle != INVALID_HANDLE_VALUE)
1599 {
1600 NtClose(DestinationHandle);
1601 }
1602
1604 {
1606 }
1607
1608 /* Set last error if any, and quit */
1609 if (NT_SUCCESS(Status))
1610 {
1611 if (!NT_SUCCESS(OldStatus))
1612 {
1613 BaseSetLastNTError(OldStatus);
1614 }
1615 }
1616 else
1617 {
1619 }
1620
1621 return NT_SUCCESS(Status);
1622}
1623
1624/* EOF */
WCHAR Letter
unsigned char BOOLEAN
PRTL_UNICODE_STRING_BUFFER Path
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
#define FILE_DELETE_ON_CLOSE
Definition: constants.h:494
#define DEBUG_CHANNEL(args)
Definition: rdesktop.h:159
#define DPRINT1
Definition: precomp.h:8
BOOL Query(LPCTSTR *ServiceArgs, DWORD ArgCount, BOOL bExtended)
Definition: query.c:292
#define FIXME(fmt,...)
Definition: precomp.h:53
BOOL Error
Definition: chkdsk.c:66
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
Definition: bufpool.h:45
Definition: File.h:16
BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:446
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
#define ERROR_SUCCESS
Definition: deptool.c:10
#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 ARRAYSIZE(array)
Definition: filtermapper.c:47
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
DWORD WINAPI QueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:542
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
BOOL BasepCopyFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, IN LPVOID lpData OPTIONAL, IN LPBOOL pbCancel OPTIONAL, IN DWORD dwCopyFlags, IN DWORD dwBasepFlags, OUT LPHANDLE lpExistingHandle, OUT LPHANDLE lpNewHandle)
Definition: copy.c:202
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:794
BOOL WINAPI FlushFileBuffers(IN HANDLE hFile)
Definition: fileinfo.c:25
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1004
struct _COPY_PROGRESS_CONTEXT COPY_PROGRESS_CONTEXT
BOOL WINAPI MoveFileWithProgressW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine, IN LPVOID lpData, IN DWORD dwFlags)
Definition: move.c:718
BOOL WINAPI MoveFileA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName)
Definition: move.c:1137
BOOL WINAPI ReplaceFileA(IN LPCSTR lpReplacedFileName, IN LPCSTR lpReplacementFileName, IN LPCSTR lpBackupFileName OPTIONAL, IN DWORD dwReplaceFlags, IN LPVOID lpExclude, IN LPVOID lpReserved)
Definition: move.c:1169
BOOL WINAPI MoveFileExA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1153
BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileName, LPCWSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved)
Definition: move.c:1231
NTSTATUS WINAPI BasepMoveFileDelayed(_In_ PUNICODE_STRING ExistingPath, _In_ PUNICODE_STRING NewPath, _In_ INT KeyId, _In_ BOOL CreateIfNotFound)
Adds an entry in the "PendingFileRenameOperations" registry value, that is parsed at boot-time by SMS...
Definition: move.c:88
DWORD WINAPI BasepMoveFileCopyProgress(IN LARGE_INTEGER TotalFileSize, IN LARGE_INTEGER TotalBytesTransferred, IN LARGE_INTEGER StreamSize, IN LARGE_INTEGER StreamBytesTransferred, IN DWORD dwStreamNumber, IN DWORD dwCallbackReason, IN HANDLE hSourceFile, IN HANDLE hDestinationFile, IN LPVOID lpData OPTIONAL)
Definition: move.c:672
NTSTATUS WINAPI BasepOpenFileForMove(IN LPCWSTR File, OUT PUNICODE_STRING RelativeNtName, OUT LPWSTR *NtName, OUT PHANDLE FileHandle, OUT POBJECT_ATTRIBUTES ObjectAttributes, IN ACCESS_MASK DesiredAccess, IN ULONG ShareAccess, IN ULONG OpenOptions)
Definition: move.c:548
BOOL WINAPI MoveFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1120
struct _COPY_PROGRESS_CONTEXT * PCOPY_PROGRESS_CONTEXT
BOOL WINAPI MoveFileWithProgressA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName OPTIONAL, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, IN LPVOID lpData OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1059
BOOL WINAPI MoveFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName)
Definition: move.c:1104
BOOL WINAPI PrivMoveFileIdentityW(IN LPCWSTR lpSource, IN LPCWSTR lpDestination, IN DWORD dwFlags)
Definition: move.c:1385
DWORD WINAPI BasepGetComputerNameFromNtPath(IN PUNICODE_STRING NewPath, IN HANDLE NewHandle, OUT PWSTR ComputerName, IN OUT PULONG ComputerNameLength)
Definition: move.c:236
#define STRING_LENGTH
NTSTATUS WINAPI BasepNotifyTrackingService(IN OUT PHANDLE ExistingHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE NewHandle, IN PUNICODE_STRING NewPath)
Definition: move.c:395
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
static const WCHAR Cleanup[]
Definition: register.c:80
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT ShareAccess
Definition: create.c:4147
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
#define MOVEFILE_WRITE_THROUGH
Definition: filesup.h:30
#define MOVEFILE_REPLACE_EXISTING
Definition: filesup.h:28
#define MOVEFILE_COPY_ALLOWED
Definition: filesup.h:29
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE _In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Out_ PIO_STATUS_BLOCK _In_opt_ PLARGE_INTEGER _In_ ULONG FileAttributes
Definition: fltkernel.h:1236
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
@ FileRenameInformation
Definition: from_kernel.h:71
@ FileTrackingInformation
Definition: from_kernel.h:97
@ FileLinkInformation
Definition: from_kernel.h:72
@ FileAttributeTagInformation
Definition: from_kernel.h:96
@ FileBasicInformation
Definition: from_kernel.h:65
@ FileDispositionInformation
Definition: from_kernel.h:74
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
#define FILE_OPEN_NO_RECALL
Definition: from_kernel.h:47
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
Status
Definition: gdiplustypes.h:25
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
#define OBJ_OPENIF
Definition: winternl.h:229
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define PRIV_ALLOW_NON_TRACKABLE
Definition: kernel32.h:134
#define kernel32file
Definition: kernel32.h:6
#define PRIV_DELETE_ON_SUCCESS
Definition: kernel32.h:133
#define ASSERT(a)
Definition: mode.c:44
#define FILE_ATTRIBUTE_DEVICE
Definition: disk.h:27
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
_Must_inspect_result_ _Out_ PNDIS_STATUS _Out_ PNDIS_STATUS _Out_ PNDIS_HANDLE _Out_ PUINT _In_ UINT _In_ NDIS_HANDLE _In_ NDIS_HANDLE _In_ PNDIS_STRING _In_ UINT OpenOptions
Definition: ndis.h:6017
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
_In_ HANDLE SourceHandle
Definition: obfuncs.h:429
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI ULONG NTAPI RtlIsDosDeviceName_U(_In_ PCWSTR Name)
VOID NTAPI RtlReleaseRelativeName(_In_ PRTL_RELATIVE_NAME_U RelativeName)
NTSYSAPI RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(_In_ PCWSTR Path)
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_U(_In_ PCWSTR DosName, _Out_ PUNICODE_STRING NtName, _Out_ PCWSTR *PartName, _Out_ PRTL_RELATIVE_NAME_U RelativeName)
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)
@ RtlPathTypeUncAbsolute
Definition: rtltypes.h:472
#define _In_
Definition: no_sal2.h:158
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
NTSYSAPI NTSTATUS NTAPI NtSetValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
Definition: ntapi.c:859
#define FILE_WRITE_DATA
Definition: nt_native.h:631
#define WRITE_DAC
Definition: nt_native.h:59
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
@ KeyValuePartialInformation
Definition: nt_native.h:1182
ULONG ACCESS_MASK
Definition: nt_native.h:40
NTSYSAPI NTSTATUS NTAPI NtWriteFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID WriteBuffer, IN ULONG WriteBufferLength, IN PLARGE_INTEGER FileOffset OPTIONAL, IN PULONG LockOperationKey OPTIONAL)
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
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 NtQueryValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define REG_OPTION_BACKUP_RESTORE
Definition: nt_native.h:1066
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
#define DELETE
Definition: nt_native.h:57
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define GENERIC_WRITE
Definition: nt_native.h:90
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
#define UNICODE_NULL
#define ANSI_NULL
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_NOT_SAME_DEVICE
Definition: ntstatus.h:448
NTSTRSAFEVAPI RtlStringCbPrintfW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1173
#define L(x)
Definition: ntvdm.h:50
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_FINALLY
Definition: pseh2_64.h:114
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define _SEH2_LEAVE
Definition: pseh2_64.h:167
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:167
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
NTSTATUS NTAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
#define DPRINT
Definition: sndvol32.h:73
#define TRACE(s)
Definition: solgame.cpp:4
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
LPPROGRESS_ROUTINE UserRoutine
Definition: move.c:27
LARGE_INTEGER CreationTime
Definition: nt_native.h:939
UNICODE_STRING RelativeName
Definition: rtltypes.h:1380
HANDLE ContainingDirectory
Definition: rtltypes.h:1381
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
#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
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_SHARING_VIOLATION
Definition: udferr_usr.h:154
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
STRING OEM_STRING
Definition: umtypes.h:203
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
#define COPY_FILE_FAIL_IF_EXISTS
Definition: winbase.h:231
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define COPY_FILE_OPEN_SOURCE_FOR_WRITE
Definition: winbase.h:233
DWORD(WINAPI * LPPROGRESS_ROUTINE)(_In_ LARGE_INTEGER, _In_ LARGE_INTEGER, _In_ LARGE_INTEGER, _In_ LARGE_INTEGER, _In_ DWORD, _In_ DWORD, _In_ HANDLE, _In_ HANDLE, _In_opt_ LPVOID)
Definition: winbase.h:1464
#define MOVEFILE_FAIL_IF_NOT_TRACKABLE
Definition: winbase.h:429
#define MOVEFILE_CREATE_HARDLINK
Definition: winbase.h:428
#define MOVEFILE_DELAY_UNTIL_REBOOT
Definition: winbase.h:426
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:269
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
#define WINAPI
Definition: msvc.h:6
#define ERROR_BUFFER_OVERFLOW
Definition: winerror.h:185
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define ERROR_BAD_PATHNAME
Definition: winerror.h:233
#define ERROR_UNABLE_TO_REMOVE_REPLACED
Definition: winerror.h:696
_Must_inspect_result_ __drv_aliasesMem PDEVICE_OBJECT _In_ PDEVICE_OBJECT TargetDevice
Definition: iofuncs.h:691
struct _FILE_TRACKING_INFORMATION FILE_TRACKING_INFORMATION
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7231
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175