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 %d 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
);
201 LPCWSTR lpExistingFileName
,
202 LPCWSTR lpNewFileName
,
203 LPPROGRESS_ROUTINE lpProgressRoutine
,
210 HANDLE FileHandleSource
, FileHandleDest
;
211 IO_STATUS_BLOCK IoStatusBlock
;
212 FILE_STANDARD_INFORMATION FileStandard
;
213 FILE_BASIC_INFORMATION FileBasic
;
215 BOOL KeepDestOnError
= FALSE
;
218 FileHandleSource
= CreateFileW(lpExistingFileName
,
220 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
223 FILE_ATTRIBUTE_NORMAL
|FILE_FLAG_NO_BUFFERING
,
225 if (INVALID_HANDLE_VALUE
!= FileHandleSource
)
227 errCode
= NtQueryInformationFile(FileHandleSource
,
230 sizeof(FILE_STANDARD_INFORMATION
),
231 FileStandardInformation
);
232 if (!NT_SUCCESS(errCode
))
234 TRACE("Status 0x%08x obtaining FileStandardInformation for source\n", errCode
);
235 BaseSetLastNTError(errCode
);
239 errCode
= NtQueryInformationFile(FileHandleSource
,
240 &IoStatusBlock
,&FileBasic
,
241 sizeof(FILE_BASIC_INFORMATION
),
242 FileBasicInformation
);
243 if (!NT_SUCCESS(errCode
))
245 TRACE("Status 0x%08x obtaining FileBasicInformation for source\n", errCode
);
246 BaseSetLastNTError(errCode
);
250 FileHandleDest
= CreateFileW(lpNewFileName
,
254 dwCopyFlags
? CREATE_NEW
: CREATE_ALWAYS
,
255 FileBasic
.FileAttributes
,
257 if (INVALID_HANDLE_VALUE
!= FileHandleDest
)
259 errCode
= CopyLoop(FileHandleSource
,
261 FileStandard
.EndOfFile
,
266 if (!NT_SUCCESS(errCode
))
268 BaseSetLastNTError(errCode
);
274 t
.QuadPart
= FileBasic
.LastWriteTime
.QuadPart
;
275 errCode
= SetLastWriteTime(FileHandleDest
, t
);
276 if (!NT_SUCCESS(errCode
))
278 BaseSetLastNTError(errCode
);
285 NtClose(FileHandleDest
);
286 if (! RC
&& ! KeepDestOnError
)
288 SystemError
= GetLastError();
289 SetFileAttributesW(lpNewFileName
, FILE_ATTRIBUTE_NORMAL
);
290 DeleteFileW(lpNewFileName
);
291 SetLastError(SystemError
);
296 WARN("Error %d during opening of dest file\n", GetLastError());
300 NtClose(FileHandleSource
);
304 WARN("Error %d during opening of source file\n", GetLastError());
316 CopyFileExA(IN LPCSTR lpExistingFileName
,
317 IN LPCSTR lpNewFileName
,
318 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL
,
319 IN LPVOID lpData OPTIONAL
,
320 IN LPBOOL pbCancel OPTIONAL
,
321 IN DWORD dwCopyFlags
)
324 UNICODE_STRING lpNewFileNameW
;
325 PUNICODE_STRING lpExistingFileNameW
;
327 lpExistingFileNameW
= Basep8BitStringToStaticUnicodeString(lpExistingFileName
);
328 if (!lpExistingFileName
)
333 if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW
, lpNewFileName
))
335 Result
= CopyFileExW(lpExistingFileNameW
->Buffer
,
336 lpNewFileNameW
.Buffer
,
342 RtlFreeUnicodeString(&lpNewFileNameW
);
355 LPCSTR lpExistingFileName
,
356 LPCSTR lpNewFileName
,
360 return CopyFileExA (lpExistingFileName
,
375 LPCWSTR lpExistingFileName
,
376 LPCWSTR lpNewFileName
,
380 return CopyFileExW (lpExistingFileName
,
395 LPCWSTR lpExistingFileName
,
396 LPCWSTR lpNewFileName
,
397 LPPROGRESS_ROUTINE lpProgressRoutine
,