ReactOS  0.4.13-dev-551-gf37fb1f
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  * UPDATE HISTORY:
11  * Created 01/11/98
12  * DP (29/07/2006)
13  * Fix some bugs in the add_boot_rename_entry function
14  */
15 
16 /* INCLUDES *****************************************************************/
17 
18 #include <k32.h>
19 #include <malloc.h>
20 #include <strsafe.h>
21 #define NDEBUG
22 #include <debug.h>
24 
25 /* GLOBALS *****************************************************************/
26 
27 /* DEFINES *****************************************************************/
28 typedef struct _COPY_PROGRESS_CONTEXT
29 {
34 
35 /* FUNCTIONS ****************************************************************/
36 /*
37  * @implemented
38  */
40 WINAPI
42  IN PUNICODE_STRING NewPath,
43  IN INT KeyId,
44  IN BOOL CreateIfNotFound)
45 {
46 #define STRING_LENGTH 0x400
49  PVOID Buffer, BufferBegin;
51  PWSTR PendingOperations, BufferWrite;
52  ULONG DataSize, BufferLength, StringLength = STRING_LENGTH;
53  UNICODE_STRING SessionManagerString, PendingOperationsString;
54  /* +6 because a INT shouldn't take more than 6 chars. Especially given the call path */
55  WCHAR PendingOperationsBuffer[sizeof(L"PendingFileRenameOperations") / sizeof(WCHAR) + 6];
56 
57  RtlInitUnicodeString(&SessionManagerString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager");
58 
59  /* Select appropriate key for adding our file */
60  if (KeyId == 1)
61  {
62  PendingOperations = L"PendingFileRenameOperations";
63  }
64  else
65  {
66  StringCbPrintfW(PendingOperationsBuffer, sizeof(PendingOperationsBuffer), L"PendingFileRenameOperations%d", KeyId);
67  PendingOperations = PendingOperationsBuffer;
68  }
69  RtlInitUnicodeString(&PendingOperationsString, PendingOperations);
70 
72  &SessionManagerString,
74  NULL, NULL);
75 
76  /* Open parent key */
82  {
87  }
88 
89  if (!NT_SUCCESS(Status))
90  {
91  return Status;
92  }
93 
94  /* Reserve enough to read previous string + to append our with required null chars */
95  BufferLength = NewPath->Length + ExistingPath->Length + STRING_LENGTH + 3 * sizeof(UNICODE_NULL);
96 
97  while (TRUE)
98  {
99  /* Allocate output buffer */
100  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
101  if (Buffer == NULL)
102  {
104  return STATUS_NO_MEMORY;
105  }
106 
108  &PendingOperationsString,
110  Buffer, StringLength, &DataSize);
112  {
113  break;
114  }
115 
116  /* If buffer was too small, then, reallocate one which is big enough */
117  StringLength = DataSize;
118  RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
119  BufferLength = ExistingPath->Length + StringLength + NewPath->Length + 3 * sizeof(UNICODE_NULL);
120  /* Check we didn't overflow */
121  if (BufferLength < StringLength)
122  {
125  }
126  }
127 
128  /* Check if it existed - if not, create only IF asked to */
129  if (!NT_SUCCESS(Status) && (Status != STATUS_OBJECT_NAME_NOT_FOUND || !CreateIfNotFound))
130  {
132  RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
133  return Status;
134  }
135 
136  if (!NT_SUCCESS(Status))
137  {
138  /* We didn't find any - ie, we create, so use complete buffer */
139  BufferBegin = Buffer;
140  BufferWrite = Buffer;
141  }
142  else
143  {
145 
146  /* Get data, our buffer begin and then where we should append data
147  * (- null char, this is REG_MULTI_SZ, it already includes double termination, we keep only one)
148  */
149  BufferBegin = PartialInfo->Data;
150  BufferWrite = (PWSTR)((ULONG_PTR)PartialInfo->Data + PartialInfo->DataLength - sizeof(UNICODE_NULL));
151  }
152 
153  /* First copy existing */
154  RtlCopyMemory(BufferWrite, ExistingPath->Buffer, ExistingPath->Length);
155  BufferWrite += ExistingPath->Length / sizeof(WCHAR);
156  /* And append null char */
157  *BufferWrite = UNICODE_NULL;
158  ++BufferWrite;
159  /* Append destination */
160  RtlCopyMemory(BufferWrite, NewPath->Buffer, NewPath->Length);
161  BufferWrite += NewPath->Length / sizeof(WCHAR);
162  /* And append two null char (end of string) */
163  *BufferWrite = UNICODE_NULL;
164  ++BufferWrite;
165  *BufferWrite = UNICODE_NULL;
166 
167  /* Set new value */
169  &PendingOperationsString,
170  0, REG_MULTI_SZ, BufferBegin,
171  (ULONG_PTR)BufferWrite - (ULONG_PTR)BufferBegin + sizeof(WCHAR));
172 
174  RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
175 
176  return Status;
177 }
178 
179 
180 /*
181  * @implemented
182  */
183 DWORD
184 WINAPI
186  IN HANDLE NewHandle,
187  OUT PWSTR ComputerName,
188  IN OUT PULONG ComputerNameLength)
189 {
190  BOOL Query = FALSE;
191  WCHAR Letter;
192  PWSTR AbsolutePath, EndOfName;
193  USHORT AbsolutePathLength, NameLength;
194  WCHAR TargetDevice[0x105];
195  WCHAR DeviceName[] = {'A', ':', '\0'}; /* Init to something, will be set later */
196  UNICODE_STRING UncString = RTL_CONSTANT_STRING(L"\\??\\UNC\\");
197  UNICODE_STRING GlobalString = RTL_CONSTANT_STRING(L"\\??\\");
198 
199  DPRINT("BasepGetComputerNameFromNtPath(%wZ, %p, %p, %lu)\n", NewPath, NewHandle, ComputerName, ComputerNameLength);
200 
201  /* If it's an UNC path */
202  if (RtlPrefixUnicodeString(&UncString, NewPath, TRUE))
203  {
204  /* Check for broken caller */
205  if (NewPath->Length <= UncString.Length)
206  {
207  return ERROR_BAD_PATHNAME;
208  }
209 
210  /* Skip UNC prefix */
211  AbsolutePath = &NewPath->Buffer[UncString.Length / sizeof(WCHAR)];
212  AbsolutePathLength = NewPath->Length - UncString.Length;
213 
214  /* And query DFS */
215  Query = TRUE;
216  }
217  /* Otherwise, we have to be in global (NT path!), with drive letter */
218  else if (RtlPrefixUnicodeString(&GlobalString, NewPath, TRUE) && NewPath->Buffer[5] == ':')
219  {
220  /* Path is like that: \??\C:\Complete Path\To File.ext */
221  /* Get the letter and upcase it if required */
222  Letter = NewPath->Buffer[4];
223  if (Letter >= 'a' && Letter <= 'z')
224  {
225  Letter -= ('a' - 'A');
226  }
227  DeviceName[0] = Letter;
228 
229  /* Query the associated DOS device */
231  {
232  return GetLastError();
233  }
234 
235  /* If that's a network share */
236  if (TargetDevice == wcsstr(TargetDevice, L"\\Device\\LanmanRedirector\\;"))
237  {
238  /* Path is like that: \Device\LanmanRedirector\;C:0000000000000000\Complete Path\To File.ext */
239  /* Check we have the correct drive letter */
240  if (TargetDevice[26] == DeviceName[0] &&
241  TargetDevice[27] == ':')
242  {
243  /* Check for the path begin, computer name is before */
244  PWSTR Path = wcschr(&TargetDevice[28], '\\');
245  if (Path == NULL)
246  {
247  return ERROR_BAD_PATHNAME;
248  }
249 
250  AbsolutePath = Path + 1;
251  AbsolutePathLength = sizeof(WCHAR) * (ARRAYSIZE(TargetDevice) - (AbsolutePath - TargetDevice));
252  }
253  else
254  {
255  return ERROR_BAD_PATHNAME;
256  }
257  }
258  /* If it's a local device */
259  else if (TargetDevice == wcsstr(TargetDevice, L"\\Device\\Harddisk")
260  || TargetDevice == wcsstr(TargetDevice, L"\\Device\\CdRom")
261  || TargetDevice == wcsstr(TargetDevice, L"\\Device\\Floppy"))
262  {
263  /* Just query the computer name */
264  if (!GetComputerNameW(ComputerName, ComputerNameLength))
265  {
266  return GetLastError();
267  }
268 
269  return ERROR_SUCCESS;
270  }
271  /* If it's a DFS share */
272  else if (TargetDevice == wcsstr(TargetDevice, L"\\Device\\WinDfs\\"))
273  {
274  /* Obviously, query DFS */
275  Query = TRUE;
276  }
277  else
278  {
279  return ERROR_BAD_PATHNAME;
280  }
281  }
282  else
283  {
284  return ERROR_BAD_PATHNAME;
285  }
286 
287  /* Query DFS, currently not implemented - shouldn't be missing in ReactOS yet ;-) */
288  if (Query)
289  {
290  UNIMPLEMENTED_DBGBREAK("Querying DFS not implemented!\n");
291  AbsolutePath = NULL;
292  AbsolutePathLength = 0;
293  }
294 
295  /* Now, properly extract the computer name from the full path */
296  EndOfName = AbsolutePath;
297  if (AbsolutePathLength)
298  {
299  for (NameLength = 0; NameLength < AbsolutePathLength; NameLength += sizeof(WCHAR))
300  {
301  /* Look for the next \, it will be the end of computer name */
302  if (EndOfName[0] == '\\')
303  {
304  break;
305  }
306  /* Computer name cannot contain ., if we get to that point, something went wrong... */
307  else if (EndOfName[0] == '.')
308  {
309  return ERROR_BAD_PATHNAME;
310  }
311 
312  ++EndOfName;
313  }
314  }
315 
316  NameLength = EndOfName - AbsolutePath;
317  /* Check we didn't overflow and that our computer name isn't ill-formed */
318  if (NameLength >= AbsolutePathLength || NameLength >= MAX_COMPUTERNAME_LENGTH * sizeof(WCHAR))
319  {
320  return ERROR_BAD_PATHNAME;
321  }
322 
323  /* Check we can fit */
324  if (NameLength + sizeof(UNICODE_NULL) > *ComputerNameLength * sizeof(WCHAR))
325  {
326  return ERROR_BUFFER_OVERFLOW;
327  }
328 
329  /* Write, zero and done! */
330  RtlCopyMemory(ComputerName, AbsolutePath, NameLength);
331  *ComputerNameLength = NameLength / sizeof(WCHAR);
332  ComputerName[NameLength / sizeof(WCHAR)] = UNICODE_NULL;
333 
334  return ERROR_SUCCESS;
335 }
336 
337 
338 /*
339  * @implemented
340  */
341 NTSTATUS
342 WINAPI
345  IN HANDLE NewHandle,
346  IN PUNICODE_STRING NewPath)
347 {
349  ULONG ComputerNameLength, FileAttributes;
350  WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
351  OEM_STRING ComputerNameStringA;
352  CHAR ComputerNameStringBuffer[0x105];
353  UNICODE_STRING ComputerNameStringW;
355  FILE_BASIC_INFORMATION FileBasicInfo;
356  HANDLE hFullWrite;
357  struct
358  {
360  CHAR Buffer[(MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR)];
361  } FileTrackingInfo;
362 
363  DPRINT("BasepNotifyTrackingService(%p, %p, %p, %wZ)\n", *ExistingHandle, ObjectAttributes, NewHandle, NewPath);
364 
366  ComputerNameLength = ARRAYSIZE(ComputerName);
367 
368  /* Attempt to get computer name of target handle */
369  if (BasepGetComputerNameFromNtPath(NewPath, NewHandle, ComputerName, &ComputerNameLength))
370  {
371  /* If we failed to get it, we will just notify with the handle */
372  FileTrackingInfo.ObjectInformationLength = 0;
373  }
374  else
375  {
376  /* Convert the retrieved computer name to ANSI and attach it to the notification */
377  ComputerNameStringA.Length = 0;
378  ComputerNameStringA.MaximumLength = ARRAYSIZE(ComputerNameStringBuffer);
379  ComputerNameStringA.Buffer = ComputerNameStringBuffer;
380 
381  RtlInitUnicodeString(&ComputerNameStringW, ComputerName);
382  Status = RtlUnicodeStringToOemString(&ComputerNameStringA, &ComputerNameStringW, 0);
383  if (!NT_SUCCESS(Status))
384  {
385  return Status;
386  }
387 
388  RtlCopyMemory(FileTrackingInfo.ObjectInformation, ComputerNameStringA.Buffer, ComputerNameStringA.Length);
389  FileTrackingInfo.ObjectInformation[ComputerNameStringA.Length] = 0;
390  FileTrackingInfo.ObjectInformationLength = ComputerNameStringA.Length + 1;
391  }
392 
393  /* Attach the handle we moved */
394  FileTrackingInfo.DestinationFile = NewHandle;
395 
396  /* Final, notify */
397  Status = NtSetInformationFile(*ExistingHandle,
398  &IoStatusBlock,
399  &FileTrackingInfo,
400  sizeof(FileTrackingInfo),
403  {
404  return Status;
405  }
406 
407  /* If we get here, we got access denied error, this comes from a
408  * read-only flag. So, close the file, in order to reopen it with enough
409  * rights to remove said flag and reattempt notification
410  */
411  CloseHandle(*ExistingHandle);
412 
413  /* Reopen it, to be able to change the destination file attributes */
414  Status = NtOpenFile(ExistingHandle,
417  &IoStatusBlock,
420  if (!NT_SUCCESS(Status))
421  {
422  *ExistingHandle = INVALID_HANDLE_VALUE;
423  return Status;
424  }
425 
426  /* Get the file attributes */
427  Status = NtQueryInformationFile(*ExistingHandle,
428  &IoStatusBlock,
429  &FileBasicInfo,
430  sizeof(FileBasicInfo),
432  if (!NT_SUCCESS(Status))
433  {
434  return Status;
435  }
436 
437  /* Get rid of the read only flag */
439  RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
440  FileBasicInfo.FileAttributes = FileAttributes;
441 
442  /* Attempt... */
443  Status = NtSetInformationFile(*ExistingHandle,
444  &IoStatusBlock,
445  &FileBasicInfo,
446  sizeof(FileBasicInfo),
448  if (!NT_SUCCESS(Status))
449  {
450  return Status;
451  }
452 
453  /* Now, reopen with maximum accesses to notify */
454  Status = NtOpenFile(&hFullWrite,
457  &IoStatusBlock,
460  if (NT_SUCCESS(Status))
461  {
462  NtClose(*ExistingHandle);
463  *ExistingHandle = hFullWrite;
464 
465  /* Full success, notify! */
466  Status = NtSetInformationFile(*ExistingHandle,
467  &IoStatusBlock,
468  &FileTrackingInfo,
469  sizeof(FileTrackingInfo),
471  }
472 
473  /* If opening with full access failed or if notify failed, restore read-only */
474  if (!NT_SUCCESS(Status))
475  {
476  FileBasicInfo.FileAttributes |= FILE_ATTRIBUTE_READONLY;
477 
478  Status = NtSetInformationFile(*ExistingHandle,
479  &IoStatusBlock,
480  &FileBasicInfo,
481  sizeof(FileBasicInfo),
483  }
484 
485  /* We're done */
486  return Status;
487 }
488 
489 
490 /*
491  * @implemented
492  */
493 NTSTATUS
494 WINAPI
496  OUT PUNICODE_STRING RelativeNtName,
497  OUT LPWSTR * NtName,
503 {
504  RTL_RELATIVE_NAME_U RelativeName;
508  ULONG IntShareAccess;
509  BOOLEAN HasRelative = FALSE;
510 
511  _SEH2_TRY
512  {
513  /* Zero output */
514  RelativeNtName->Length =
515  RelativeNtName->MaximumLength = 0;
516  RelativeNtName->Buffer = NULL;
517  *NtName = NULL;
518 
519  if (!RtlDosPathNameToRelativeNtPathName_U(File, RelativeNtName, NULL, &RelativeName))
520  {
522  _SEH2_LEAVE;
523  }
524 
525  HasRelative = TRUE;
526  *NtName = RelativeNtName->Buffer;
527 
528  if (RelativeName.RelativeName.Length)
529  {
530  RelativeNtName->Length = RelativeName.RelativeName.Length;
531  RelativeNtName->MaximumLength = RelativeName.RelativeName.MaximumLength;
532  RelativeNtName->Buffer = RelativeName.RelativeName.Buffer;
533  }
534  else
535  {
536  RelativeName.ContainingDirectory = 0;
537  }
538 
540  RelativeNtName,
542  RelativeName.ContainingDirectory,
543  NULL);
544  /* Force certain flags here, given ops we'll do */
545  IntShareAccess = ShareAccess | FILE_SHARE_READ | FILE_SHARE_WRITE;
547 
548  /* We'll try to read reparse tag */
552  &IoStatusBlock,
553  IntShareAccess,
555  if (NT_SUCCESS(Status))
556  {
557  /* Attempt the read */
559  &IoStatusBlock,
560  &TagInfo,
563 
564  /* Return if failure with a status that wouldn't mean the FSD cannot support reparse points */
565  if (!NT_SUCCESS(Status) &&
567  {
568  _SEH2_LEAVE;
569  }
570 
571  if (NT_SUCCESS(Status))
572  {
573  /* This cannot happen on mount points */
574  if (TagInfo.FileAttributes & FILE_ATTRIBUTE_DEVICE ||
576  {
577  _SEH2_LEAVE;
578  }
579  }
580 
583 
584  IntShareAccess = ShareAccess | FILE_SHARE_READ | FILE_SHARE_DELETE;
585  }
586  else if (Status == STATUS_INVALID_PARAMETER)
587  {
588  IntShareAccess = ShareAccess | FILE_SHARE_READ | FILE_SHARE_WRITE;
589  }
590  else
591  {
592  _SEH2_LEAVE;
593  }
594 
595  /* Reattempt to open normally, following reparse point if needed */
599  &IoStatusBlock,
600  IntShareAccess,
601  OpenOptions);
602  }
604  {
605  if (HasRelative)
606  {
607  RtlReleaseRelativeName(&RelativeName);
608  }
609  }
610  _SEH2_END;
611 
612  return Status;
613 }
614 
615 
616 /*
617  * @implemented
618  */
619 DWORD
620 WINAPI
622  IN LARGE_INTEGER TotalBytesTransferred,
623  IN LARGE_INTEGER StreamSize,
624  IN LARGE_INTEGER StreamBytesTransferred,
625  IN DWORD dwStreamNumber,
626  IN DWORD dwCallbackReason,
627  IN HANDLE hSourceFile,
628  IN HANDLE hDestinationFile,
629  IN LPVOID lpData OPTIONAL)
630 {
631  DWORD Ret = 0;
633 
634  if (Context->Flags & MOVEFILE_WRITE_THROUGH)
635  {
636  if (!dwCallbackReason)
637  {
638  if (StreamBytesTransferred.QuadPart == StreamSize.QuadPart)
639  {
640  FlushFileBuffers(hDestinationFile);
641  }
642  }
643  }
644 
645  if (Context->UserRoutine)
646  {
647  Ret = Context->UserRoutine(TotalFileSize,
648  TotalBytesTransferred,
649  StreamSize,
650  StreamBytesTransferred,
651  dwStreamNumber,
652  dwCallbackReason,
653  hSourceFile,
654  hDestinationFile,
655  Context->UserData);
656  }
657 
658  return Ret;
659 }
660 
661 
662 /*
663  * @implemented
664  */
665 BOOL
666 WINAPI
667 MoveFileWithProgressW(IN LPCWSTR lpExistingFileName,
668  IN LPCWSTR lpNewFileName,
669  IN LPPROGRESS_ROUTINE lpProgressRoutine,
670  IN LPVOID lpData,
671  IN DWORD dwFlags)
672 {
674  PWSTR NewBuffer;
676  COPY_PROGRESS_CONTEXT CopyContext;
678  PFILE_RENAME_INFORMATION RenameInfo;
679  UNICODE_STRING NewPathU, ExistingPathU;
680  FILE_ATTRIBUTE_TAG_INFORMATION FileAttrTagInfo;
681  HANDLE SourceHandle = INVALID_HANDLE_VALUE, NewHandle, ExistingHandle;
682  BOOL Ret = FALSE, ReplaceIfExists, DelayUntilReboot, AttemptReopenWithoutReparse;
683 
684  DPRINT("MoveFileWithProgressW(%S, %S, %p, %p, %x)\n", lpExistingFileName, lpNewFileName, lpProgressRoutine, lpData, dwFlags);
685 
686  NewPathU.Buffer = NULL;
687  ExistingPathU.Buffer = NULL;
688 
689  _SEH2_TRY
690  {
691  /* Don't allow renaming to a disk */
692  if (lpNewFileName && RtlIsDosDeviceName_U(lpNewFileName))
693  {
695  _SEH2_LEAVE;
696  }
697 
698  ReplaceIfExists = !!(dwFlags & MOVEFILE_REPLACE_EXISTING);
699 
700  /* Get file path */
701  if (!RtlDosPathNameToNtPathName_U(lpExistingFileName, &ExistingPathU, NULL, NULL))
702  {
704  _SEH2_LEAVE;
705  }
706 
707  /* Sanitize input */
708  DelayUntilReboot = !!(dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT);
709  if (DelayUntilReboot && (dwFlags & MOVEFILE_CREATE_HARDLINK))
710  {
712  _SEH2_LEAVE;
713  }
714 
715  /* Unless we manage a proper opening, we'll attempt to reopen without reparse support */
716  AttemptReopenWithoutReparse = TRUE;
718  &ExistingPathU,
720  NULL,
721  NULL);
722  /* Attempt to open source file */
726  &IoStatusBlock,
729  if (!NT_SUCCESS(Status))
730  {
731  /* If we failed and the file doesn't exist, don't attempt to reopen without reparse */
732  if (DelayUntilReboot &&
734  {
735  /* Here we don't fail completely, as we postpone the operation to reboot
736  * File might exist afterwards, and we don't need a handle here
737  */
739  AttemptReopenWithoutReparse = FALSE;
740  }
741  /* If we failed for any reason than unsupported reparse, fail completely */
742  else if (Status != STATUS_INVALID_PARAMETER)
743  {
745  _SEH2_LEAVE;
746  }
747  }
748  else
749  {
750  /* We managed to open, so query information */
752  &IoStatusBlock,
753  &FileAttrTagInfo,
756  if (!NT_SUCCESS(Status))
757  {
758  /* Do not tolerate any other error than something related to not supported operation */
760  {
762  _SEH2_LEAVE;
763  }
764 
765  /* Not a reparse point, no need to reopen, it's fine */
766  AttemptReopenWithoutReparse = FALSE;
767  }
768  /* Validate the reparse point (do we support it?) */
769  else if (FileAttrTagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
770  FileAttrTagInfo.ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
771  {
774  }
775  else
776  {
777  /* Mount point, let's rename it */
778  AttemptReopenWithoutReparse = FALSE;
779  }
780  }
781 
782  /* Simply reopen if required */
783  if (AttemptReopenWithoutReparse)
784  {
788  &IoStatusBlock,
791  if (!NT_SUCCESS(Status))
792  {
794  _SEH2_LEAVE;
795  }
796  }
797 
798  /* Nullify string if we're to use it */
799  if (DelayUntilReboot && !lpNewFileName)
800  {
801  RtlInitUnicodeString(&NewPathU, 0);
802  }
803  /* Check whether path exists */
804  else if (!RtlDosPathNameToNtPathName_U(lpNewFileName, &NewPathU, 0, 0))
805  {
807  _SEH2_LEAVE;
808  }
809 
810  /* Handle postponed renaming */
811  if (DelayUntilReboot)
812  {
813  /* If new file exists and we're allowed to replace, then mark the path with ! */
814  if (ReplaceIfExists && NewPathU.Length)
815  {
816  NewBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewPathU.Length + sizeof(WCHAR));
817  if (NewBuffer == NULL)
818  {
820  _SEH2_LEAVE;
821  }
822 
823  NewBuffer[0] = L'!';
824  RtlCopyMemory(&NewBuffer[1], NewPathU.Buffer, NewPathU.Length);
825  NewPathU.Length += sizeof(WCHAR);
826  NewPathU.MaximumLength += sizeof(WCHAR);
827  RtlFreeHeap(RtlGetProcessHeap(), 0, NewPathU.Buffer);
828  NewPathU.Buffer = NewBuffer;
829  }
830 
831  /* Check whether 'copy' renaming is allowed if required */
833  {
835  }
836  else
837  {
838  /* First, probe 2nd key to see whether it exists - if so, it will be appended there */
839  Status = BasepMoveFileDelayed(&ExistingPathU, &NewPathU, 2, FALSE);
841  {
842  /* If doesn't exist, append to first key first, creating it if it doesn't exist */
843  Status = BasepMoveFileDelayed(&ExistingPathU, &NewPathU, 1, TRUE);
844 
846  {
847  /* If it failed because it's too big, then create 2nd key and put it there */
848  Status = BasepMoveFileDelayed(&ExistingPathU, &NewPathU, 2, TRUE);
849  }
850  }
851  }
852 
853  /* If we failed at some point, return the error */
854  if (!NT_SUCCESS(Status))
855  {
857  _SEH2_LEAVE;
858  }
859 
860  Ret = TRUE;
861  _SEH2_LEAVE;
862  }
863 
864  /* At that point, we MUST have a source handle */
866 
867  /* Allocate renaming buffer and fill it */
868  RenameInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewPathU.Length + sizeof(FILE_RENAME_INFORMATION));
869  if (RenameInfo == NULL)
870  {
872  _SEH2_LEAVE;
873  }
874 
875  RtlCopyMemory(&RenameInfo->FileName, NewPathU.Buffer, NewPathU.Length);
876  RenameInfo->ReplaceIfExists = ReplaceIfExists;
877  RenameInfo->RootDirectory = 0;
878  RenameInfo->FileNameLength = NewPathU.Length;
879 
880  /* Attempt to rename the file */
882  &IoStatusBlock,
883  RenameInfo,
884  NewPathU.Length + sizeof(FILE_RENAME_INFORMATION),
886  RtlFreeHeap(RtlGetProcessHeap(), 0, RenameInfo);
887  if (NT_SUCCESS(Status))
888  {
889  /* If it succeed, all fine, quit */
890  Ret = TRUE;
891  _SEH2_LEAVE;
892  }
893  /* If we failed for any other reason than not the same device, fail
894  * If we failed because of different devices, only allow renaming if user allowed copy
895  */
897  {
898  /* ReactOS hack! To be removed once all FSD have proper renaming support
899  * Just leave status to error and leave
900  */
902  {
903  DPRINT1("Forcing copy, renaming not supported by FSD\n");
904  }
905  else
906  {
908  _SEH2_LEAVE;
909  }
910  }
911 
912  /* Close source file */
915 
916  /* Issue the copy of the file */
917  CopyContext.Flags = dwFlags;
918  CopyContext.UserRoutine = lpProgressRoutine;
919  CopyContext.UserData = lpData;
920  NewHandle = INVALID_HANDLE_VALUE;
921  ExistingHandle = INVALID_HANDLE_VALUE;
922 
923  Ret = BasepCopyFileExW(lpExistingFileName,
924  lpNewFileName,
926  &CopyContext,
927  NULL,
928  (ReplaceIfExists == 0) | COPY_FILE_OPEN_SOURCE_FOR_WRITE,
929  0,
930  &ExistingHandle,
931  &NewHandle);
932  if (!Ret)
933  {
934  /* If it failed, don't leak any handle */
935  if (ExistingHandle != INVALID_HANDLE_VALUE)
936  {
937  CloseHandle(ExistingHandle);
938  ExistingHandle = INVALID_HANDLE_VALUE;
939  }
940  }
941  else if (ExistingHandle != INVALID_HANDLE_VALUE)
942  {
943  if (NewHandle != INVALID_HANDLE_VALUE)
944  {
945  /* If copying succeed, notify */
946  Status = BasepNotifyTrackingService(&ExistingHandle, &ObjectAttributes, NewHandle, &NewPathU);
947  if (!NT_SUCCESS(Status))
948  {
949  /* Fail in case it had to succeed */
951  {
952  if (NewHandle != INVALID_HANDLE_VALUE)
953  CloseHandle(NewHandle);
954  NewHandle = INVALID_HANDLE_VALUE;
955  DeleteFileW(lpNewFileName);
956  Ret = FALSE;
958  }
959  }
960  }
961 
962  CloseHandle(ExistingHandle);
963  ExistingHandle = INVALID_HANDLE_VALUE;
964  }
965 
966  /* In case copy worked, close file */
967  if (NewHandle != INVALID_HANDLE_VALUE)
968  {
969  CloseHandle(NewHandle);
970  NewHandle = INVALID_HANDLE_VALUE;
971  }
972 
973  /* If it succeed, delete source file */
974  if (Ret)
975  {
976  if (!DeleteFileW(lpExistingFileName))
977  {
978  /* Reset file attributes if required */
979  SetFileAttributesW(lpExistingFileName, FILE_ATTRIBUTE_NORMAL);
980  DeleteFileW(lpExistingFileName);
981  }
982  }
983  }
985  {
988 
989  RtlFreeHeap(RtlGetProcessHeap(), 0, ExistingPathU.Buffer);
990  RtlFreeHeap(RtlGetProcessHeap(), 0, NewPathU.Buffer);
991  }
992  _SEH2_END;
993 
994  return Ret;
995 }
996 
997 
998 /*
999  * @implemented
1000  */
1001 BOOL
1002 WINAPI
1003 MoveFileWithProgressA(IN LPCSTR lpExistingFileName,
1004  IN LPCSTR lpNewFileName OPTIONAL,
1005  IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
1006  IN LPVOID lpData OPTIONAL,
1007  IN DWORD dwFlags)
1008 {
1009  BOOL Ret;
1010  UNICODE_STRING ExistingFileNameW, NewFileNameW;
1011 
1012  if (!Basep8BitStringToDynamicUnicodeString(&ExistingFileNameW, lpExistingFileName))
1013  {
1014  return FALSE;
1015  }
1016 
1017  if (lpNewFileName)
1018  {
1019  if (!Basep8BitStringToDynamicUnicodeString(&NewFileNameW, lpNewFileName))
1020  {
1021  RtlFreeUnicodeString(&ExistingFileNameW);
1022  return FALSE;
1023  }
1024  }
1025  else
1026  {
1027  NewFileNameW.Buffer = NULL;
1028  }
1029 
1030  Ret = MoveFileWithProgressW(ExistingFileNameW.Buffer, NewFileNameW.Buffer, lpProgressRoutine, lpData, dwFlags);
1031 
1032  RtlFreeUnicodeString(&ExistingFileNameW);
1033  RtlFreeUnicodeString(&NewFileNameW);
1034 
1035  return Ret;
1036 }
1037 
1038 
1039 /*
1040  * @implemented
1041  */
1042 BOOL
1043 WINAPI
1044 MoveFileW(IN LPCWSTR lpExistingFileName,
1045  IN LPCWSTR lpNewFileName)
1046 {
1047  return MoveFileWithProgressW(lpExistingFileName,
1048  lpNewFileName,
1049  NULL,
1050  NULL,
1052 }
1053 
1054 
1055 /*
1056  * @implemented
1057  */
1058 BOOL
1059 WINAPI
1060 MoveFileExW(IN LPCWSTR lpExistingFileName,
1061  IN LPCWSTR lpNewFileName OPTIONAL,
1062  IN DWORD dwFlags)
1063 {
1064  return MoveFileWithProgressW(lpExistingFileName,
1065  lpNewFileName,
1066  NULL,
1067  NULL,
1068  dwFlags);
1069 }
1070 
1071 
1072 /*
1073  * @implemented
1074  */
1075 BOOL
1076 WINAPI
1077 MoveFileA(IN LPCSTR lpExistingFileName,
1078  IN LPCSTR lpNewFileName)
1079 {
1080  return MoveFileWithProgressA(lpExistingFileName,
1081  lpNewFileName,
1082  NULL,
1083  NULL,
1085 }
1086 
1087 
1088 /*
1089  * @implemented
1090  */
1091 BOOL
1092 WINAPI
1093 MoveFileExA(IN LPCSTR lpExistingFileName,
1094  IN LPCSTR lpNewFileName OPTIONAL,
1095  IN DWORD dwFlags)
1096 {
1097  return MoveFileWithProgressA(lpExistingFileName,
1098  lpNewFileName,
1099  NULL,
1100  NULL,
1101  dwFlags);
1102 }
1103 
1104 /*
1105  * @implemented
1106  */
1107 BOOL
1108 WINAPI
1109 ReplaceFileA(IN LPCSTR lpReplacedFileName,
1110  IN LPCSTR lpReplacementFileName,
1111  IN LPCSTR lpBackupFileName OPTIONAL,
1112  IN DWORD dwReplaceFlags,
1113  IN LPVOID lpExclude,
1114  IN LPVOID lpReserved)
1115 {
1116  BOOL Ret;
1117  UNICODE_STRING ReplacedFileNameW, ReplacementFileNameW, BackupFileNameW;
1118 
1119  if (!lpReplacedFileName || !lpReplacementFileName || lpExclude || lpReserved || dwReplaceFlags & ~(REPLACEFILE_WRITE_THROUGH | REPLACEFILE_IGNORE_MERGE_ERRORS))
1120  {
1122  return FALSE;
1123  }
1124 
1125  if (!Basep8BitStringToDynamicUnicodeString(&ReplacedFileNameW, lpReplacedFileName))
1126  {
1127  return FALSE;
1128  }
1129 
1130  if (!Basep8BitStringToDynamicUnicodeString(&ReplacementFileNameW, lpReplacementFileName))
1131  {
1132  RtlFreeUnicodeString(&ReplacedFileNameW);
1133  return FALSE;
1134  }
1135 
1136  if (lpBackupFileName)
1137  {
1138  if (!Basep8BitStringToDynamicUnicodeString(&BackupFileNameW, lpBackupFileName))
1139  {
1140  RtlFreeUnicodeString(&ReplacementFileNameW);
1141  RtlFreeUnicodeString(&ReplacedFileNameW);
1142  return FALSE;
1143  }
1144  }
1145  else
1146  {
1147  BackupFileNameW.Buffer = NULL;
1148  }
1149 
1150  Ret = ReplaceFileW(ReplacedFileNameW.Buffer, ReplacementFileNameW.Buffer, BackupFileNameW.Buffer, dwReplaceFlags, 0, 0);
1151 
1152  if (lpBackupFileName)
1153  {
1154  RtlFreeUnicodeString(&BackupFileNameW);
1155  }
1156  RtlFreeUnicodeString(&ReplacementFileNameW);
1157  RtlFreeUnicodeString(&ReplacedFileNameW);
1158 
1159  return Ret;
1160 }
1161 
1162 /*
1163  * @unimplemented
1164  */
1165 BOOL
1166 WINAPI
1168  LPCWSTR lpReplacedFileName,
1169  LPCWSTR lpReplacementFileName,
1170  LPCWSTR lpBackupFileName,
1171  DWORD dwReplaceFlags,
1172  LPVOID lpExclude,
1173  LPVOID lpReserved
1174  )
1175 {
1176  HANDLE hReplaced = NULL, hReplacement = NULL;
1177  UNICODE_STRING NtReplacedName = { 0, 0, NULL };
1178  UNICODE_STRING NtReplacementName = { 0, 0, NULL };
1180  NTSTATUS Status;
1181  BOOL Ret = FALSE;
1184  PVOID Buffer = NULL ;
1185 
1186  if (dwReplaceFlags)
1187  FIXME("Ignoring flags %x\n", dwReplaceFlags);
1188 
1189  /* First two arguments are mandatory */
1190  if (!lpReplacedFileName || !lpReplacementFileName)
1191  {
1193  return FALSE;
1194  }
1195 
1196  /* Back it up */
1197  if(lpBackupFileName)
1198  {
1199  if(!CopyFileW(lpReplacedFileName, lpBackupFileName, FALSE))
1200  {
1201  Error = GetLastError();
1202  goto Cleanup ;
1203  }
1204  }
1205 
1206  /* Open the "replaced" file for reading and writing */
1207  if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &NtReplacedName, NULL, NULL)))
1208  {
1210  goto Cleanup;
1211  }
1212 
1214  &NtReplacedName,
1216  NULL,
1217  NULL);
1218 
1219  Status = NtOpenFile(&hReplaced,
1222  &IoStatusBlock,
1225 
1226  if (!NT_SUCCESS(Status))
1227  {
1230  else
1232  goto Cleanup;
1233  }
1234 
1235  /* Blank it */
1236  SetEndOfFile(hReplaced) ;
1237 
1238  /*
1239  * Open the replacement file for reading, writing, and deleting
1240  * (deleting is needed when finished)
1241  */
1242  if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName, &NtReplacementName, NULL, NULL)))
1243  {
1245  goto Cleanup;
1246  }
1247 
1249  &NtReplacementName,
1251  NULL,
1252  NULL);
1253 
1254  Status = NtOpenFile(&hReplacement,
1257  &IoStatusBlock,
1258  0,
1260 
1261  if (!NT_SUCCESS(Status))
1262  {
1264  goto Cleanup;
1265  }
1266 
1267  Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 0x10000) ;
1268  if (!Buffer)
1269  {
1271  goto Cleanup ;
1272  }
1273  while (Status != STATUS_END_OF_FILE)
1274  {
1275  Status = NtReadFile(hReplacement, NULL, NULL, NULL, &IoStatusBlock, Buffer, 0x10000, NULL, NULL) ;
1276  if (NT_SUCCESS(Status))
1277  {
1278  Status = NtWriteFile(hReplaced, NULL, NULL, NULL, &IoStatusBlock, Buffer,
1280  if (!NT_SUCCESS(Status))
1281  {
1283  goto Cleanup;
1284  }
1285  }
1286  else if (Status != STATUS_END_OF_FILE)
1287  {
1289  goto Cleanup;
1290  }
1291  }
1292 
1293  Ret = TRUE;
1294 
1295  /* Perform resource cleanup */
1296 Cleanup:
1297  if (hReplaced) NtClose(hReplaced);
1298  if (hReplacement) NtClose(hReplacement);
1299  if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
1300 
1301  if (NtReplacementName.Buffer)
1302  RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName.Buffer);
1303  if (NtReplacedName.Buffer)
1304  RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName.Buffer);
1305 
1306  /* If there was an error, set the error code */
1307  if(!Ret)
1308  {
1309  TRACE("ReplaceFileW failed (error=%lu)\n", Error);
1311  }
1312  return Ret;
1313 }
1314 
1315 
1316 /*
1317  * @implemented
1318  */
1319 BOOL
1320 WINAPI
1322 {
1323  ACCESS_MASK SourceAccess;
1324  UNICODE_STRING NtSource, NtDestination;
1325  LPWSTR RelativeSource, RelativeDestination;
1326  HANDLE SourceHandle, DestinationHandle;
1327  OBJECT_ATTRIBUTES ObjectAttributesSource, ObjectAttributesDestination;
1328  NTSTATUS Status, OldStatus = STATUS_SUCCESS;
1329  ACCESS_MASK DestAccess;
1331  FILE_BASIC_INFORMATION SourceInformation, DestinationInformation;
1332  FILE_DISPOSITION_INFORMATION FileDispositionInfo;
1333 
1334  DPRINT("PrivMoveFileIdentityW(%S, %S, %x)\n", lpSource, lpDestination, dwFlags);
1335 
1337  NtSource.Length =
1338  NtSource.MaximumLength = 0;
1339  NtSource.Buffer = NULL;
1340  RelativeSource = NULL;
1341  DestinationHandle = INVALID_HANDLE_VALUE;
1342  NtDestination.Length =
1343  NtDestination.MaximumLength = 0;
1344  NtDestination.Buffer = NULL;
1345  RelativeDestination = NULL;
1346 
1347  /* FILE_WRITE_DATA is required for later on notification */
1348  SourceAccess = FILE_READ_ATTRIBUTES | FILE_WRITE_DATA;
1350  {
1351  SourceAccess |= DELETE;
1352  }
1353 
1354  _SEH2_TRY
1355  {
1356  /* We will loop twice:
1357  * First we attempt to open with FILE_WRITE_DATA for notification
1358  * If it fails and we have flag for non-trackable files, we retry
1359  * without FILE_WRITE_DATA.
1360  * If that one fails, then, we quit for real
1361  */
1362  while (TRUE)
1363  {
1364  Status = BasepOpenFileForMove(lpSource,
1365  &NtSource,
1366  &RelativeSource,
1367  &SourceHandle,
1368  &ObjectAttributesSource,
1369  SourceAccess,
1372  if (NT_SUCCESS(Status))
1373  {
1374  break;
1375  }
1376 
1377  /* If we already attempted the opening without FILE_WRITE_DATA
1378  * or if we cannot move on non-trackable files, fail.
1379  */
1380  if (!(SourceAccess & FILE_WRITE_DATA) || !(dwFlags & PRIV_ALLOW_NON_TRACKABLE))
1381  {
1382  _SEH2_LEAVE;
1383  }
1384 
1385  if (RelativeSource)
1386  {
1387  RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSource);
1388  RelativeSource = NULL;
1389  }
1390 
1392  {
1395  }
1396 
1397  SourceAccess &= ~FILE_WRITE_DATA;
1398 
1399  /* Remember fist failure in the path */
1400  if (NT_SUCCESS(OldStatus))
1401  {
1402  OldStatus = Status;
1403  }
1404  }
1405 
1406  DestAccess = FILE_WRITE_ATTRIBUTES;
1407  /* If we could preserve FILE_WRITE_DATA for source, attempt to get it for destination
1408  * Still for notification purposes
1409  */
1410  if (SourceAccess & FILE_WRITE_DATA)
1411  {
1412  DestAccess |= FILE_WRITE_DATA;
1413  }
1414 
1415  /* cf comment for first loop */
1416  while (TRUE)
1417  {
1418  Status = BasepOpenFileForMove(lpDestination,
1419  &NtDestination,
1420  &RelativeDestination,
1421  &DestinationHandle,
1422  &ObjectAttributesDestination,
1423  DestAccess,
1426  if (NT_SUCCESS(Status))
1427  {
1428  break;
1429  }
1430 
1431  /* If we already attempted the opening without FILE_WRITE_DATA
1432  * or if we cannot move on non-trackable files, fail.
1433  */
1434  if (!(DestAccess & FILE_WRITE_DATA) || !(dwFlags & PRIV_ALLOW_NON_TRACKABLE))
1435  {
1436  _SEH2_LEAVE;
1437  }
1438 
1439  if (RelativeDestination)
1440  {
1441  RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeDestination);
1442  RelativeDestination = NULL;
1443  }
1444 
1445  if (DestinationHandle != INVALID_HANDLE_VALUE)
1446  {
1447  NtClose(DestinationHandle);
1448  DestinationHandle = INVALID_HANDLE_VALUE;
1449  }
1450 
1451  DestAccess &= ~FILE_WRITE_DATA;
1452 
1453  /* Remember fist failure in the path */
1454  if (NT_SUCCESS(OldStatus))
1455  {
1456  OldStatus = Status;
1457  }
1458  }
1459 
1460  /* Get the creation time from source */
1462  &IoStatusBlock,
1463  &SourceInformation,
1464  sizeof(SourceInformation),
1466  if (NT_SUCCESS(Status))
1467  {
1468  /* Then, prepare to set it for destination */
1469  RtlZeroMemory(&DestinationInformation, sizeof(DestinationInformation));
1470  DestinationInformation.CreationTime.QuadPart = SourceInformation.CreationTime.QuadPart;
1471 
1472  /* And set it, that's all folks! */
1473  Status = NtSetInformationFile(DestinationHandle,
1474  &IoStatusBlock,
1475  &DestinationInformation,
1476  sizeof(DestinationInformation),
1478  }
1479 
1480  if (!NT_SUCCESS(Status))
1481  {
1483  {
1484  _SEH2_LEAVE;
1485  }
1486 
1487  /* Remember the failure for later notification */
1488  if (NT_SUCCESS(OldStatus))
1489  {
1490  OldStatus = Status;
1491  }
1492  }
1493 
1494  /* If we could open with FILE_WRITE_DATA both source and destination,
1495  * then, notify
1496  */
1497  if (DestAccess & FILE_WRITE_DATA && SourceAccess & FILE_WRITE_DATA)
1498  {
1500  &ObjectAttributesSource,
1501  DestinationHandle,
1502  &NtDestination);
1503  if (!NT_SUCCESS(Status))
1504  {
1506  {
1507  if (NT_SUCCESS(OldStatus))
1508  OldStatus = Status;
1509 
1510  /* Reset status, we allow non trackable files */
1512  }
1513  }
1514  }
1515  }
1517  {
1518  if (RelativeSource)
1519  RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSource);
1520 
1521  if (RelativeDestination)
1522  RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeDestination);
1523  }
1524  _SEH2_END;
1525 
1526  /* If caller asked for source deletion, if everything succeed, proceed */
1528  {
1529  FileDispositionInfo.DeleteFile = TRUE;
1530 
1532  &IoStatusBlock,
1533  &FileDispositionInfo,
1534  sizeof(FileDispositionInfo),
1536  }
1537 
1538  /* Cleanup/close portion */
1539  if (DestinationHandle != INVALID_HANDLE_VALUE)
1540  {
1541  NtClose(DestinationHandle);
1542  }
1543 
1545  {
1547  }
1548 
1549  /* Set last error if any, and quit */
1550  if (NT_SUCCESS(Status))
1551  {
1552  if (!NT_SUCCESS(OldStatus))
1553  {
1554  BaseSetLastNTError(OldStatus);
1555  }
1556  }
1557  else
1558  {
1560  }
1561 
1562  return NT_SUCCESS(Status);
1563 }
1564 
1565 /* EOF */
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:944
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
LPPROGRESS_ROUTINE UserRoutine
Definition: move.c:31
#define MOVEFILE_CREATE_HARDLINK
Definition: winbase.h:383
#define STRING_LENGTH
BOOL WINAPI MoveFileExA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1093
struct _COPY_PROGRESS_CONTEXT * PCOPY_PROGRESS_CONTEXT
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define CloseHandle
Definition: compat.h:398
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
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
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:1003
#define ERROR_SUCCESS
Definition: deptool.c:10
#define STATUS_NOT_SAME_DEVICE
Definition: ntstatus.h:434
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
_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:6013
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4711
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
USHORT MaximumLength
Definition: env_spec_w32.h:370
_Must_inspect_result_ __drv_aliasesMem PDEVICE_OBJECT _In_ PDEVICE_OBJECT TargetDevice
Definition: iofuncs.h:688
#define MOVEFILE_REPLACE_EXISTING
Definition: filesup.h:28
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define ERROR_BUFFER_OVERFLOW
Definition: winerror.h:185
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
uint16_t * PWSTR
Definition: typedefs.h:54
#define MOVEFILE_COPY_ALLOWED
Definition: filesup.h:29
char CHAR
Definition: xmlstorage.h:175
HANDLE ContainingDirectory
Definition: rtltypes.h:1375
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1154
VOID NTAPI RtlReleaseRelativeName(_In_ PRTL_RELATIVE_NAME_U RelativeName)
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
#define FILE_OPEN_NO_RECALL
Definition: from_kernel.h:47
DEBUG_CHANNEL(kernel32file)
BOOL WINAPI MoveFileA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName)
Definition: move.c:1077
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
_In_ HANDLE SourceHandle
Definition: obfuncs.h:429
struct _COPY_PROGRESS_CONTEXT COPY_PROGRESS_CONTEXT
BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:440
WCHAR DeviceName[]
Definition: adapter.cpp:21
STRING OEM_STRING
Definition: umtypes.h:203
int32_t INT
Definition: typedefs.h:56
_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:4157
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FILE_SHARE_READ
Definition: compat.h:125
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_U(_In_ PCWSTR DosName, _Out_ PUNICODE_STRING NtName, _Out_ PCWSTR *PartName, _Out_ PRTL_RELATIVE_NAME_U RelativeName)
_SEH2_TRY
Definition: create.c:4250
#define STATUS_END_OF_FILE
Definition: shellext.h:62
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:6874
#define OBJ_OPENIF
Definition: winternl.h:229
HANDLE FileHandle
Definition: stats.c:38
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
#define STATUS_SHARING_VIOLATION
Definition: udferr_usr.h:154
#define UNICODE_NULL
#define MOVEFILE_WRITE_THROUGH
Definition: filesup.h:30
unsigned int BOOL
Definition: ntddk_ex.h:94
#define PRIV_ALLOW_NON_TRACKABLE
Definition: kernel32.h:134
_In_ ULONG BufferLength
Definition: usbdlib.h:225
#define kernel32file
Definition: kernel32.h:6
NTSTATUS WINAPI BasepNotifyTrackingService(IN OUT PHANDLE ExistingHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE NewHandle, IN PUNICODE_STRING NewPath)
Definition: move.c:343
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FIXME(fmt,...)
Definition: debug.h:110
BOOL WINAPI MoveFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName)
Definition: move.c:1044
BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileName, LPCWSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved)
Definition: move.c:1167
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
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:1109
#define COPY_FILE_OPEN_SOURCE_FOR_WRITE
Definition: winbase.h:207
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
STRSAFEAPI StringCbPrintfW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:557
DWORD WINAPI QueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:542
#define MOVEFILE_DELAY_UNTIL_REBOOT
Definition: winbase.h:381
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
const char * LPCSTR
Definition: xmlstorage.h:183
DWORD WINAPI BasepGetComputerNameFromNtPath(IN PUNICODE_STRING NewPath, IN HANDLE NewHandle, OUT PWSTR ComputerName, IN OUT PULONG ComputerNameLength)
Definition: move.c:185
_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:1230
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define FILE_WRITE_DATA
Definition: nt_native.h:631
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define FILE_DELETE_ON_CLOSE
Definition: constants.h:494
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:3951
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)
#define FILE_ATTRIBUTE_DEVICE
Definition: disk.h:27
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:395
BOOL WINAPI FlushFileBuffers(IN HANDLE hFile)
Definition: fileinfo.c:175
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ERROR_UNABLE_TO_REMOVE_REPLACED
Definition: winerror.h:696
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
#define WINAPI
Definition: msvc.h:8
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
unsigned long DWORD
Definition: ntddk_ex.h:95
#define WRITE_DAC
Definition: nt_native.h:59
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
BOOL Error
Definition: chkdsk.c:66
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define SetLastError(x)
Definition: compat.h:409
#define REG_OPTION_BACKUP_RESTORE
Definition: nt_native.h:1066
BOOL WINAPI PrivMoveFileIdentityW(IN LPCWSTR lpSource, IN LPCWSTR lpDestination, IN DWORD dwFlags)
Definition: move.c:1321
BOOL Query(LPCTSTR *ServiceArgs, DWORD ArgCount, BOOL bExtended)
Definition: query.c:292
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:495
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define PRIV_DELETE_ON_SUCCESS
Definition: kernel32.h:133
LARGE_INTEGER CreationTime
Definition: nt_native.h:939
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
static const WCHAR L[]
Definition: oid.c:1250
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
WCHAR Letter
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
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
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_NON_DIRECTORY_FILE
Definition: constants.h:492
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
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:1392
#define GENERIC_READ
Definition: compat.h:124
NTSTATUS NTAPI NtQueryInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass)
static const WCHAR Cleanup[]
Definition: register.c:80
#define SYNCHRONIZE
Definition: nt_native.h:61
Status
Definition: gdiplustypes.h:24
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:240
NTSTATUS WINAPI BasepMoveFileDelayed(IN PUNICODE_STRING ExistingPath, IN PUNICODE_STRING NewPath, IN INT KeyId, IN BOOL CreateIfNotFound)
Definition: move.c:41
_SEH2_END
Definition: create.c:4424
PRTL_UNICODE_STRING_BUFFER Path
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
struct _FILE_TRACKING_INFORMATION FILE_TRACKING_INFORMATION
unsigned short USHORT
Definition: pedump.c:61
_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 DesiredAccess
Definition: create.c:4157
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
_SEH2_FINALLY
Definition: create.c:4395
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned int * PULONG
Definition: retypes.h:1
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
BOOL WINAPI MoveFileWithProgressW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine, IN LPVOID lpData, IN DWORD dwFlags)
Definition: move.c:667
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
#define DPRINT1
Definition: precomp.h:8
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
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:621
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
BOOL WINAPI MoveFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1060
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
UNICODE_STRING RelativeName
Definition: rtltypes.h:1374
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
Definition: File.h:15
#define _SEH2_LEAVE
Definition: filesup.c:20
WCHAR * LPWSTR
Definition: xmlstorage.h:184
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2777
#define ERROR_BAD_PATHNAME
Definition: winerror.h:233
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
NTSYSAPI ULONG NTAPI RtlIsDosDeviceName_U(_In_ PCWSTR Name)
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define MOVEFILE_FAIL_IF_NOT_TRACKABLE
Definition: winbase.h:384
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:3042
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)
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 DELETE
Definition: nt_native.h:57
LONGLONG QuadPart
Definition: typedefs.h:112
NTSYSAPI RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(_In_ PCWSTR Path)
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68