2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/file/copy.c
5 * PURPOSE: Copying files
6 * PROGRAMMER: Ariadne (ariadne@xs4all.nl)
9 * 07/02/99 Moved to separate file
12 /* INCLUDES ****************************************************************/
19 DEBUG_CHANNEL(kernel32file
);
22 /* FUNCTIONS ****************************************************************/
27 HANDLE FileHandleSource
,
28 HANDLE FileHandleDest
,
29 LARGE_INTEGER SourceFileSize
,
30 LPPROGRESS_ROUTINE lpProgressRoutine
,
37 IO_STATUS_BLOCK IoStatusBlock
;
38 UCHAR
*lpBuffer
= NULL
;
39 SIZE_T RegionSize
= 0x10000;
40 LARGE_INTEGER BytesCopied
;
46 errCode
= NtAllocateVirtualMemory(NtCurrentProcess(),
50 MEM_RESERVE
| MEM_COMMIT
,
53 if (NT_SUCCESS(errCode
))
55 BytesCopied
.QuadPart
= 0;
56 EndOfFileFound
= FALSE
;
57 CallbackReason
= CALLBACK_STREAM_SWITCH
;
58 while (! EndOfFileFound
&&
59 NT_SUCCESS(errCode
) &&
60 (NULL
== pbCancel
|| ! *pbCancel
))
62 if (NULL
!= lpProgressRoutine
)
64 ProgressResult
= (*lpProgressRoutine
)(SourceFileSize
,
73 switch (ProgressResult
)
76 TRACE("Progress callback requested cancel\n");
77 errCode
= STATUS_REQUEST_ABORTED
;
80 TRACE("Progress callback requested stop\n");
81 errCode
= STATUS_REQUEST_ABORTED
;
85 lpProgressRoutine
= NULL
;
87 case PROGRESS_CONTINUE
:
91 CallbackReason
= CALLBACK_CHUNK_FINISHED
;
93 if (NT_SUCCESS(errCode
))
95 errCode
= NtReadFile(FileHandleSource
,
99 (PIO_STATUS_BLOCK
)&IoStatusBlock
,
104 /* With sync read, 0 length + status success mean EOF:
105 * https://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx
107 if (NT_SUCCESS(errCode
) && IoStatusBlock
.Information
== 0)
109 errCode
= STATUS_END_OF_FILE
;
111 if (NT_SUCCESS(errCode
) && (NULL
== pbCancel
|| ! *pbCancel
))
113 errCode
= NtWriteFile(FileHandleDest
,
117 (PIO_STATUS_BLOCK
)&IoStatusBlock
,
119 IoStatusBlock
.Information
,
122 if (NT_SUCCESS(errCode
))
124 BytesCopied
.QuadPart
+= IoStatusBlock
.Information
;
128 WARN("Error 0x%08x reading writing to dest\n", errCode
);
131 else if (!NT_SUCCESS(errCode
))
133 if (STATUS_END_OF_FILE
== errCode
)
135 EndOfFileFound
= TRUE
;
136 errCode
= STATUS_SUCCESS
;
140 WARN("Error 0x%08x reading from source\n", errCode
);
146 if (! EndOfFileFound
&& (NULL
!= pbCancel
&& *pbCancel
))
148 TRACE("User requested cancel\n");
149 errCode
= STATUS_REQUEST_ABORTED
;
152 NtFreeVirtualMemory(NtCurrentProcess(),
159 TRACE("Error 0x%08x allocating buffer of %lu bytes\n", errCode
, RegionSize
);
168 LARGE_INTEGER LastWriteTime
171 NTSTATUS errCode
= STATUS_SUCCESS
;
172 IO_STATUS_BLOCK IoStatusBlock
;
173 FILE_BASIC_INFORMATION FileBasic
;
175 errCode
= NtQueryInformationFile (FileHandle
,
178 sizeof(FILE_BASIC_INFORMATION
),
179 FileBasicInformation
);
180 if (!NT_SUCCESS(errCode
))
182 WARN("Error 0x%08x obtaining FileBasicInformation\n", errCode
);
186 FileBasic
.LastWriteTime
.QuadPart
= LastWriteTime
.QuadPart
;
187 errCode
= NtSetInformationFile (FileHandle
,
190 sizeof(FILE_BASIC_INFORMATION
),
191 FileBasicInformation
);
192 if (!NT_SUCCESS(errCode
))
194 WARN("Error 0x%0x setting LastWriteTime\n", errCode
);
202 BasepCopyFileExW(IN LPCWSTR lpExistingFileName
,
203 IN LPCWSTR lpNewFileName
,
204 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL
,
205 IN LPVOID lpData OPTIONAL
,
206 IN LPBOOL pbCancel OPTIONAL
,
207 IN DWORD dwCopyFlags
,
208 IN DWORD dwBasepFlags
,
209 OUT LPHANDLE lpExistingHandle
,
210 OUT LPHANDLE lpNewHandle
)
213 HANDLE FileHandleSource
, FileHandleDest
;
214 IO_STATUS_BLOCK IoStatusBlock
;
215 FILE_STANDARD_INFORMATION FileStandard
;
216 FILE_BASIC_INFORMATION FileBasic
;
218 BOOL KeepDestOnError
= FALSE
;
221 FileHandleSource
= CreateFileW(lpExistingFileName
,
223 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
226 FILE_ATTRIBUTE_NORMAL
|FILE_FLAG_NO_BUFFERING
,
228 if (INVALID_HANDLE_VALUE
!= FileHandleSource
)
230 errCode
= NtQueryInformationFile(FileHandleSource
,
233 sizeof(FILE_STANDARD_INFORMATION
),
234 FileStandardInformation
);
235 if (!NT_SUCCESS(errCode
))
237 TRACE("Status 0x%08x obtaining FileStandardInformation for source\n", errCode
);
238 BaseSetLastNTError(errCode
);
242 errCode
= NtQueryInformationFile(FileHandleSource
,
243 &IoStatusBlock
,&FileBasic
,
244 sizeof(FILE_BASIC_INFORMATION
),
245 FileBasicInformation
);
246 if (!NT_SUCCESS(errCode
))
248 TRACE("Status 0x%08x obtaining FileBasicInformation for source\n", errCode
);
249 BaseSetLastNTError(errCode
);
253 FileHandleDest
= CreateFileW(lpNewFileName
,
257 dwCopyFlags
? CREATE_NEW
: CREATE_ALWAYS
,
258 FileBasic
.FileAttributes
,
260 if (INVALID_HANDLE_VALUE
!= FileHandleDest
)
262 errCode
= CopyLoop(FileHandleSource
,
264 FileStandard
.EndOfFile
,
269 if (!NT_SUCCESS(errCode
))
271 BaseSetLastNTError(errCode
);
277 t
.QuadPart
= FileBasic
.LastWriteTime
.QuadPart
;
278 errCode
= SetLastWriteTime(FileHandleDest
, t
);
279 if (!NT_SUCCESS(errCode
))
281 BaseSetLastNTError(errCode
);
288 NtClose(FileHandleDest
);
289 if (! RC
&& ! KeepDestOnError
)
291 SystemError
= GetLastError();
292 SetFileAttributesW(lpNewFileName
, FILE_ATTRIBUTE_NORMAL
);
293 DeleteFileW(lpNewFileName
);
294 SetLastError(SystemError
);
299 WARN("Error %lu during opening of dest file\n", GetLastError());
303 NtClose(FileHandleSource
);
307 WARN("Error %lu during opening of source file\n", GetLastError());
318 CopyFileExW(IN LPCWSTR lpExistingFileName
,
319 IN LPCWSTR lpNewFileName
,
320 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL
,
321 IN LPVOID lpData OPTIONAL
,
322 IN LPBOOL pbCancel OPTIONAL
,
323 IN DWORD dwCopyFlags
)
326 HANDLE ExistingHandle
, NewHandle
;
328 ExistingHandle
= INVALID_HANDLE_VALUE
;
329 NewHandle
= INVALID_HANDLE_VALUE
;
333 Ret
= BasepCopyFileExW(lpExistingFileName
,
345 if (ExistingHandle
!= INVALID_HANDLE_VALUE
)
347 CloseHandle(ExistingHandle
);
350 if (NewHandle
!= INVALID_HANDLE_VALUE
)
352 CloseHandle(NewHandle
);
366 CopyFileExA(IN LPCSTR lpExistingFileName
,
367 IN LPCSTR lpNewFileName
,
368 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL
,
369 IN LPVOID lpData OPTIONAL
,
370 IN LPBOOL pbCancel OPTIONAL
,
371 IN DWORD dwCopyFlags
)
374 UNICODE_STRING lpNewFileNameW
;
375 PUNICODE_STRING lpExistingFileNameW
;
377 lpExistingFileNameW
= Basep8BitStringToStaticUnicodeString(lpExistingFileName
);
378 if (!lpExistingFileNameW
)
383 if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW
, lpNewFileName
))
385 Result
= CopyFileExW(lpExistingFileNameW
->Buffer
,
386 lpNewFileNameW
.Buffer
,
392 RtlFreeUnicodeString(&lpNewFileNameW
);
404 CopyFileA(IN LPCSTR lpExistingFileName
,
405 IN LPCSTR lpNewFileName
,
406 IN BOOL bFailIfExists
)
409 UNICODE_STRING lpNewFileNameW
;
410 PUNICODE_STRING lpExistingFileNameW
;
412 lpExistingFileNameW
= Basep8BitStringToStaticUnicodeString(lpExistingFileName
);
413 if (!lpExistingFileNameW
)
418 if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW
, lpNewFileName
))
420 Result
= CopyFileExW(lpExistingFileNameW
->Buffer
,
421 lpNewFileNameW
.Buffer
,
425 (bFailIfExists
? COPY_FILE_FAIL_IF_EXISTS
: 0));
427 RtlFreeUnicodeString(&lpNewFileNameW
);
439 CopyFileW(IN LPCWSTR lpExistingFileName
,
440 IN LPCWSTR lpNewFileName
,
441 IN BOOL bFailIfExists
)
443 return CopyFileExW(lpExistingFileName
,
448 (bFailIfExists
? COPY_FILE_FAIL_IF_EXISTS
: 0));
457 PrivCopyFileExW(IN LPCWSTR lpExistingFileName
,
458 IN LPCWSTR lpNewFileName
,
459 IN LPPROGRESS_ROUTINE lpProgressRoutine
,
462 IN DWORD dwCopyFlags
)
465 HANDLE ExistingHandle
, NewHandle
;
467 ExistingHandle
= INVALID_HANDLE_VALUE
;
468 NewHandle
= INVALID_HANDLE_VALUE
;
470 /* Check for incompatible flags */
471 if (dwCopyFlags
& COPY_FILE_FAIL_IF_EXISTS
&& dwCopyFlags
& BASEP_COPY_REPLACE
)
473 SetLastError(ERROR_INVALID_PARAMETER
);
479 Ret
= BasepCopyFileExW(lpExistingFileName
,
484 dwCopyFlags
& BASEP_COPY_PUBLIC_MASK
,
485 dwCopyFlags
& BASEP_COPY_BASEP_MASK
,
491 if (ExistingHandle
!= INVALID_HANDLE_VALUE
)
493 CloseHandle(ExistingHandle
);
496 if (NewHandle
!= INVALID_HANDLE_VALUE
)
498 CloseHandle(NewHandle
);