Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencopy.c
Go to the documentation of this file.
00001 /* $Id: copy.c 55885 2012-02-27 17:10:44Z sir_richard $ 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS system libraries 00005 * FILE: lib/kernel32/file/copy.c 00006 * PURPOSE: Copying files 00007 * PROGRAMMER: Ariadne (ariadne@xs4all.nl) 00008 * UPDATE HISTORY: 00009 * 01/11/98 Created 00010 * 07/02/99 Moved to seperate file 00011 */ 00012 00013 /* INCLUDES ****************************************************************/ 00014 00015 #include <k32.h> 00016 #define NDEBUG 00017 #include <debug.h> 00018 00019 #if DBG 00020 DEBUG_CHANNEL(kernel32file); 00021 #endif 00022 00023 /* FUNCTIONS ****************************************************************/ 00024 00025 00026 static NTSTATUS 00027 CopyLoop ( 00028 HANDLE FileHandleSource, 00029 HANDLE FileHandleDest, 00030 LARGE_INTEGER SourceFileSize, 00031 LPPROGRESS_ROUTINE lpProgressRoutine, 00032 LPVOID lpData, 00033 BOOL *pbCancel, 00034 BOOL *KeepDest 00035 ) 00036 { 00037 NTSTATUS errCode; 00038 IO_STATUS_BLOCK IoStatusBlock; 00039 UCHAR *lpBuffer = NULL; 00040 SIZE_T RegionSize = 0x10000; 00041 LARGE_INTEGER BytesCopied; 00042 DWORD CallbackReason; 00043 DWORD ProgressResult; 00044 BOOL EndOfFileFound; 00045 00046 *KeepDest = FALSE; 00047 errCode = NtAllocateVirtualMemory(NtCurrentProcess(), 00048 (PVOID *)&lpBuffer, 00049 0, 00050 &RegionSize, 00051 MEM_RESERVE | MEM_COMMIT, 00052 PAGE_READWRITE); 00053 00054 if (NT_SUCCESS(errCode)) 00055 { 00056 BytesCopied.QuadPart = 0; 00057 EndOfFileFound = FALSE; 00058 CallbackReason = CALLBACK_STREAM_SWITCH; 00059 while (! EndOfFileFound && 00060 NT_SUCCESS(errCode) && 00061 (NULL == pbCancel || ! *pbCancel)) 00062 { 00063 if (NULL != lpProgressRoutine) 00064 { 00065 ProgressResult = (*lpProgressRoutine)(SourceFileSize, 00066 BytesCopied, 00067 SourceFileSize, 00068 BytesCopied, 00069 0, 00070 CallbackReason, 00071 FileHandleSource, 00072 FileHandleDest, 00073 lpData); 00074 switch (ProgressResult) 00075 { 00076 case PROGRESS_CANCEL: 00077 TRACE("Progress callback requested cancel\n"); 00078 errCode = STATUS_REQUEST_ABORTED; 00079 break; 00080 case PROGRESS_STOP: 00081 TRACE("Progress callback requested stop\n"); 00082 errCode = STATUS_REQUEST_ABORTED; 00083 *KeepDest = TRUE; 00084 break; 00085 case PROGRESS_QUIET: 00086 lpProgressRoutine = NULL; 00087 break; 00088 case PROGRESS_CONTINUE: 00089 default: 00090 break; 00091 } 00092 CallbackReason = CALLBACK_CHUNK_FINISHED; 00093 } 00094 if (NT_SUCCESS(errCode)) 00095 { 00096 errCode = NtReadFile(FileHandleSource, 00097 NULL, 00098 NULL, 00099 NULL, 00100 (PIO_STATUS_BLOCK)&IoStatusBlock, 00101 lpBuffer, 00102 RegionSize, 00103 NULL, 00104 NULL); 00105 if (NT_SUCCESS(errCode) && (NULL == pbCancel || ! *pbCancel)) 00106 { 00107 errCode = NtWriteFile(FileHandleDest, 00108 NULL, 00109 NULL, 00110 NULL, 00111 (PIO_STATUS_BLOCK)&IoStatusBlock, 00112 lpBuffer, 00113 IoStatusBlock.Information, 00114 NULL, 00115 NULL); 00116 if (NT_SUCCESS(errCode)) 00117 { 00118 BytesCopied.QuadPart += IoStatusBlock.Information; 00119 } 00120 else 00121 { 00122 WARN("Error 0x%08x reading writing to dest\n", errCode); 00123 } 00124 } 00125 else if (!NT_SUCCESS(errCode)) 00126 { 00127 if (STATUS_END_OF_FILE == errCode) 00128 { 00129 EndOfFileFound = TRUE; 00130 errCode = STATUS_SUCCESS; 00131 } 00132 else 00133 { 00134 WARN("Error 0x%08x reading from source\n", errCode); 00135 } 00136 } 00137 } 00138 } 00139 00140 if (! EndOfFileFound && (NULL != pbCancel && *pbCancel)) 00141 { 00142 TRACE("User requested cancel\n"); 00143 errCode = STATUS_REQUEST_ABORTED; 00144 } 00145 00146 NtFreeVirtualMemory(NtCurrentProcess(), 00147 (PVOID *)&lpBuffer, 00148 &RegionSize, 00149 MEM_RELEASE); 00150 } 00151 else 00152 { 00153 TRACE("Error 0x%08x allocating buffer of %d bytes\n", errCode, RegionSize); 00154 } 00155 00156 return errCode; 00157 } 00158 00159 static NTSTATUS 00160 SetLastWriteTime( 00161 HANDLE FileHandle, 00162 LARGE_INTEGER LastWriteTime 00163 ) 00164 { 00165 NTSTATUS errCode = STATUS_SUCCESS; 00166 IO_STATUS_BLOCK IoStatusBlock; 00167 FILE_BASIC_INFORMATION FileBasic; 00168 00169 errCode = NtQueryInformationFile (FileHandle, 00170 &IoStatusBlock, 00171 &FileBasic, 00172 sizeof(FILE_BASIC_INFORMATION), 00173 FileBasicInformation); 00174 if (!NT_SUCCESS(errCode)) 00175 { 00176 WARN("Error 0x%08x obtaining FileBasicInformation\n", errCode); 00177 } 00178 else 00179 { 00180 FileBasic.LastWriteTime.QuadPart = LastWriteTime.QuadPart; 00181 errCode = NtSetInformationFile (FileHandle, 00182 &IoStatusBlock, 00183 &FileBasic, 00184 sizeof(FILE_BASIC_INFORMATION), 00185 FileBasicInformation); 00186 if (!NT_SUCCESS(errCode)) 00187 { 00188 WARN("Error 0x%0x setting LastWriteTime\n", errCode); 00189 } 00190 } 00191 00192 return errCode; 00193 } 00194 00195 00196 /* 00197 * @implemented 00198 */ 00199 BOOL 00200 WINAPI 00201 CopyFileExW ( 00202 LPCWSTR lpExistingFileName, 00203 LPCWSTR lpNewFileName, 00204 LPPROGRESS_ROUTINE lpProgressRoutine, 00205 LPVOID lpData, 00206 BOOL *pbCancel, 00207 DWORD dwCopyFlags 00208 ) 00209 { 00210 NTSTATUS errCode; 00211 HANDLE FileHandleSource, FileHandleDest; 00212 IO_STATUS_BLOCK IoStatusBlock; 00213 FILE_STANDARD_INFORMATION FileStandard; 00214 FILE_BASIC_INFORMATION FileBasic; 00215 BOOL RC = FALSE; 00216 BOOL KeepDestOnError = FALSE; 00217 DWORD SystemError; 00218 00219 FileHandleSource = CreateFileW(lpExistingFileName, 00220 GENERIC_READ, 00221 FILE_SHARE_READ | FILE_SHARE_WRITE, 00222 NULL, 00223 OPEN_EXISTING, 00224 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING, 00225 NULL); 00226 if (INVALID_HANDLE_VALUE != FileHandleSource) 00227 { 00228 errCode = NtQueryInformationFile(FileHandleSource, 00229 &IoStatusBlock, 00230 &FileStandard, 00231 sizeof(FILE_STANDARD_INFORMATION), 00232 FileStandardInformation); 00233 if (!NT_SUCCESS(errCode)) 00234 { 00235 TRACE("Status 0x%08x obtaining FileStandardInformation for source\n", errCode); 00236 BaseSetLastNTError(errCode); 00237 } 00238 else 00239 { 00240 errCode = NtQueryInformationFile(FileHandleSource, 00241 &IoStatusBlock,&FileBasic, 00242 sizeof(FILE_BASIC_INFORMATION), 00243 FileBasicInformation); 00244 if (!NT_SUCCESS(errCode)) 00245 { 00246 TRACE("Status 0x%08x obtaining FileBasicInformation for source\n", errCode); 00247 BaseSetLastNTError(errCode); 00248 } 00249 else 00250 { 00251 FileHandleDest = CreateFileW(lpNewFileName, 00252 GENERIC_WRITE, 00253 FILE_SHARE_WRITE, 00254 NULL, 00255 dwCopyFlags ? CREATE_NEW : CREATE_ALWAYS, 00256 FileBasic.FileAttributes, 00257 NULL); 00258 if (INVALID_HANDLE_VALUE != FileHandleDest) 00259 { 00260 errCode = CopyLoop(FileHandleSource, 00261 FileHandleDest, 00262 FileStandard.EndOfFile, 00263 lpProgressRoutine, 00264 lpData, 00265 pbCancel, 00266 &KeepDestOnError); 00267 if (!NT_SUCCESS(errCode)) 00268 { 00269 BaseSetLastNTError(errCode); 00270 } 00271 else 00272 { 00273 LARGE_INTEGER t; 00274 00275 t.QuadPart = FileBasic.LastWriteTime.QuadPart; 00276 errCode = SetLastWriteTime(FileHandleDest, t); 00277 if (!NT_SUCCESS(errCode)) 00278 { 00279 BaseSetLastNTError(errCode); 00280 } 00281 else 00282 { 00283 RC = TRUE; 00284 } 00285 } 00286 NtClose(FileHandleDest); 00287 if (! RC && ! KeepDestOnError) 00288 { 00289 SystemError = GetLastError(); 00290 SetFileAttributesW(lpNewFileName, FILE_ATTRIBUTE_NORMAL); 00291 DeleteFileW(lpNewFileName); 00292 SetLastError(SystemError); 00293 } 00294 } 00295 else 00296 { 00297 WARN("Error %d during opening of dest file\n", GetLastError()); 00298 } 00299 } 00300 } 00301 NtClose(FileHandleSource); 00302 } 00303 else 00304 { 00305 WARN("Error %d during opening of source file\n", GetLastError()); 00306 } 00307 00308 return RC; 00309 } 00310 00311 00312 /* 00313 * @implemented 00314 */ 00315 BOOL 00316 WINAPI 00317 CopyFileExA(IN LPCSTR lpExistingFileName, 00318 IN LPCSTR lpNewFileName, 00319 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, 00320 IN LPVOID lpData OPTIONAL, 00321 IN LPBOOL pbCancel OPTIONAL, 00322 IN DWORD dwCopyFlags) 00323 { 00324 BOOL Result = FALSE; 00325 UNICODE_STRING lpNewFileNameW; 00326 PUNICODE_STRING lpExistingFileNameW; 00327 00328 lpExistingFileNameW = Basep8BitStringToStaticUnicodeString(lpExistingFileName); 00329 if (!lpExistingFileName) 00330 { 00331 return FALSE; 00332 } 00333 00334 if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW, lpNewFileName)) 00335 { 00336 Result = CopyFileExW(lpExistingFileNameW->Buffer, 00337 lpNewFileNameW.Buffer, 00338 lpProgressRoutine, 00339 lpData, 00340 pbCancel, 00341 dwCopyFlags); 00342 00343 RtlFreeUnicodeString(&lpNewFileNameW); 00344 } 00345 00346 return Result; 00347 } 00348 00349 00350 /* 00351 * @implemented 00352 */ 00353 BOOL 00354 WINAPI 00355 CopyFileA ( 00356 LPCSTR lpExistingFileName, 00357 LPCSTR lpNewFileName, 00358 BOOL bFailIfExists 00359 ) 00360 { 00361 return CopyFileExA (lpExistingFileName, 00362 lpNewFileName, 00363 NULL, 00364 NULL, 00365 NULL, 00366 bFailIfExists); 00367 } 00368 00369 00370 /* 00371 * @implemented 00372 */ 00373 BOOL 00374 WINAPI 00375 CopyFileW ( 00376 LPCWSTR lpExistingFileName, 00377 LPCWSTR lpNewFileName, 00378 BOOL bFailIfExists 00379 ) 00380 { 00381 return CopyFileExW (lpExistingFileName, 00382 lpNewFileName, 00383 NULL, 00384 NULL, 00385 NULL, 00386 bFailIfExists); 00387 } 00388 00389 00390 /* 00391 * @implemented 00392 */ 00393 BOOL 00394 WINAPI 00395 PrivCopyFileExW ( 00396 LPCWSTR lpExistingFileName, 00397 LPCWSTR lpNewFileName, 00398 LPPROGRESS_ROUTINE lpProgressRoutine, 00399 LPVOID lpData, 00400 BOOL *pbCancel, 00401 DWORD dwCopyFlags 00402 ) 00403 { 00404 UNIMPLEMENTED; 00405 return FALSE; 00406 } 00407 00408 /* EOF */ Generated on Wed May 23 2012 04:16:17 for ReactOS by
1.7.6.1
|