ReactOS  0.4.15-dev-5606-gf34e425
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 *****************************************************************/
24 typedef struct _COPY_PROGRESS_CONTEXT
25 {
30 
31 /* FUNCTIONS ****************************************************************/
32 
87 WINAPI
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 */
130  &ObjectAttributes, 0, NULL,
133  {
136  &ObjectAttributes, 0, NULL,
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  */
234 DWORD
235 WINAPI
237  IN HANDLE NewHandle,
238  OUT PWSTR ComputerName,
239  IN OUT PULONG ComputerNameLength)
240 {
241  BOOL Query = FALSE;
242  WCHAR Letter;
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  {
378  return ERROR_BUFFER_OVERFLOW;
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  */
393 NTSTATUS
394 WINAPI
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,
451  &IoStatusBlock,
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,
470  &IoStatusBlock,
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,
481  &IoStatusBlock,
482  &FileBasicInfo,
483  sizeof(FileBasicInfo),
485  if (!NT_SUCCESS(Status))
486  {
487  return Status;
488  }
489 
490  /* Get rid of the read only flag */
492  RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
493  FileBasicInfo.FileAttributes = FileAttributes;
494 
495  /* Attempt... */
496  Status = NtSetInformationFile(*ExistingHandle,
497  &IoStatusBlock,
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,
510  &IoStatusBlock,
513  if (NT_SUCCESS(Status))
514  {
515  NtClose(*ExistingHandle);
516  *ExistingHandle = hFullWrite;
517 
518  /* Full success, notify! */
519  Status = NtSetInformationFile(*ExistingHandle,
520  &IoStatusBlock,
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  {
529  FileBasicInfo.FileAttributes |= FILE_ATTRIBUTE_READONLY;
530 
531  Status = NtSetInformationFile(*ExistingHandle,
532  &IoStatusBlock,
533  &FileBasicInfo,
534  sizeof(FileBasicInfo),
536  }
537 
538  /* We're done */
539  return Status;
540 }
541 
542 
543 /*
544  * @implemented
545  */
546 NTSTATUS
547 WINAPI
549  OUT PUNICODE_STRING RelativeNtName,
550  OUT LPWSTR * NtName,
556 {
557  RTL_RELATIVE_NAME_U RelativeName;
561  ULONG IntShareAccess;
562  BOOLEAN HasRelative = FALSE;
563 
564  _SEH2_TRY
565  {
566  /* Zero output */
567  RtlInitEmptyUnicodeString(RelativeNtName, NULL, 0);
568  *NtName = NULL;
569 
570  if (!RtlDosPathNameToRelativeNtPathName_U(File, RelativeNtName, NULL, &RelativeName))
571  {
573  _SEH2_LEAVE;
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 */
603  &IoStatusBlock,
604  IntShareAccess,
606  if (NT_SUCCESS(Status))
607  {
608  /* Attempt the read */
610  &IoStatusBlock,
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  {
619  _SEH2_LEAVE;
620  }
621 
622  if (NT_SUCCESS(Status))
623  {
624  /* This cannot happen on mount points */
625  if (TagInfo.FileAttributes & FILE_ATTRIBUTE_DEVICE ||
627  {
628  _SEH2_LEAVE;
629  }
630  }
631 
634 
635  IntShareAccess = ShareAccess | FILE_SHARE_READ | FILE_SHARE_DELETE;
636  }
637  else if (Status == STATUS_INVALID_PARAMETER)
638  {
639  IntShareAccess = ShareAccess | FILE_SHARE_READ | FILE_SHARE_WRITE;
640  }
641  else
642  {
643  _SEH2_LEAVE;
644  }
645 
646  /* Reattempt to open normally, following reparse point if needed */
650  &IoStatusBlock,
651  IntShareAccess,
652  OpenOptions);
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  */
670 DWORD
671 WINAPI
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  */
716 BOOL
717 WINAPI
718 MoveFileWithProgressW(IN LPCWSTR lpExistingFileName,
719  IN LPCWSTR lpNewFileName,
720  IN LPPROGRESS_ROUTINE lpProgressRoutine,
721  IN LPVOID lpData,
722  IN DWORD dwFlags)
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 
741  _SEH2_TRY
742  {
743  /* Don't allow renaming to a disk */
744  if (lpNewFileName && RtlIsDosDeviceName_U(lpNewFileName))
745  {
747  _SEH2_LEAVE;
748  }
749 
750  ReplaceIfExists = !!(dwFlags & MOVEFILE_REPLACE_EXISTING);
751 
752  /* Get file path */
753  if (!RtlDosPathNameToNtPathName_U(lpExistingFileName, &ExistingPathU, NULL, NULL))
754  {
756  _SEH2_LEAVE;
757  }
758 
759  /* Sanitize input */
760  DelayUntilReboot = !!(dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT);
761  if (DelayUntilReboot && (dwFlags & MOVEFILE_CREATE_HARDLINK))
762  {
764  _SEH2_LEAVE;
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 */
778  &IoStatusBlock,
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 */
793  else if (Status != STATUS_INVALID_PARAMETER)
794  {
796  _SEH2_LEAVE;
797  }
798  }
799  else
800  {
801  /* We managed to open, so query information */
803  &IoStatusBlock,
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  {
813  _SEH2_LEAVE;
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  {
839  &IoStatusBlock,
842  if (!NT_SUCCESS(Status))
843  {
845  _SEH2_LEAVE;
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  {
858  _SEH2_LEAVE;
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  {
871  _SEH2_LEAVE;
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  {
908  _SEH2_LEAVE;
909  }
910 
911  Ret = TRUE;
912  _SEH2_LEAVE;
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  {
924  _SEH2_LEAVE;
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 */
934  &IoStatusBlock,
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;
944  _SEH2_LEAVE;
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  {
960  _SEH2_LEAVE;
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  */
1057 BOOL
1058 WINAPI
1059 MoveFileWithProgressA(IN LPCSTR lpExistingFileName,
1060  IN LPCSTR lpNewFileName OPTIONAL,
1061  IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
1062  IN LPVOID lpData OPTIONAL,
1063  IN DWORD dwFlags)
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  */
1102 BOOL
1103 WINAPI
1104 MoveFileW(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  */
1118 BOOL
1119 WINAPI
1120 MoveFileExW(IN LPCWSTR lpExistingFileName,
1121  IN LPCWSTR lpNewFileName OPTIONAL,
1122  IN DWORD dwFlags)
1123 {
1124  return MoveFileWithProgressW(lpExistingFileName,
1125  lpNewFileName,
1126  NULL,
1127  NULL,
1128  dwFlags);
1129 }
1130 
1131 
1132 /*
1133  * @implemented
1134  */
1135 BOOL
1136 WINAPI
1137 MoveFileA(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  */
1151 BOOL
1152 WINAPI
1153 MoveFileExA(IN LPCSTR lpExistingFileName,
1154  IN LPCSTR lpNewFileName OPTIONAL,
1155  IN DWORD dwFlags)
1156 {
1157  return MoveFileWithProgressA(lpExistingFileName,
1158  lpNewFileName,
1159  NULL,
1160  NULL,
1161  dwFlags);
1162 }
1163 
1164 /*
1165  * @implemented
1166  */
1167 BOOL
1168 WINAPI
1169 ReplaceFileA(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  */
1229 BOOL
1230 WINAPI
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 };
1244  NTSTATUS Status;
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,
1286  &IoStatusBlock,
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,
1321  &IoStatusBlock,
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  {
1342  Status = NtWriteFile(hReplaced, NULL, NULL, NULL, &IoStatusBlock, Buffer,
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 */
1360 Cleanup:
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  */
1383 BOOL
1384 WINAPI
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  {
1442  _SEH2_LEAVE;
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  {
1495  _SEH2_LEAVE;
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 */
1521  &IoStatusBlock,
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,
1533  &IoStatusBlock,
1534  &DestinationInformation,
1535  sizeof(DestinationInformation),
1537  }
1538 
1539  if (!NT_SUCCESS(Status))
1540  {
1542  {
1543  _SEH2_LEAVE;
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 
1591  &IoStatusBlock,
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 */
_SEH2_TRY
Definition: create.c:4226
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:794
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
LPPROGRESS_ROUTINE UserRoutine
Definition: move.c:27
#define MOVEFILE_CREATE_HARDLINK
Definition: winbase.h:402
#define STRING_LENGTH
BOOL WINAPI MoveFileExA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1153
struct _COPY_PROGRESS_CONTEXT * PCOPY_PROGRESS_CONTEXT
#define IN
Definition: typedefs.h:39
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3767
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
#define CloseHandle
Definition: compat.h:739
#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:1059
#define ERROR_SUCCESS
Definition: deptool.c:10
#define STATUS_NOT_SAME_DEVICE
Definition: ntstatus.h:448
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
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
USHORT MaximumLength
Definition: env_spec_w32.h:370
_Must_inspect_result_ __drv_aliasesMem PDEVICE_OBJECT _In_ PDEVICE_OBJECT TargetDevice
Definition: iofuncs.h:690
#define MOVEFILE_REPLACE_EXISTING
Definition: filesup.h:28
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define TRUE
Definition: types.h:120
#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:56
#define MOVEFILE_COPY_ALLOWED
Definition: filesup.h:29
char CHAR
Definition: xmlstorage.h:175
HANDLE ContainingDirectory
Definition: rtltypes.h:1381
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1004
VOID NTAPI RtlReleaseRelativeName(_In_ PRTL_RELATIVE_NAME_U RelativeName)
LONG NTSTATUS
Definition: precomp.h:26
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#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:1137
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
_In_ HANDLE SourceHandle
Definition: obfuncs.h:429
struct _COPY_PROGRESS_CONTEXT COPY_PROGRESS_CONTEXT
_SEH2_END
Definition: create.c:4400
BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:446
STRING OEM_STRING
Definition: umtypes.h:203
int32_t INT
Definition: typedefs.h:58
#define OBJ_OPENIF
Definition: winternl.h:229
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FILE_SHARE_READ
Definition: compat.h:136
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_U(_In_ PCWSTR DosName, _Out_ PUNICODE_STRING NtName, _Out_ PCWSTR *PartName, _Out_ PRTL_RELATIVE_NAME_U RelativeName)
#define STATUS_END_OF_FILE
Definition: shellext.h:67
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7231
return STATUS_NOT_IMPLEMENTED
#define L(x)
Definition: ntvdm.h:50
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3272
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
#define STATUS_SHARING_VIOLATION
Definition: udferr_usr.h:154
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define ANSI_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
#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:395
#define COPY_FILE_FAIL_IF_EXISTS
Definition: winbase.h:205
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FIXME(fmt,...)
Definition: debug.h:111
BOOL WINAPI MoveFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName)
Definition: move.c:1104
BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileName, LPCWSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved)
Definition: move.c:1231
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:1169
#define COPY_FILE_OPEN_SOURCE_FOR_WRITE
Definition: winbase.h:207
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
unsigned char BOOLEAN
DWORD WINAPI QueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:542
#define _In_
Definition: ms_sal.h:308
#define MOVEFILE_DELAY_UNTIL_REBOOT
Definition: winbase.h:400
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:236
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
_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:588
Status
Definition: gdiplustypes.h:24
#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:3952
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:736
BOOL WINAPI FlushFileBuffers(IN HANDLE hFile)
Definition: fileinfo.c:25
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
#define ASSERT(a)
Definition: mode.c:44
__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
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
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
_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:4137
#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:752
#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:1385
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:548
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define PRIV_DELETE_ON_SUCCESS
Definition: kernel32.h:133
LARGE_INTEGER CreationTime
Definition: nt_native.h:939
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
WCHAR Letter
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
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:1427
#define GENERIC_READ
Definition: compat.h:135
static const WCHAR Cleanup[]
Definition: register.c:80
#define SYNCHRONIZE
Definition: nt_native.h:61
_SEH2_FINALLY
Definition: create.c:4371
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:243
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1230
PRTL_UNICODE_STRING_BUFFER Path
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
struct _FILE_TRACKING_INFORMATION FILE_TRACKING_INFORMATION
unsigned short USHORT
Definition: pedump.c:61
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
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:718
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#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:672
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
BOOL WINAPI MoveFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1120
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
UNICODE_STRING RelativeName
Definition: rtltypes.h:1380
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
Definition: File.h:15
#define STATUS_SUCCESS
Definition: shellext.h:65
#define _SEH2_LEAVE
Definition: filesup.c:20
#define DPRINT
Definition: sndvol32.h:71
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#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:403
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 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:114
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