ReactOS  0.4.15-dev-5452-g3c95c95
move.c File Reference
#include <k32.h>
#include <malloc.h>
#include <debug.h>
Include dependency graph for move.c:

Go to the source code of this file.

Classes

struct  _COPY_PROGRESS_CONTEXT
 

Macros

#define NDEBUG
 
#define STRING_LENGTH   0x400
 

Typedefs

typedef struct _COPY_PROGRESS_CONTEXT COPY_PROGRESS_CONTEXT
 
typedef struct _COPY_PROGRESS_CONTEXTPCOPY_PROGRESS_CONTEXT
 

Functions

 DEBUG_CHANNEL (kernel32file)
 
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 SMSS.EXE to check whether there are some files to be renamed/moved or deleted. More...
 
DWORD WINAPI BasepGetComputerNameFromNtPath (IN PUNICODE_STRING NewPath, IN HANDLE NewHandle, OUT PWSTR ComputerName, IN OUT PULONG ComputerNameLength)
 
NTSTATUS WINAPI BasepNotifyTrackingService (IN OUT PHANDLE ExistingHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE NewHandle, IN PUNICODE_STRING NewPath)
 
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)
 
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)
 
BOOL WINAPI MoveFileWithProgressW (IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine, IN LPVOID lpData, IN DWORD dwFlags)
 
BOOL WINAPI MoveFileWithProgressA (IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName OPTIONAL, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, IN LPVOID lpData OPTIONAL, IN DWORD dwFlags)
 
BOOL WINAPI MoveFileW (IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName)
 
BOOL WINAPI MoveFileExW (IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
 
BOOL WINAPI MoveFileA (IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName)
 
BOOL WINAPI MoveFileExA (IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
 
BOOL WINAPI ReplaceFileA (IN LPCSTR lpReplacedFileName, IN LPCSTR lpReplacementFileName, IN LPCSTR lpBackupFileName OPTIONAL, IN DWORD dwReplaceFlags, IN LPVOID lpExclude, IN LPVOID lpReserved)
 
BOOL WINAPI ReplaceFileW (LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileName, LPCWSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved)
 
BOOL WINAPI PrivMoveFileIdentityW (IN LPCWSTR lpSource, IN LPCWSTR lpDestination, IN DWORD dwFlags)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 17 of file move.c.

◆ STRING_LENGTH

#define STRING_LENGTH   0x400

Typedef Documentation

◆ COPY_PROGRESS_CONTEXT

◆ PCOPY_PROGRESS_CONTEXT

Function Documentation

◆ BasepGetComputerNameFromNtPath()

DWORD WINAPI BasepGetComputerNameFromNtPath ( IN PUNICODE_STRING  NewPath,
IN HANDLE  NewHandle,
OUT PWSTR  ComputerName,
IN OUT PULONG  ComputerNameLength 
)

Definition at line 236 of file move.c.

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 }
#define ERROR_SUCCESS
Definition: deptool.c:10
_Must_inspect_result_ __drv_aliasesMem PDEVICE_OBJECT _In_ PDEVICE_OBJECT TargetDevice
Definition: iofuncs.h:690
#define TRUE
Definition: types.h:120
#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 ARRAYSIZE(array)
Definition: filtermapper.c:47
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:446
#define L(x)
Definition: ntvdm.h:50
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3272
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
unsigned int BOOL
Definition: ntddk_ex.h:94
DWORD WINAPI QueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:542
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MAX_PATH
Definition: compat.h:34
BOOL Query(LPCTSTR *ServiceArgs, DWORD ArgCount, BOOL bExtended)
Definition: query.c:292
WCHAR Letter
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:243
PRTL_UNICODE_STRING_BUFFER Path
unsigned short USHORT
Definition: pedump.c:61
#define NULL
Definition: types.h:112
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define DPRINT
Definition: sndvol32.h:71
#define ERROR_BAD_PATHNAME
Definition: winerror.h:233
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14

Referenced by BasepNotifyTrackingService().

◆ BasepMoveFileCopyProgress()

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 at line 672 of file move.c.

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 }
struct _COPY_PROGRESS_CONTEXT * PCOPY_PROGRESS_CONTEXT
#define MOVEFILE_WRITE_THROUGH
Definition: filesup.h:30
BOOL WINAPI FlushFileBuffers(IN HANDLE hFile)
Definition: fileinfo.c:25
unsigned long DWORD
Definition: ntddk_ex.h:95

Referenced by MoveFileWithProgressW().

◆ BasepMoveFileDelayed()

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 SMSS.EXE to check whether there are some files to be renamed/moved or deleted.

