ReactOS 0.4.16-dev-340-g0540c21
copy.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/copy.c
5 * PURPOSE: Copying files
6 * PROGRAMMER: Ariadne (ariadne@xs4all.nl)
7 * UPDATE HISTORY:
8 * 01/11/98 Created
9 * 07/02/99 Moved to separate file
10 */
11
12/* INCLUDES ****************************************************************/
13
14#include <k32.h>
15#define NDEBUG
16#include <debug.h>
17
18#if DBG
20#endif
21
22/* FUNCTIONS ****************************************************************/
23
24
25static NTSTATUS
27 HANDLE FileHandleSource,
28 HANDLE FileHandleDest,
29 LARGE_INTEGER SourceFileSize,
30 LPPROGRESS_ROUTINE lpProgressRoutine,
31 LPVOID lpData,
32 BOOL *pbCancel,
33 BOOL *KeepDest
34)
35{
36 NTSTATUS errCode;
39 SIZE_T RegionSize = 0x10000;
41 DWORD CallbackReason;
42 DWORD ProgressResult;
43 BOOL EndOfFileFound;
44
45 *KeepDest = FALSE;
47 (PVOID *)&lpBuffer,
48 0,
52
53 if (NT_SUCCESS(errCode))
54 {
55 BytesCopied.QuadPart = 0;
56 EndOfFileFound = FALSE;
57 CallbackReason = CALLBACK_STREAM_SWITCH;
58 while (! EndOfFileFound &&
59 NT_SUCCESS(errCode) &&
60 (NULL == pbCancel || ! *pbCancel))
61 {
62 if (NULL != lpProgressRoutine)
63 {
64 ProgressResult = (*lpProgressRoutine)(SourceFileSize,
66 SourceFileSize,
68 0,
69 CallbackReason,
70 FileHandleSource,
71 FileHandleDest,
72 lpData);
73 switch (ProgressResult)
74 {
75 case PROGRESS_CANCEL:
76 TRACE("Progress callback requested cancel\n");
77 errCode = STATUS_REQUEST_ABORTED;
78 break;
79 case PROGRESS_STOP:
80 TRACE("Progress callback requested stop\n");
81 errCode = STATUS_REQUEST_ABORTED;
82 *KeepDest = TRUE;
83 break;
84 case PROGRESS_QUIET:
85 lpProgressRoutine = NULL;
86 break;
88 default:
89 break;
90 }
91 CallbackReason = CALLBACK_CHUNK_FINISHED;
92 }
93 if (NT_SUCCESS(errCode))
94 {
95 errCode = NtReadFile(FileHandleSource,
96 NULL,
97 NULL,
98 NULL,
100 lpBuffer,
102 NULL,
103 NULL);
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
106 */
107 if (NT_SUCCESS(errCode) && IoStatusBlock.Information == 0)
108 {
109 errCode = STATUS_END_OF_FILE;
110 }
111 if (NT_SUCCESS(errCode) && (NULL == pbCancel || ! *pbCancel))
112 {
113 errCode = NtWriteFile(FileHandleDest,
114 NULL,
115 NULL,
116 NULL,
118 lpBuffer,
120 NULL,
121 NULL);
122 if (NT_SUCCESS(errCode))
123 {
125 }
126 else
127 {
128 WARN("Error 0x%08x reading writing to dest\n", errCode);
129 }
130 }
131 else if (!NT_SUCCESS(errCode))
132 {
133 if (STATUS_END_OF_FILE == errCode)
134 {
135 EndOfFileFound = TRUE;
136 errCode = STATUS_SUCCESS;
137 }
138 else
139 {
140 WARN("Error 0x%08x reading from source\n", errCode);
141 }
142 }
143 }
144 }
145
146 if (! EndOfFileFound && (NULL != pbCancel && *pbCancel))
147 {
148 TRACE("User requested cancel\n");
149 errCode = STATUS_REQUEST_ABORTED;
150 }
151
153 (PVOID *)&lpBuffer,
154 &RegionSize,
156 }
157 else
158 {
159 TRACE("Error 0x%08x allocating buffer of %lu bytes\n", errCode, RegionSize);
160 }
161
162 return errCode;
163}
164
165static NTSTATUS
168 LARGE_INTEGER LastWriteTime
169)
170{
171 NTSTATUS errCode = STATUS_SUCCESS;
173 FILE_BASIC_INFORMATION FileBasic;
174
177 &FileBasic,
180 if (!NT_SUCCESS(errCode))
181 {
182 WARN("Error 0x%08x obtaining FileBasicInformation\n", errCode);
183 }
184 else
185 {
186 FileBasic.LastWriteTime.QuadPart = LastWriteTime.QuadPart;
189 &FileBasic,
192 if (!NT_SUCCESS(errCode))
193 {
194 WARN("Error 0x%0x setting LastWriteTime\n", errCode);
195 }
196 }
197
198 return errCode;
199}
200
201BOOL
202BasepCopyFileExW(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)
211{
212 NTSTATUS errCode;
213 HANDLE FileHandleSource, FileHandleDest;
215 FILE_STANDARD_INFORMATION FileStandard;
216 FILE_BASIC_INFORMATION FileBasic;
217 BOOL RC = FALSE;
218 BOOL KeepDestOnError = FALSE;
220
221 FileHandleSource = CreateFileW(lpExistingFileName,
224 NULL,
227 NULL);
228 if (INVALID_HANDLE_VALUE != FileHandleSource)
229 {
230 errCode = NtQueryInformationFile(FileHandleSource,
232 &FileStandard,
235 if (!NT_SUCCESS(errCode))
236 {
237 TRACE("Status 0x%08x obtaining FileStandardInformation for source\n", errCode);
238 BaseSetLastNTError(errCode);
239 }
240 else
241 {
242 errCode = NtQueryInformationFile(FileHandleSource,
243 &IoStatusBlock,&FileBasic,
246 if (!NT_SUCCESS(errCode))
247 {
248 TRACE("Status 0x%08x obtaining FileBasicInformation for source\n", errCode);
249 BaseSetLastNTError(errCode);
250 }
251 else
252 {
253 FileHandleDest = CreateFileW(lpNewFileName,
256 NULL,
257 dwCopyFlags ? CREATE_NEW : CREATE_ALWAYS,
258 FileBasic.FileAttributes,
259 NULL);
260 if (INVALID_HANDLE_VALUE != FileHandleDest)
261 {
262 errCode = CopyLoop(FileHandleSource,
263 FileHandleDest,
264 FileStandard.EndOfFile,
265 lpProgressRoutine,
266 lpData,
267 pbCancel,
268 &KeepDestOnError);
269 if (!NT_SUCCESS(errCode))
270 {
271 BaseSetLastNTError(errCode);
272 }
273 else
274 {
276
277 t.QuadPart = FileBasic.LastWriteTime.QuadPart;
278 errCode = SetLastWriteTime(FileHandleDest, t);
279 if (!NT_SUCCESS(errCode))
280 {
281 BaseSetLastNTError(errCode);
282 }
283 else
284 {
285 RC = TRUE;
286 }
287 }
288 NtClose(FileHandleDest);
289 if (! RC && ! KeepDestOnError)
290 {
293 DeleteFileW(lpNewFileName);
295 }
296 }
297 else
298 {
299 WARN("Error %lu during opening of dest file\n", GetLastError());
300 }
301 }
302 }
303 NtClose(FileHandleSource);
304 }
305 else
306 {
307 WARN("Error %lu during opening of source file\n", GetLastError());
308 }
309
310 return RC;
311}
312
313/*
314 * @implemented
315 */
316BOOL
317WINAPI
318CopyFileExW(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)
324{
325 BOOL Ret;
326 HANDLE ExistingHandle, NewHandle;
327
328 ExistingHandle = INVALID_HANDLE_VALUE;
329 NewHandle = INVALID_HANDLE_VALUE;
330
332 {
333 Ret = BasepCopyFileExW(lpExistingFileName,
334 lpNewFileName,
335 lpProgressRoutine,
336 lpData,
337 pbCancel,
338 dwCopyFlags,
339 0,
340 &ExistingHandle,
341 &NewHandle);
342 }
344 {
345 if (ExistingHandle != INVALID_HANDLE_VALUE)
346 {
347 CloseHandle(ExistingHandle);
348 }
349
350 if (NewHandle != INVALID_HANDLE_VALUE)
351 {
352 CloseHandle(NewHandle);
353 }
354 }
355 _SEH2_END;
356
357 return Ret;
358}
359
360
361/*
362 * @implemented
363 */
364BOOL
365WINAPI
366CopyFileExA(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)
372{
373 BOOL Result = FALSE;
374 UNICODE_STRING lpNewFileNameW;
375 PUNICODE_STRING lpExistingFileNameW;
376
377 lpExistingFileNameW = Basep8BitStringToStaticUnicodeString(lpExistingFileName);
378 if (!lpExistingFileNameW)
379 {
380 return FALSE;
381 }
382
383 if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW, lpNewFileName))
384 {
385 Result = CopyFileExW(lpExistingFileNameW->Buffer,
386 lpNewFileNameW.Buffer,
387 lpProgressRoutine,
388 lpData,
389 pbCancel,
390 dwCopyFlags);
391
392 RtlFreeUnicodeString(&lpNewFileNameW);
393 }
394
395 return Result;
396}
397
398
399/*
400 * @implemented
401 */
402BOOL
403WINAPI
404CopyFileA(IN LPCSTR lpExistingFileName,
405 IN LPCSTR lpNewFileName,
406 IN BOOL bFailIfExists)
407{
408 BOOL Result = FALSE;
409 UNICODE_STRING lpNewFileNameW;
410 PUNICODE_STRING lpExistingFileNameW;
411
412 lpExistingFileNameW = Basep8BitStringToStaticUnicodeString(lpExistingFileName);
413 if (!lpExistingFileNameW)
414 {
415 return FALSE;
416 }
417
418 if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW, lpNewFileName))
419 {
420 Result = CopyFileExW(lpExistingFileNameW->Buffer,
421 lpNewFileNameW.Buffer,
422 NULL,
423 NULL,
424 NULL,
425 (bFailIfExists ? COPY_FILE_FAIL_IF_EXISTS : 0));
426
427 RtlFreeUnicodeString(&lpNewFileNameW);
428 }
429
430 return Result;
431}
432
433
434/*
435 * @implemented
436 */
437BOOL
438WINAPI
439CopyFileW(IN LPCWSTR lpExistingFileName,
440 IN LPCWSTR lpNewFileName,
441 IN BOOL bFailIfExists)
442{
443 return CopyFileExW(lpExistingFileName,
444 lpNewFileName,
445 NULL,
446 NULL,
447 NULL,
448 (bFailIfExists ? COPY_FILE_FAIL_IF_EXISTS : 0));
449}
450
451
452/*
453 * @implemented
454 */
455BOOL
456WINAPI
457PrivCopyFileExW(IN LPCWSTR lpExistingFileName,
458 IN LPCWSTR lpNewFileName,
459 IN LPPROGRESS_ROUTINE lpProgressRoutine,
460 IN LPVOID lpData,
461 IN LPBOOL pbCancel,
462 IN DWORD dwCopyFlags)
463{
464 BOOL Ret;
465 HANDLE ExistingHandle, NewHandle;
466
467 ExistingHandle = INVALID_HANDLE_VALUE;
468 NewHandle = INVALID_HANDLE_VALUE;
469
470 /* Check for incompatible flags */
471 if (dwCopyFlags & COPY_FILE_FAIL_IF_EXISTS && dwCopyFlags & BASEP_COPY_REPLACE)
472 {
474 return FALSE;
475 }
476
478 {
479 Ret = BasepCopyFileExW(lpExistingFileName,
480 lpNewFileName,
481 lpProgressRoutine,
482 lpData,
483 pbCancel,
484 dwCopyFlags & BASEP_COPY_PUBLIC_MASK,
485 dwCopyFlags & BASEP_COPY_BASEP_MASK,
486 &ExistingHandle,
487 &NewHandle);
488 }
490 {
491 if (ExistingHandle != INVALID_HANDLE_VALUE)
492 {
493 CloseHandle(ExistingHandle);
494 }
495
496 if (NewHandle != INVALID_HANDLE_VALUE)
497 {
498 CloseHandle(NewHandle);
499 }
500 }
501 _SEH2_END;
502
503 return Ret;
504}
505
506/* EOF */
LONG NTSTATUS
Definition: precomp.h:26
#define DEBUG_CHANNEL(args)
Definition: rdesktop.h:159
#define WARN(fmt,...)
Definition: precomp.h:61
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:175
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define CloseHandle
Definition: compat.h:739
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define OPEN_EXISTING
Definition: compat.h:775
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
BOOL WINAPI CopyFileExA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, IN LPVOID lpData OPTIONAL, IN LPBOOL pbCancel OPTIONAL, IN DWORD dwCopyFlags)
Definition: copy.c:366
static NTSTATUS CopyLoop(HANDLE FileHandleSource, HANDLE FileHandleDest, LARGE_INTEGER SourceFileSize, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, BOOL *pbCancel, BOOL *KeepDest)
Definition: copy.c:26
static NTSTATUS SetLastWriteTime(HANDLE FileHandle, LARGE_INTEGER LastWriteTime)
Definition: copy.c:166
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
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
BOOL WINAPI CopyFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, IN LPVOID lpData OPTIONAL, IN LPBOOL pbCancel OPTIONAL, IN DWORD dwCopyFlags)
Definition: copy.c:318
BOOL WINAPI PrivCopyFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine, IN LPVOID lpData, IN LPBOOL pbCancel, IN DWORD dwCopyFlags)
Definition: copy.c:457
BOOL WINAPI CopyFileA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:404
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:794
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
PUNICODE_STRING WINAPI Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
Definition: utils.c:188
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
@ FileBasicInformation
Definition: from_kernel.h:65
GLdouble GLdouble t
Definition: gl.h:2047
#define BASEP_COPY_PUBLIC_MASK
Definition: kernel32.h:129
#define BASEP_COPY_BASEP_MASK
Definition: kernel32.h:130
#define BASEP_COPY_REPLACE
Definition: kernel32.h:127
#define kernel32file
Definition: kernel32.h:6
#define CREATE_ALWAYS
Definition: disk.h:72
#define FILE_FLAG_NO_BUFFERING
Definition: disk.h:45
#define CREATE_NEW
Definition: disk.h:69
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
_In_ UINT _In_ UINT _In_ PNDIS_PACKET _In_ UINT _Out_ PUINT BytesCopied
Definition: ndis.h:3171
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define PAGE_READWRITE
Definition: nt_native.h:1304
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 NtCurrentProcess()
Definition: nt_native.h:1657
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 NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define MEM_RESERVE
Definition: nt_native.h:1314
#define MEM_RELEASE
Definition: nt_native.h:1316
#define GENERIC_WRITE
Definition: nt_native.h:90
#define MEM_COMMIT
Definition: nt_native.h:1313
NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
Definition: virtual.c:5230
NTSTATUS NTAPI NtAllocateVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID *UBaseAddress, IN ULONG_PTR ZeroBits, IN OUT PSIZE_T URegionSize, IN ULONG AllocationType, IN ULONG Protect)
Definition: virtual.c:4492
#define _SEH2_FINALLY
Definition: pseh2_64.h:114
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:167
#define FileStandardInformation
Definition: propsheet.cpp:61
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
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 TRACE(s)
Definition: solgame.cpp:4
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
LARGE_INTEGER LastWriteTime
Definition: nt_native.h:941
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
#define STATUS_REQUEST_ABORTED
Definition: udferr_usr.h:183
LONGLONG QuadPart
Definition: typedefs.h:114
static const char * SystemError(DWORD err)
Definition: vfdcmd.c:3368
#define CALLBACK_CHUNK_FINISHED
Definition: winbase.h:151
#define COPY_FILE_FAIL_IF_EXISTS
Definition: winbase.h:231
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define PROGRESS_QUIET
Definition: winbase.h:150
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:1464
#define PROGRESS_CANCEL
Definition: winbase.h:148
#define CALLBACK_STREAM_SWITCH
Definition: winbase.h:152
#define PROGRESS_CONTINUE
Definition: winbase.h:147
#define PROGRESS_STOP
Definition: winbase.h:149
BOOL * LPBOOL
Definition: windef.h:162
#define WINAPI
Definition: msvc.h:6
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
const char * LPCSTR
Definition: xmlstorage.h:183
unsigned char UCHAR
Definition: xmlstorage.h:181
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185