2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/file/copy.c
5 * PURPOSE: Copying files
6 * PROGRAMMER: Ariadne (ariadne@xs4all.nl)
9 * 07/02/99 Moved to seperate 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 if (NT_SUCCESS(errCode
) && (NULL
== pbCancel
|| ! *pbCancel
))
106 errCode
= NtWriteFile(FileHandleDest
,
110 (PIO_STATUS_BLOCK
)&IoStatusBlock
,
112 IoStatusBlock
.Information
,
115 if (NT_SUCCESS(errCode
))
117 BytesCopied
.QuadPart
+= IoStatusBlock
.Information
;
121 WARN("Error 0x%08x reading writing to dest\n", errCode
);
124 else if (!NT_SUCCESS(errCode
))
126 if (STATUS_END_OF_FILE
== errCode
)
128 EndOfFileFound
= TRUE
;
129 errCode
= STATUS_SUCCESS
;
133 WARN("Error 0x%08x reading from source\n", errCode
);
139 if (! EndOfFileFound
&& (NULL
!= pbCancel
&& *pbCancel
))
141 TRACE("User requested cancel\n");
142 errCode
= STATUS_REQUEST_ABORTED
;
145 NtFreeVirtualMemory(NtCurrentProcess(),
152 TRACE("Error 0x%08x allocating buffer of %lu bytes\n", errCode
, RegionSize
);
161 LARGE_INTEGER LastWriteTime
164 NTSTATUS errCode
= STATUS_SUCCESS
;
165 IO_STATUS_BLOCK IoStatusBlock
;
166 FILE_BASIC_INFORMATION FileBasic
;
168 errCode
= NtQueryInformationFile (FileHandle
,
171 sizeof(FILE_BASIC_INFORMATION
),
172 FileBasicInformation
);
173 if (!NT_SUCCESS(errCode
))
175 WARN("Error 0x%08x obtaining FileBasicInformation\n", errCode
);
179 FileBasic
.LastWriteTime
.QuadPart
= LastWriteTime
.QuadPart
;
180 errCode
= NtSetInformationFile (FileHandle
,
183 sizeof(FILE_BASIC_INFORMATION
),
184 FileBasicInformation
);
185 if (!NT_SUCCESS(errCode
))
187 WARN("Error 0x%0x setting LastWriteTime\n", errCode
);
195 BasepCopyFileExW(IN LPCWSTR lpExistingFileName
,
196 IN LPCWSTR lpNewFileName
,
197 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL
,
198 IN LPVOID lpData OPTIONAL
,
199 IN LPBOOL pbCancel OPTIONAL
,
200 IN DWORD dwCopyFlags
,
201 IN DWORD dwBasepFlags
,
202 OUT LPHANDLE lpExistingHandle
,
203 OUT LPHANDLE lpNewHandle
)
206 HANDLE FileHandleSource
, FileHandleDest
;
207 IO_STATUS_BLOCK IoStatusBlock
;
208 FILE_STANDARD_INFORMATION FileStandard
;
209 FILE_BASIC_INFORMATION FileBasic
;
211 BOOL KeepDestOnError
= FALSE
;
214 FileHandleSource
= CreateFileW(lpExistingFileName
,
216 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
219 FILE_ATTRIBUTE_NORMAL
|FILE_FLAG_NO_BUFFERING
,
221 if (INVALID_HANDLE_VALUE
!= FileHandleSource
)
223 errCode
= NtQueryInformationFile(FileHandleSource
,
226 sizeof(FILE_STANDARD_INFORMATION
),
227 FileStandardInformation
);
228 if (!NT_SUCCESS(errCode
))
230 TRACE("Status 0x%08x obtaining FileStandardInformation for source\n", errCode
);
231 BaseSetLastNTError(errCode
);
235 errCode
= NtQueryInformationFile(FileHandleSource
,
236 &IoStatusBlock
,&FileBasic
,
237 sizeof(FILE_BASIC_INFORMATION
),
238 FileBasicInformation
);
239 if (!NT_SUCCESS(errCode
))
241 TRACE("Status 0x%08x obtaining FileBasicInformation for source\n", errCode
);
242 BaseSetLastNTError(errCode
);
246 FileHandleDest
= CreateFileW(lpNewFileName
,
250 dwCopyFlags
? CREATE_NEW
: CREATE_ALWAYS
,
251 FileBasic
.FileAttributes
,
253 if (INVALID_HANDLE_VALUE
!= FileHandleDest
)
255 errCode
= CopyLoop(FileHandleSource
,
257 FileStandard
.EndOfFile
,
262 if (!NT_SUCCESS(errCode
))
264 BaseSetLastNTError(errCode
);
270 t
.QuadPart
= FileBasic
.LastWriteTime
.QuadPart
;
271 errCode
= SetLastWriteTime(FileHandleDest
, t
);
272 if (!NT_SUCCESS(errCode
))
274 BaseSetLastNTError(errCode
);
281 NtClose(FileHandleDest
);
282 if (! RC
&& ! KeepDestOnError
)
284 SystemError
= GetLastError();
285 SetFileAttributesW(lpNewFileName
, FILE_ATTRIBUTE_NORMAL
);
286 DeleteFileW(lpNewFileName
);
287 SetLastError(SystemError
);
292 WARN("Error %lu during opening of dest file\n", GetLastError());
296 NtClose(FileHandleSource
);
300 WARN("Error %lu during opening of source file\n", GetLastError());
311 CopyFileExW(IN LPCWSTR lpExistingFileName
,
312 IN LPCWSTR lpNewFileName
,
313 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL
,
314 IN LPVOID lpData OPTIONAL
,
315 IN LPBOOL pbCancel OPTIONAL
,
316 IN DWORD dwCopyFlags
)
319 HANDLE ExistingHandle
, NewHandle
;
321 ExistingHandle
= INVALID_HANDLE_VALUE
;
322 NewHandle
= INVALID_HANDLE_VALUE
;
326 Ret
= BasepCopyFileExW(lpExistingFileName
,
338 if (ExistingHandle
!= INVALID_HANDLE_VALUE
)
340 CloseHandle(ExistingHandle
);
343 if (NewHandle
!= INVALID_HANDLE_VALUE
)
345 CloseHandle(NewHandle
);
359 CopyFileExA(IN LPCSTR lpExistingFileName
,
360 IN LPCSTR lpNewFileName
,
361 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL
,
362 IN LPVOID lpData OPTIONAL
,
363 IN LPBOOL pbCancel OPTIONAL
,
364 IN DWORD dwCopyFlags
)
367 UNICODE_STRING lpNewFileNameW
;
368 PUNICODE_STRING lpExistingFileNameW
;
370 lpExistingFileNameW
= Basep8BitStringToStaticUnicodeString(lpExistingFileName
);
371 if (!lpExistingFileNameW
)
376 if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW
, lpNewFileName
))
378 Result
= CopyFileExW(lpExistingFileNameW
->Buffer
,
379 lpNewFileNameW
.Buffer
,
385 RtlFreeUnicodeString(&lpNewFileNameW
);
397 CopyFileA(IN LPCSTR lpExistingFileName
,
398 IN LPCSTR lpNewFileName
,
399 IN BOOL bFailIfExists
)
402 UNICODE_STRING lpNewFileNameW
;
403 PUNICODE_STRING lpExistingFileNameW
;
405 lpExistingFileNameW
= Basep8BitStringToStaticUnicodeString(lpExistingFileName
);
406 if (!lpExistingFileNameW
)
411 if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW
, lpNewFileName
))
413 Result
= CopyFileExW(lpExistingFileNameW
->Buffer
,
414 lpNewFileNameW
.Buffer
,
418 (bFailIfExists
? COPY_FILE_FAIL_IF_EXISTS
: 0));
420 RtlFreeUnicodeString(&lpNewFileNameW
);
432 CopyFileW(IN LPCWSTR lpExistingFileName
,
433 IN LPCWSTR lpNewFileName
,
434 IN BOOL bFailIfExists
)
436 return CopyFileExW(lpExistingFileName
,
441 (bFailIfExists
? COPY_FILE_FAIL_IF_EXISTS
: 0));
450 PrivCopyFileExW(IN LPCWSTR lpExistingFileName
,
451 IN LPCWSTR lpNewFileName
,
452 IN LPPROGRESS_ROUTINE lpProgressRoutine
,
455 IN DWORD dwCopyFlags
)
458 HANDLE ExistingHandle
, NewHandle
;
460 ExistingHandle
= INVALID_HANDLE_VALUE
;
461 NewHandle
= INVALID_HANDLE_VALUE
;
463 /* Check for incompatible flags */
464 if (dwCopyFlags
& COPY_FILE_FAIL_IF_EXISTS
&& dwCopyFlags
& BASEP_COPY_REPLACE
)
466 SetLastError(ERROR_INVALID_PARAMETER
);
472 Ret
= BasepCopyFileExW(lpExistingFileName
,
477 dwCopyFlags
& BASEP_COPY_PUBLIC_MASK
,
478 dwCopyFlags
& BASEP_COPY_BASEP_MASK
,
484 if (ExistingHandle
!= INVALID_HANDLE_VALUE
)
486 CloseHandle(ExistingHandle
);
489 if (NewHandle
!= INVALID_HANDLE_VALUE
)
491 CloseHandle(NewHandle
);