Parameters
[in]ExistingPathFull NT path to the file to rename/move or delete.
[in]NewPathFull NT path to the moved/renamed file; or an empty string if the file is to be deleted.
[in]KeyIdSelects an alternate "PendingFileRenameOperationsXXX" registry value.
[in]CreateIfNotFoundTRUE if the file needs to be created if it does not already exist, FALSE if not.
Remarks
If both ExistingPath and NewPath strings are non-empty, the file is moved, otherwise it is deleted.
Note
The registry value is a list of NULL-terminated strings, which is itself terminated with an empty NULL-terminated string (single 0-byte). When a new entry is added, if NewPath is empty, then the second entry is simply a single NULL. Otherwise the second file path goes there. Each path is in NT format (e.g. path prepended with \??) and the second file path gets also a '!' as the first character if MOVEFILE_REPLACE_EXISTING is specified.

Examples:

\??\D:\test\file1[0] !\??\D:\test\file1_renamed[0] \??\D:\test\delete[0] [0] <- file is to be deleted, second string empty \??\D:\test\file2[0] !\??\D:\test\file2_renamed[0] [0] <- indicates end of strings

or:

\??\D:\test\file1[0] !\??\D:\test\file1_renamed[0] \??\D:\test\delete[0] [0] <- file is to be deleted, second string empty [0] <- indicates end of strings

@implemented

Definition at line 88 of file move.c.

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 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define STRING_LENGTH
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3767
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4711
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define OBJ_OPENIF
Definition: winternl.h:229
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define L(x)
Definition: ntvdm.h:50
#define UNICODE_NULL
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define GENERIC_WRITE
Definition: nt_native.h:90
Definition: bufpool.h:45
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
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)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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 STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define REG_OPTION_BACKUP_RESTORE
Definition: nt_native.h:1066
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define GENERIC_READ
Definition: compat.h:135
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#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
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751

Referenced by MoveFileWithProgressW().

◆ BasepNotifyTrackingService()

NTSTATUS WINAPI BasepNotifyTrackingService ( IN OUT PHANDLE  ExistingHandle,
IN POBJECT_ATTRIBUTES  ObjectAttributes,
IN HANDLE  NewHandle,
IN PUNICODE_STRING  NewPath 
)

Definition at line 395 of file move.c.

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 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define CloseHandle
Definition: compat.h:739
char CHAR
Definition: xmlstorage.h:175
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)
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
STRING OEM_STRING
Definition: umtypes.h:203
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FILE_SHARE_READ
Definition: compat.h:136
#define FALSE
Definition: types.h:117
#define ANSI_NULL
#define GENERIC_WRITE
Definition: nt_native.h:90
Definition: bufpool.h:45
DWORD WINAPI BasepGetComputerNameFromNtPath(IN PUNICODE_STRING NewPath, IN HANDLE NewHandle, OUT PWSTR ComputerName, IN OUT PULONG ComputerNameLength)
Definition: move.c:236
_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
Status
Definition: gdiplustypes.h:24
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
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToOemString(POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
#define SYNCHRONIZE
Definition: nt_native.h:61
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:243
struct _FILE_TRACKING_INFORMATION FILE_TRACKING_INFORMATION
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
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

Referenced by MoveFileWithProgressW(), and PrivMoveFileIdentityW().

◆ BasepOpenFileForMove()

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 at line 548 of file move.c.

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 }
_SEH2_TRY
Definition: create.c:4226
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2654
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
_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
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
HANDLE ContainingDirectory
Definition: rtltypes.h:1381
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)
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
_SEH2_END
Definition: create.c:4400
#define FILE_SHARE_READ
Definition: compat.h:136
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToRelativeNtPathName_U(_In_ PCWSTR DosName, _Out_ PUNICODE_STRING NtName, _Out_ PCWSTR *PartName, _Out_ PRTL_RELATIVE_NAME_U RelativeName)
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7231
return STATUS_NOT_IMPLEMENTED
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
Status
Definition: gdiplustypes.h:24
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
#define FILE_ATTRIBUTE_DEVICE
Definition: disk.h:27
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_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 STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define SYNCHRONIZE
Definition: nt_native.h:61
_SEH2_FINALLY
Definition: create.c:4371
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1230
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define NULL
Definition: types.h:112
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
unsigned int ULONG
Definition: retypes.h:1
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
UNICODE_STRING RelativeName
Definition: rtltypes.h:1380
Definition: File.h:15
#define _SEH2_LEAVE
Definition: filesup.c:20
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46

Referenced by PrivMoveFileIdentityW().

◆ DEBUG_CHANNEL()

DEBUG_CHANNEL ( kernel32file  )

◆ MoveFileA()

BOOL WINAPI MoveFileA ( IN LPCSTR  lpExistingFileName,
IN LPCSTR  lpNewFileName 
)

Definition at line 1137 of file move.c.

1139 {
1140  return MoveFileWithProgressA(lpExistingFileName,
1141  lpNewFileName,
1142  NULL,
1143  NULL,
1145 }
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 MOVEFILE_COPY_ALLOWED
Definition: filesup.h:29
#define NULL
Definition: types.h:112

Referenced by DosInt21h(), mmioDosIOProc(), test_continuouscabs(), test_delete(), test_filenames(), test_FindFirstChangeNotification(), test_MoveFileA(), and VerInstallFileA().

◆ MoveFileExA()

BOOL WINAPI MoveFileExA ( IN LPCSTR  lpExistingFileName,
IN LPCSTR lpNewFileName  OPTIONAL,
IN DWORD  dwFlags 
)

Definition at line 1153 of file move.c.

1156 {
1157  return MoveFileWithProgressA(lpExistingFileName,
1158  lpNewFileName,
1159  NULL,
1160  NULL,
1161  dwFlags);
1162 }
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
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define NULL
Definition: types.h:112

Referenced by cleanup_eventlog(), process_pending_renames(), and rename().

◆ MoveFileExW()

BOOL WINAPI MoveFileExW ( IN LPCWSTR  lpExistingFileName,
IN LPCWSTR lpNewFileName  OPTIONAL,
IN DWORD  dwFlags 
)

Definition at line 1120 of file move.c.

1123 {
1124  return MoveFileWithProgressW(lpExistingFileName,
1125  lpNewFileName,
1126  NULL,
1127  NULL,
1128  dwFlags);
1129 }
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define NULL
Definition: types.h:112
BOOL WINAPI MoveFileWithProgressW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine, IN LPVOID lpData, IN DWORD dwFlags)
Definition: move.c:718

Referenced by _wrename(), BackgroundCopyJob_Complete(), DelayedMove(), do_file_copyW(), extract_cabinet_file(), msi_move_file(), pendingRename(), and SaveDefaultUserHive().

◆ MoveFileW()

BOOL WINAPI MoveFileW ( IN LPCWSTR  lpExistingFileName,
IN LPCWSTR  lpNewFileName 
)

Definition at line 1104 of file move.c.

1106 {
1107  return MoveFileWithProgressW(lpExistingFileName,
1108  lpNewFileName,
1109  NULL,
1110  NULL,
1112 }
#define MOVEFILE_COPY_ALLOWED
Definition: filesup.h:29
#define NULL
Definition: types.h:112
BOOL WINAPI MoveFileWithProgressW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine, IN LPVOID lpData, IN DWORD dwFlags)
Definition: move.c:718

Referenced by BrsFolder_Treeview_Rename(), BtrfsRecv::cmd_rename(), CFileDefExt::GeneralPageProc(), RecycleBin5_RecycleBin5_DeleteFile(), CFSFolder::SetNameOf(), SetupCommitFileQueueW(), SHNotifyMoveFileW(), test_MoveFileW(), test_readdirectorychanges_cr(), and wmain().

◆ MoveFileWithProgressA()

BOOL WINAPI MoveFileWithProgressA ( IN LPCSTR  lpExistingFileName,
IN LPCSTR lpNewFileName  OPTIONAL,
IN LPPROGRESS_ROUTINE lpProgressRoutine  OPTIONAL,
IN LPVOID lpData  OPTIONAL,
IN DWORD  dwFlags 
)

Definition at line 1059 of file move.c.

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 }
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define NULL
Definition: types.h:112
BOOL WINAPI MoveFileWithProgressW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine, IN LPVOID lpData, IN DWORD dwFlags)
Definition: move.c:718

Referenced by MoveFileA(), and MoveFileExA().

◆ MoveFileWithProgressW()

BOOL WINAPI MoveFileWithProgressW ( IN LPCWSTR  lpExistingFileName,
IN LPCWSTR  lpNewFileName,
IN LPPROGRESS_ROUTINE  lpProgressRoutine,
IN LPVOID  lpData,
IN DWORD  dwFlags 
)

Definition at line 718 of file move.c.

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 }
_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
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 CloseHandle
Definition: compat.h:739
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_NOT_SAME_DEVICE
Definition: ntstatus.h:448
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define MOVEFILE_REPLACE_EXISTING
Definition: filesup.h:28
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint16_t * PWSTR
Definition: typedefs.h:56
#define MOVEFILE_COPY_ALLOWED
Definition: filesup.h:29
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 INVALID_HANDLE_VALUE
Definition: compat.h:731
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
_In_ HANDLE SourceHandle
Definition: obfuncs.h:429
_SEH2_END
Definition: create.c:4400
#define FILE_SHARE_READ
Definition: compat.h:136
#define IO_REPARSE_TAG_MOUNT_POINT
Definition: iotypes.h:7231
return STATUS_NOT_IMPLEMENTED
#define L(x)
Definition: ntvdm.h:50
#define STATUS_SHARING_VIOLATION
Definition: udferr_usr.h:154
#define FALSE
Definition: types.h:117
#define MOVEFILE_WRITE_THROUGH
Definition: filesup.h:30
unsigned int BOOL
Definition: ntddk_ex.h:94
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
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
#define COPY_FILE_OPEN_SOURCE_FOR_WRITE
Definition: winbase.h:207
#define FILE_WRITE_THROUGH
Definition: from_kernel.h:26
#define MOVEFILE_DELAY_UNTIL_REBOOT
Definition: winbase.h:400
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
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
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
Status
Definition: gdiplustypes.h:24
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
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#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
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
#define SYNCHRONIZE
Definition: nt_native.h:61
_SEH2_FINALLY
Definition: create.c:4371
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#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
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
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
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define _SEH2_LEAVE
Definition: filesup.c:20
#define DPRINT
Definition: sndvol32.h:71
NTSYSAPI ULONG NTAPI RtlIsDosDeviceName_U(_In_ PCWSTR Name)
#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)
#define DELETE
Definition: nt_native.h:57
NTSYSAPI RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(_In_ PCWSTR Path)

Referenced by MoveFileExW(), MoveFileW(), MoveFileWithProgressA(), and SHNotifyMoveFileW().

◆ PrivMoveFileIdentityW()

BOOL WINAPI PrivMoveFileIdentityW ( IN LPCWSTR  lpSource,
IN LPCWSTR  lpDestination,
IN DWORD  dwFlags 
)

Definition at line 1385 of file move.c.

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 }
_SEH2_TRY
Definition: create.c:4226
#define TRUE
Definition: types.h:120
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
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
_In_ HANDLE SourceHandle
Definition: obfuncs.h:429
_SEH2_END
Definition: create.c:4400
#define FILE_WRITE_ATTRIBUTES
Definition: nt_native.h:649
#define FILE_SHARE_READ
Definition: compat.h:136
#define PRIV_ALLOW_NON_TRACKABLE
Definition: kernel32.h:134
NTSTATUS WINAPI BasepNotifyTrackingService(IN OUT PHANDLE ExistingHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE NewHandle, IN PUNICODE_STRING NewPath)
Definition: move.c:395
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
#define FILE_WRITE_DATA
Definition: nt_native.h:631
Status
Definition: gdiplustypes.h:24
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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_SHARE_DELETE
Definition: nt_native.h:682
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
_SEH2_FINALLY
Definition: create.c:4371
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define NULL
Definition: types.h:112
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#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
ULONG ACCESS_MASK
Definition: nt_native.h:40
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
#define DELETE
Definition: nt_native.h:57
LONGLONG QuadPart
Definition: typedefs.h:114

◆ ReplaceFileA()

BOOL WINAPI ReplaceFileA ( IN LPCSTR  lpReplacedFileName,
IN LPCSTR  lpReplacementFileName,
IN LPCSTR lpBackupFileName  OPTIONAL,
IN DWORD  dwReplaceFlags,
IN LPVOID  lpExclude,
IN LPVOID  lpReserved 
)

Definition at line 1169 of file move.c.

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 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName, LPCWSTR lpReplacementFileName, LPCWSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved)
Definition: move.c:1231
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define SetLastError(x)
Definition: compat.h:752
#define NULL
Definition: types.h:112

◆ ReplaceFileW()

BOOL WINAPI ReplaceFileW ( LPCWSTR  lpReplacedFileName,
LPCWSTR  lpReplacementFileName,
LPCWSTR  lpBackupFileName,
DWORD  dwReplaceFlags,
LPVOID  lpExclude,
LPVOID  lpReserved 
)

Definition at line 1231 of file move.c.

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 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define ERROR_SUCCESS
Definition: deptool.c:10
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define TRUE
Definition: types.h:120
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1004
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_SHARE_READ
Definition: compat.h:136
#define STATUS_END_OF_FILE
Definition: shellext.h:67
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FIXME(fmt,...)
Definition: debug.h:111
Definition: bufpool.h:45
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
Status
Definition: gdiplustypes.h:24
#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
#define TRACE(s)
Definition: solgame.cpp:4
#define GetProcessHeap()
Definition: compat.h:736
#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
unsigned long DWORD
Definition: ntddk_ex.h:95
#define WRITE_DAC
Definition: nt_native.h:59
BOOL Error
Definition: chkdsk.c:66
#define SetLastError(x)
Definition: compat.h:752
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
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
#define GENERIC_READ
Definition: compat.h:135
static const WCHAR Cleanup[]
Definition: register.c:80
#define SYNCHRONIZE
Definition: nt_native.h:61
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define NULL
Definition: types.h:112
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
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

Referenced by ReplaceFileA().