Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmove.c
Go to the documentation of this file.
00001 /* $Id: move.c 54326 2011-11-07 00:18:13Z ion $ 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS system libraries 00005 * FILE: lib/kernel32/file/file.c 00006 * PURPOSE: Directory functions 00007 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl) 00008 * Gerhard W. Gruber (sparhawk_at_gmx.at) 00009 * Dmitry Philippov (shedon@mail.ru) 00010 * UPDATE HISTORY: 00011 * Created 01/11/98 00012 * DP (29/07/2006) 00013 * Fix some bugs in the add_boot_rename_entry function 00014 */ 00015 00016 /* INCLUDES *****************************************************************/ 00017 00018 #include <k32.h> 00019 #include <malloc.h> 00020 #define NDEBUG 00021 #include <debug.h> 00022 DEBUG_CHANNEL(kernel32file); 00023 00024 /* GLOBALS *****************************************************************/ 00025 00026 /* FUNCTIONS ****************************************************************/ 00027 static BOOL 00028 RemoveReadOnlyAttributeW(IN LPCWSTR lpFileName) 00029 { 00030 DWORD Attributes; 00031 Attributes = GetFileAttributesW(lpFileName); 00032 if (Attributes != INVALID_FILE_ATTRIBUTES) 00033 { 00034 return SetFileAttributesW(lpFileName,Attributes - 00035 (Attributes & ~FILE_ATTRIBUTE_READONLY)); 00036 } 00037 00038 return FALSE; 00039 } 00040 00041 00042 /*********************************************************************** 00043 * add_boot_rename_entry 00044 * 00045 * Adds an entry to the registry that is loaded when windows boots and 00046 * checks if there are some files to be removed or renamed/moved. 00047 * <fn1> has to be valid and <fn2> may be NULL. If both pointers are 00048 * non-NULL then the file is moved, otherwise it is deleted. The 00049 * entry of the registrykey is always appended with two zero 00050 * terminated strings. If <fn2> is NULL then the second entry is 00051 * simply a single 0-byte. Otherwise the second filename goes 00052 * there. The entries are prepended with \??\ before the path and the 00053 * second filename gets also a '!' as the first character if 00054 * MOVEFILE_REPLACE_EXISTING is set. After the final string another 00055 * 0-byte follows to indicate the end of the strings. 00056 * i.e.: 00057 * \??\D:\test\file1[0] 00058 * !\??\D:\test\file1_renamed[0] 00059 * \??\D:\Test|delete[0] 00060 * [0] <- file is to be deleted, second string empty 00061 * \??\D:\test\file2[0] 00062 * !\??\D:\test\file2_renamed[0] 00063 * [0] <- indicates end of strings 00064 * 00065 * or: 00066 * \??\D:\test\file1[0] 00067 * !\??\D:\test\file1_renamed[0] 00068 * \??\D:\Test|delete[0] 00069 * [0] <- file is to be deleted, second string empty 00070 * [0] <- indicates end of strings 00071 * 00072 */ 00073 static BOOL add_boot_rename_entry( LPCWSTR source, LPCWSTR dest, DWORD flags ) 00074 { 00075 static const WCHAR ValueName[] = {'P','e','n','d','i','n','g', 00076 'F','i','l','e','R','e','n','a','m','e', 00077 'O','p','e','r','a','t','i','o','n','s',0}; 00078 00079 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager"); 00080 00081 static const int info_size = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data ); 00082 00083 OBJECT_ATTRIBUTES ObjectAttributes; 00084 UNICODE_STRING nameW, source_name, dest_name; 00085 KEY_VALUE_PARTIAL_INFORMATION *info; 00086 BOOL rc = FALSE; 00087 HANDLE Reboot = NULL; 00088 DWORD len1, len2; 00089 DWORD DestLen = 0; 00090 DWORD DataSize = 0; 00091 BYTE *Buffer = NULL; 00092 WCHAR *p; 00093 NTSTATUS Status; 00094 00095 TRACE("add_boot_rename_entry( %S, %S, %d ) \n", source, dest, flags); 00096 00097 if(dest) 00098 DestLen = wcslen(dest); 00099 00100 if (!RtlDosPathNameToNtPathName_U( source, &source_name, NULL, NULL )) 00101 { 00102 SetLastError( ERROR_PATH_NOT_FOUND ); 00103 return FALSE; 00104 } 00105 dest_name.Buffer = NULL; 00106 if (DestLen && !RtlDosPathNameToNtPathName_U( dest, &dest_name, NULL, NULL )) 00107 { 00108 RtlFreeHeap( RtlGetProcessHeap(), 0, source_name.Buffer ); 00109 SetLastError( ERROR_PATH_NOT_FOUND ); 00110 return FALSE; 00111 } 00112 00113 InitializeObjectAttributes(&ObjectAttributes, 00114 &KeyName, 00115 OBJ_OPENIF | OBJ_CASE_INSENSITIVE, 00116 NULL, 00117 NULL); 00118 00119 Status = NtCreateKey(&Reboot, 00120 KEY_QUERY_VALUE | KEY_SET_VALUE, 00121 &ObjectAttributes, 00122 0, 00123 NULL, 00124 REG_OPTION_NON_VOLATILE, 00125 NULL); 00126 00127 if (Status == STATUS_ACCESS_DENIED) 00128 { 00129 Status = NtCreateKey( 00130 &Reboot, 00131 KEY_QUERY_VALUE | KEY_SET_VALUE, 00132 &ObjectAttributes, 00133 0, 00134 NULL, 00135 REG_OPTION_BACKUP_RESTORE, 00136 NULL); 00137 } 00138 00139 if (!NT_SUCCESS(Status)) 00140 { 00141 WARN("NtCreateKey() failed (Status 0x%lx)\n", Status); 00142 if (source_name.Buffer) 00143 RtlFreeHeap(RtlGetProcessHeap(), 0, source_name.Buffer); 00144 if (dest_name.Buffer) 00145 RtlFreeHeap(RtlGetProcessHeap(), 0, dest_name.Buffer); 00146 return FALSE; 00147 } 00148 00149 len1 = source_name.Length + sizeof(WCHAR); 00150 if (DestLen) 00151 { 00152 len2 = dest_name.Length + sizeof(WCHAR); 00153 if (flags & MOVEFILE_REPLACE_EXISTING) 00154 len2 += sizeof(WCHAR); /* Plus 1 because of the leading '!' */ 00155 } 00156 else 00157 { 00158 len2 = sizeof(WCHAR); /* minimum is the 0 characters for the empty second string */ 00159 } 00160 00161 RtlInitUnicodeString( &nameW, ValueName ); 00162 00163 /* First we check if the key exists and if so how many bytes it already contains. */ 00164 Status = NtQueryValueKey( 00165 Reboot, 00166 &nameW, 00167 KeyValuePartialInformation, 00168 NULL, 00169 0, 00170 &DataSize ); 00171 if ((Status == STATUS_BUFFER_OVERFLOW) || 00172 (Status == STATUS_BUFFER_TOO_SMALL)) 00173 { 00174 if (!(Buffer = HeapAlloc(GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR)))) 00175 goto Quit; 00176 Status = NtQueryValueKey(Reboot, &nameW, KeyValuePartialInformation, 00177 Buffer, DataSize, &DataSize); 00178 if(!NT_SUCCESS(Status)) 00179 goto Quit; 00180 info = (KEY_VALUE_PARTIAL_INFORMATION *)Buffer; 00181 if (info->Type != REG_MULTI_SZ) goto Quit; 00182 if (DataSize > sizeof(info)) DataSize -= sizeof(WCHAR); /* remove terminating null (will be added back later) */ 00183 } 00184 else 00185 { 00186 DataSize = info_size; 00187 if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) ))) 00188 goto Quit; 00189 } 00190 00191 memcpy( Buffer + DataSize, source_name.Buffer, len1 ); 00192 DataSize += len1; 00193 p = (WCHAR *)(Buffer + DataSize); 00194 if (DestLen) 00195 { 00196 if (flags & MOVEFILE_REPLACE_EXISTING) 00197 *p++ = '!'; 00198 memcpy( p, dest_name.Buffer, len2 ); 00199 DataSize += len2; 00200 } 00201 else 00202 { 00203 *p = 0; 00204 DataSize += sizeof(WCHAR); 00205 } 00206 00207 /* add final null */ 00208 p = (WCHAR *)(Buffer + DataSize); 00209 *p = 0; 00210 DataSize += sizeof(WCHAR); 00211 00212 rc = NT_SUCCESS(NtSetValueKey(Reboot, &nameW, 0, REG_MULTI_SZ, Buffer + info_size, DataSize - info_size)); 00213 00214 Quit: 00215 RtlFreeHeap(RtlGetProcessHeap(), 0, source_name.Buffer); 00216 if (dest_name.Buffer) 00217 RtlFreeHeap(RtlGetProcessHeap(), 0, dest_name.Buffer); 00218 NtClose(Reboot); 00219 if(Buffer) 00220 HeapFree(GetProcessHeap(), 0, Buffer); 00221 return(rc); 00222 } 00223 00224 00225 /* 00226 * @implemented 00227 */ 00228 BOOL 00229 WINAPI 00230 MoveFileWithProgressW ( 00231 LPCWSTR lpExistingFileName, 00232 LPCWSTR lpNewFileName, 00233 LPPROGRESS_ROUTINE lpProgressRoutine, 00234 LPVOID lpData, 00235 DWORD dwFlags 00236 ) 00237 { 00238 HANDLE hFile = NULL, hNewFile = NULL; 00239 IO_STATUS_BLOCK IoStatusBlock; 00240 OBJECT_ATTRIBUTES ObjectAttributes; 00241 PFILE_RENAME_INFORMATION FileRename; 00242 NTSTATUS errCode; 00243 BOOL Result; 00244 UNICODE_STRING DstPathU; 00245 BOOL folder = FALSE; 00246 00247 TRACE("MoveFileWithProgressW()\n"); 00248 00249 if (dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT) 00250 return add_boot_rename_entry( lpExistingFileName, lpNewFileName, dwFlags ); 00251 00252 // if (dwFlags & MOVEFILE_WRITE_THROUGH) 00253 // FIXME("MOVEFILE_WRITE_THROUGH unimplemented\n"); 00254 00255 if (!lpNewFileName) 00256 return DeleteFileW(lpExistingFileName); 00257 00258 /* validate & translate the filename */ 00259 if (!RtlDosPathNameToNtPathName_U (lpNewFileName, 00260 &DstPathU, 00261 NULL, 00262 NULL)) 00263 { 00264 WARN("Invalid destination path\n"); 00265 SetLastError(ERROR_PATH_NOT_FOUND); 00266 return FALSE; 00267 } 00268 00269 InitializeObjectAttributes(&ObjectAttributes, 00270 &DstPathU, 00271 OBJ_CASE_INSENSITIVE, 00272 NULL, 00273 NULL); 00274 00275 errCode = NtOpenFile( &hNewFile, 00276 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 00277 &ObjectAttributes, 00278 &IoStatusBlock, 00279 0, 00280 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | 00281 ((dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0) ); 00282 00283 if (NT_SUCCESS(errCode)) /* Destination exists */ 00284 { 00285 NtClose(hNewFile); 00286 00287 if (!(dwFlags & MOVEFILE_REPLACE_EXISTING)) 00288 { 00289 SetLastError(ERROR_ALREADY_EXISTS); 00290 return FALSE; 00291 } 00292 else if (GetFileAttributesW(lpNewFileName) & FILE_ATTRIBUTE_DIRECTORY) 00293 { 00294 SetLastError(ERROR_ACCESS_DENIED); 00295 return FALSE; 00296 } 00297 } 00298 00299 hFile = CreateFileW (lpExistingFileName, 00300 GENERIC_ALL, 00301 FILE_SHARE_WRITE|FILE_SHARE_READ, 00302 NULL, 00303 OPEN_EXISTING, 00304 FILE_FLAG_BACKUP_SEMANTICS | 00305 ((dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_FLAG_WRITE_THROUGH : 0), 00306 NULL); 00307 00308 if (hFile == INVALID_HANDLE_VALUE) 00309 { 00310 return FALSE; 00311 } 00312 00313 FileRename = RtlAllocateHeap( 00314 RtlGetProcessHeap(), 00315 HEAP_ZERO_MEMORY, 00316 sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length); 00317 if( !FileRename ) { 00318 CloseHandle(hFile); 00319 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00320 return FALSE; 00321 } 00322 if( dwFlags & MOVEFILE_REPLACE_EXISTING ) { 00323 FileRename->ReplaceIfExists = TRUE; 00324 } 00325 else { 00326 FileRename->ReplaceIfExists = FALSE; 00327 } 00328 00329 00330 memcpy(FileRename->FileName, DstPathU.Buffer, DstPathU.Length); 00331 RtlFreeHeap (RtlGetProcessHeap (), 00332 0, 00333 DstPathU.Buffer); 00334 00335 FileRename->FileNameLength = DstPathU.Length; 00336 errCode = NtSetInformationFile (hFile, 00337 &IoStatusBlock, 00338 FileRename, 00339 sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length, 00340 FileRenameInformation); 00341 CloseHandle(hFile); 00342 RtlFreeHeap(RtlGetProcessHeap(), 0, FileRename); 00343 00344 if (GetFileAttributesW(lpExistingFileName) & FILE_ATTRIBUTE_DIRECTORY) 00345 { 00346 folder = TRUE; 00347 } 00348 00349 00350 /* 00351 * FIXME: 00352 * Fail now move the folder 00353 * Before we fail at CreateFileW 00354 */ 00355 00356 00357 if (NT_SUCCESS(errCode)) 00358 { 00359 Result = TRUE; 00360 } 00361 else 00362 { 00363 if (folder==FALSE) 00364 { 00365 Result = CopyFileExW (lpExistingFileName, 00366 lpNewFileName, 00367 lpProgressRoutine, 00368 lpData, 00369 NULL, 00370 (dwFlags & MOVEFILE_REPLACE_EXISTING) ? 0 : COPY_FILE_FAIL_IF_EXISTS); 00371 if (Result) 00372 { 00373 /* Cleanup the source file */ 00374 Result = DeleteFileW (lpExistingFileName); 00375 } 00376 } 00377 else 00378 { 00379 /* move folder code start */ 00380 WIN32_FIND_DATAW findBuffer; 00381 LPWSTR lpExistingFileName2 = NULL; 00382 LPWSTR lpNewFileName2 = NULL; 00383 LPWSTR lpDeleteFile = NULL; 00384 INT size; 00385 INT size2; 00386 BOOL loop = TRUE; 00387 BOOL Result = FALSE; 00388 INT max_size = MAX_PATH; 00389 00390 00391 /* Build the string */ 00392 size = wcslen(lpExistingFileName); 00393 if (size+6> max_size) 00394 max_size = size + 6; 00395 00396 lpDeleteFile = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR)); 00397 if (lpDeleteFile == NULL) 00398 return FALSE; 00399 00400 lpNewFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR)); 00401 if (lpNewFileName2 == NULL) 00402 { 00403 HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); 00404 return FALSE; 00405 } 00406 00407 lpExistingFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR)); 00408 if (lpExistingFileName2 == NULL) 00409 { 00410 HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); 00411 HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); 00412 return FALSE; 00413 } 00414 00415 wcscpy( (WCHAR *)lpExistingFileName2,lpExistingFileName); 00416 wcscpy( (WCHAR *)&lpExistingFileName2[size],L"\\*.*\0"); 00417 00418 /* Get the file name */ 00419 memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW)); 00420 hFile = FindFirstFileW(lpExistingFileName2, &findBuffer); 00421 if (hFile == INVALID_HANDLE_VALUE) 00422 loop=FALSE; 00423 00424 if (findBuffer.cFileName[0] == L'\0') 00425 loop=FALSE; 00426 00427 00428 /* FIXME 00429 * remove readonly flag from source folder and do not set the readonly flag to dest folder 00430 */ 00431 RemoveReadOnlyAttributeW(lpExistingFileName); 00432 RemoveReadOnlyAttributeW(lpNewFileName); 00433 //CreateDirectoryExW(lpExistingFileName,lpNewFileName,NULL); 00434 CreateDirectoryW(lpNewFileName, NULL); 00435 00436 /* search the files/folders and move them */ 00437 while (loop==TRUE) 00438 { 00439 Result = TRUE; 00440 00441 if ((!wcscmp(findBuffer.cFileName,L"..")) || (!wcscmp(findBuffer.cFileName,L"."))) 00442 { 00443 loop = FindNextFileW(hFile, &findBuffer); 00444 00445 if (!loop) 00446 { 00447 size = wcslen(lpExistingFileName2)-4; 00448 FindClose(hFile); 00449 hFile = INVALID_HANDLE_VALUE; 00450 00451 wcscpy( &lpExistingFileName2[size],L"\0"); 00452 00453 if (wcsncmp(lpExistingFileName,lpExistingFileName2,size)) 00454 { 00455 DWORD Attributes; 00456 00457 /* delete folder */ 00458 TRACE("MoveFileWithProgressW : Delete folder : %S\n",lpDeleteFile); 00459 00460 /* remove system folder flag other wise we can not delete the folder */ 00461 Attributes = GetFileAttributesW(lpExistingFileName2); 00462 if (Attributes != INVALID_FILE_ATTRIBUTES) 00463 { 00464 SetFileAttributesW(lpExistingFileName2,(Attributes & ~FILE_ATTRIBUTE_SYSTEM)); 00465 } 00466 00467 RemoveReadOnlyAttributeW(lpExistingFileName2); 00468 00469 Result = RemoveDirectoryW(lpExistingFileName2); 00470 if (Result == FALSE) 00471 break; 00472 00473 loop=TRUE; 00474 size = wcslen(lpExistingFileName); 00475 00476 if (size+6>max_size) 00477 { 00478 if (lpNewFileName2 != NULL) 00479 HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); 00480 00481 if (lpExistingFileName2 != NULL) 00482 HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2); 00483 00484 if (lpDeleteFile != NULL) 00485 HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); 00486 00487 return FALSE; 00488 } 00489 00490 wcscpy( lpExistingFileName2,lpExistingFileName); 00491 wcscpy( &lpExistingFileName2[size],L"\\*.*\0"); 00492 00493 /* Get the file name */ 00494 memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW)); 00495 hFile = FindFirstFileW(lpExistingFileName2, &findBuffer); 00496 } 00497 } 00498 continue; 00499 } 00500 00501 if (findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 00502 { 00503 00504 /* Build the new src string */ 00505 size = wcslen(findBuffer.cFileName); 00506 size2= wcslen(lpExistingFileName2); 00507 00508 if (size2+size+6>max_size) 00509 { 00510 FindClose(hFile); 00511 00512 if (lpNewFileName2 != NULL) 00513 HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); 00514 00515 if (lpExistingFileName2 != NULL) 00516 HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2); 00517 00518 if (lpDeleteFile != NULL) 00519 HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); 00520 00521 return FALSE; 00522 } 00523 00524 wcscpy( &lpExistingFileName2[size2-3],findBuffer.cFileName); 00525 wcscpy( &lpExistingFileName2[size2+size-3],L"\0"); 00526 00527 00528 /* Continue */ 00529 wcscpy( lpDeleteFile,lpExistingFileName2); 00530 wcscpy( &lpExistingFileName2[size2+size-3],L"\\*.*\0"); 00531 00532 00533 /* Build the new dst string */ 00534 size = wcslen(lpExistingFileName2) + wcslen(lpNewFileName); 00535 size2 = wcslen(lpExistingFileName); 00536 00537 if (size>max_size) 00538 { 00539 FindClose(hFile); 00540 00541 if (lpNewFileName2 != NULL) 00542 HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); 00543 00544 if (lpExistingFileName2 != NULL) 00545 HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2); 00546 00547 if (lpDeleteFile != NULL) 00548 HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); 00549 00550 return FALSE; 00551 } 00552 00553 wcscpy( lpNewFileName2,lpNewFileName); 00554 size = wcslen(lpNewFileName); 00555 wcscpy( &lpNewFileName2[size], &lpExistingFileName2[size2]); 00556 size = wcslen(lpNewFileName2); 00557 wcscpy( &lpNewFileName2[size-4],L"\0"); 00558 00559 /* Create Folder */ 00560 00561 /* FIXME 00562 * remove readonly flag from source folder and do not set the readonly flag to dest folder 00563 */ 00564 RemoveReadOnlyAttributeW(lpDeleteFile); 00565 RemoveReadOnlyAttributeW(lpNewFileName2); 00566 00567 CreateDirectoryW(lpNewFileName2,NULL); 00568 //CreateDirectoryExW(lpDeleteFile, lpNewFileName2,NULL); 00569 00570 00571 /* set new search path from src string */ 00572 FindClose(hFile); 00573 memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW)); 00574 hFile = FindFirstFileW(lpExistingFileName2, &findBuffer); 00575 } 00576 else 00577 { 00578 00579 /* Build the new string */ 00580 size = wcslen(findBuffer.cFileName); 00581 size2= wcslen(lpExistingFileName2); 00582 wcscpy( lpDeleteFile,lpExistingFileName2); 00583 wcscpy( &lpDeleteFile[size2-3],findBuffer.cFileName); 00584 00585 /* Build dest string */ 00586 size = wcslen(lpDeleteFile) + wcslen(lpNewFileName); 00587 size2 = wcslen(lpExistingFileName); 00588 00589 if (size>max_size) 00590 { 00591 FindClose(hFile); 00592 00593 if (lpNewFileName2 != NULL) 00594 HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); 00595 00596 if (lpExistingFileName2 != NULL) 00597 HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2); 00598 00599 if (lpDeleteFile != NULL) 00600 HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); 00601 00602 return FALSE; 00603 } 00604 00605 wcscpy( lpNewFileName2,lpNewFileName); 00606 size = wcslen(lpNewFileName); 00607 wcscpy(&lpNewFileName2[size],&lpDeleteFile[size2]); 00608 00609 00610 /* overrite existsen file, if the file got the flag have readonly 00611 * we need reomve that flag 00612 */ 00613 00614 /* copy file */ 00615 00616 TRACE("MoveFileWithProgressW : Copy file : %S to %S\n",lpDeleteFile, lpNewFileName2); 00617 RemoveReadOnlyAttributeW(lpDeleteFile); 00618 RemoveReadOnlyAttributeW(lpNewFileName2); 00619 00620 Result = CopyFileExW (lpDeleteFile, 00621 lpNewFileName2, 00622 lpProgressRoutine, 00623 lpData, 00624 NULL, 00625 0); 00626 00627 if (Result == FALSE) 00628 break; 00629 00630 /* delete file */ 00631 TRACE("MoveFileWithProgressW : remove readonly flag from file : %S\n",lpNewFileName2); 00632 Result = RemoveReadOnlyAttributeW(lpDeleteFile); 00633 if (Result == FALSE) 00634 break; 00635 00636 TRACE("MoveFileWithProgressW : Delete file : %S\n",lpDeleteFile); 00637 Result = DeleteFileW(lpDeleteFile); 00638 if (Result == FALSE) 00639 break; 00640 00641 } 00642 loop = FindNextFileW(hFile, &findBuffer); 00643 } 00644 00645 00646 /* Remove last folder */ 00647 if ((loop == FALSE) && (Result != FALSE)) 00648 { 00649 DWORD Attributes; 00650 00651 Attributes = GetFileAttributesW(lpDeleteFile); 00652 if (Attributes != INVALID_FILE_ATTRIBUTES) 00653 { 00654 SetFileAttributesW(lpDeleteFile,(Attributes & ~FILE_ATTRIBUTE_SYSTEM)); 00655 } 00656 00657 Result = RemoveDirectoryW(lpExistingFileName); 00658 } 00659 00660 /* Cleanup */ 00661 FindClose(hFile); 00662 00663 if (lpNewFileName2 != NULL) 00664 { 00665 HeapFree(GetProcessHeap(),0,(VOID *) lpNewFileName2); 00666 lpNewFileName2 = NULL; 00667 } 00668 00669 if (lpExistingFileName2 != NULL) 00670 { 00671 HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2); 00672 lpExistingFileName2 = NULL; 00673 } 00674 00675 if (lpDeleteFile != NULL) 00676 { 00677 HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile); 00678 lpDeleteFile = NULL; 00679 } 00680 00681 return Result; 00682 00683 // end move folder code 00684 } 00685 } 00686 00687 00688 return Result; 00689 } 00690 00691 00692 /* 00693 * @implemented 00694 */ 00695 BOOL 00696 WINAPI 00697 MoveFileWithProgressA ( 00698 LPCSTR lpExistingFileName, 00699 LPCSTR lpNewFileName, 00700 LPPROGRESS_ROUTINE lpProgressRoutine, 00701 LPVOID lpData, 00702 DWORD dwFlags 00703 ) 00704 { 00705 PWCHAR ExistingFileNameW; 00706 PWCHAR NewFileNameW; 00707 BOOL ret; 00708 00709 if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, FALSE))) 00710 return FALSE; 00711 00712 if (!(NewFileNameW= FilenameA2W(lpNewFileName, TRUE))) 00713 return FALSE; 00714 00715 ret = MoveFileWithProgressW (ExistingFileNameW , 00716 NewFileNameW, 00717 lpProgressRoutine, 00718 lpData, 00719 dwFlags); 00720 00721 RtlFreeHeap (RtlGetProcessHeap (), 0, NewFileNameW); 00722 00723 return ret; 00724 } 00725 00726 00727 /* 00728 * @implemented 00729 */ 00730 BOOL 00731 WINAPI 00732 MoveFileW ( 00733 LPCWSTR lpExistingFileName, 00734 LPCWSTR lpNewFileName 00735 ) 00736 { 00737 return MoveFileExW (lpExistingFileName, 00738 lpNewFileName, 00739 MOVEFILE_COPY_ALLOWED); 00740 } 00741 00742 00743 /* 00744 * @implemented 00745 */ 00746 BOOL 00747 WINAPI 00748 MoveFileExW ( 00749 LPCWSTR lpExistingFileName, 00750 LPCWSTR lpNewFileName, 00751 DWORD dwFlags 00752 ) 00753 { 00754 return MoveFileWithProgressW (lpExistingFileName, 00755 lpNewFileName, 00756 NULL, 00757 NULL, 00758 dwFlags); 00759 } 00760 00761 00762 /* 00763 * @implemented 00764 */ 00765 BOOL 00766 WINAPI 00767 MoveFileA ( 00768 LPCSTR lpExistingFileName, 00769 LPCSTR lpNewFileName 00770 ) 00771 { 00772 return MoveFileExA (lpExistingFileName, 00773 lpNewFileName, 00774 MOVEFILE_COPY_ALLOWED); 00775 } 00776 00777 00778 /* 00779 * @implemented 00780 */ 00781 BOOL 00782 WINAPI 00783 MoveFileExA ( 00784 LPCSTR lpExistingFileName, 00785 LPCSTR lpNewFileName, 00786 DWORD dwFlags 00787 ) 00788 { 00789 return MoveFileWithProgressA (lpExistingFileName, 00790 lpNewFileName, 00791 NULL, 00792 NULL, 00793 dwFlags); 00794 } 00795 00796 /* 00797 * @implemented 00798 */ 00799 BOOL 00800 WINAPI 00801 ReplaceFileA( 00802 LPCSTR lpReplacedFileName, 00803 LPCSTR lpReplacementFileName, 00804 LPCSTR lpBackupFileName, 00805 DWORD dwReplaceFlags, 00806 LPVOID lpExclude, 00807 LPVOID lpReserved 00808 ) 00809 { 00810 WCHAR *replacedW, *replacementW, *backupW = NULL; 00811 BOOL ret; 00812 00813 /* This function only makes sense when the first two parameters are defined */ 00814 if (!lpReplacedFileName || !(replacedW = FilenameA2W(lpReplacedFileName, TRUE))) 00815 { 00816 SetLastError(ERROR_INVALID_PARAMETER); 00817 return FALSE; 00818 } 00819 00820 if (!lpReplacementFileName || !(replacementW = FilenameA2W(lpReplacementFileName, TRUE))) 00821 { 00822 HeapFree(GetProcessHeap(), 0, replacedW); 00823 SetLastError(ERROR_INVALID_PARAMETER); 00824 return FALSE; 00825 } 00826 00827 /* The backup parameter, however, is optional */ 00828 if (lpBackupFileName) 00829 { 00830 if (!(backupW = FilenameA2W(lpBackupFileName, TRUE))) 00831 { 00832 HeapFree(GetProcessHeap(), 0, replacedW); 00833 HeapFree(GetProcessHeap(), 0, replacementW); 00834 SetLastError(ERROR_INVALID_PARAMETER); 00835 return FALSE; 00836 } 00837 } 00838 00839 ret = ReplaceFileW(replacedW, replacementW, backupW, dwReplaceFlags, lpExclude, lpReserved); 00840 HeapFree(GetProcessHeap(), 0, replacedW); 00841 HeapFree(GetProcessHeap(), 0, replacementW); 00842 HeapFree(GetProcessHeap(), 0, backupW); 00843 00844 return ret; 00845 } 00846 00847 /* 00848 * @unimplemented 00849 */ 00850 BOOL 00851 WINAPI 00852 ReplaceFileW( 00853 LPCWSTR lpReplacedFileName, 00854 LPCWSTR lpReplacementFileName, 00855 LPCWSTR lpBackupFileName, 00856 DWORD dwReplaceFlags, 00857 LPVOID lpExclude, 00858 LPVOID lpReserved 00859 ) 00860 { 00861 HANDLE hReplaced = NULL, hReplacement = NULL; 00862 UNICODE_STRING NtReplacedName = { 0, 0, NULL }; 00863 UNICODE_STRING NtReplacementName = { 0, 0, NULL }; 00864 DWORD Error = ERROR_SUCCESS; 00865 NTSTATUS Status; 00866 BOOL Ret = FALSE; 00867 IO_STATUS_BLOCK IoStatusBlock; 00868 OBJECT_ATTRIBUTES ObjectAttributes; 00869 PVOID Buffer = NULL ; 00870 00871 if (dwReplaceFlags) 00872 FIXME("Ignoring flags %x\n", dwReplaceFlags); 00873 00874 /* First two arguments are mandatory */ 00875 if (!lpReplacedFileName || !lpReplacementFileName) 00876 { 00877 SetLastError(ERROR_INVALID_PARAMETER); 00878 return FALSE; 00879 } 00880 00881 /* Back it up */ 00882 if(lpBackupFileName) 00883 { 00884 if(!CopyFileW(lpReplacedFileName, lpBackupFileName, FALSE)) 00885 { 00886 Error = GetLastError(); 00887 goto Cleanup ; 00888 } 00889 } 00890 00891 /* Open the "replaced" file for reading and writing */ 00892 if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &NtReplacedName, NULL, NULL))) 00893 { 00894 Error = ERROR_PATH_NOT_FOUND; 00895 goto Cleanup; 00896 } 00897 00898 InitializeObjectAttributes(&ObjectAttributes, 00899 &NtReplacedName, 00900 OBJ_CASE_INSENSITIVE, 00901 NULL, 00902 NULL); 00903 00904 Status = NtOpenFile(&hReplaced, 00905 GENERIC_READ | GENERIC_WRITE | DELETE | SYNCHRONIZE | WRITE_DAC, 00906 &ObjectAttributes, 00907 &IoStatusBlock, 00908 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 00909 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); 00910 00911 if (!NT_SUCCESS(Status)) 00912 { 00913 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 00914 Error = ERROR_FILE_NOT_FOUND; 00915 else 00916 Error = ERROR_UNABLE_TO_REMOVE_REPLACED; 00917 goto Cleanup; 00918 } 00919 00920 /* Blank it */ 00921 SetEndOfFile(hReplaced) ; 00922 00923 /* 00924 * Open the replacement file for reading, writing, and deleting 00925 * (deleting is needed when finished) 00926 */ 00927 if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName, &NtReplacementName, NULL, NULL))) 00928 { 00929 Error = ERROR_PATH_NOT_FOUND; 00930 goto Cleanup; 00931 } 00932 00933 InitializeObjectAttributes(&ObjectAttributes, 00934 &NtReplacementName, 00935 OBJ_CASE_INSENSITIVE, 00936 NULL, 00937 NULL); 00938 00939 Status = NtOpenFile(&hReplacement, 00940 GENERIC_READ | DELETE | SYNCHRONIZE, 00941 &ObjectAttributes, 00942 &IoStatusBlock, 00943 0, 00944 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE); 00945 00946 if (!NT_SUCCESS(Status)) 00947 { 00948 Error = RtlNtStatusToDosError(Status); 00949 goto Cleanup; 00950 } 00951 00952 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 0x10000) ; 00953 if (!Buffer) 00954 { 00955 Error = ERROR_NOT_ENOUGH_MEMORY; 00956 goto Cleanup ; 00957 } 00958 while (Status != STATUS_END_OF_FILE) 00959 { 00960 Status = NtReadFile(hReplacement, NULL, NULL, NULL, &IoStatusBlock, Buffer, 0x10000, NULL, NULL) ; 00961 if (NT_SUCCESS(Status)) 00962 { 00963 Status = NtWriteFile(hReplaced, NULL, NULL, NULL, &IoStatusBlock, Buffer, 00964 IoStatusBlock.Information, NULL, NULL) ; 00965 if (!NT_SUCCESS(Status)) 00966 { 00967 Error = RtlNtStatusToDosError(Status); 00968 goto Cleanup; 00969 } 00970 } 00971 else if (Status != STATUS_END_OF_FILE) 00972 { 00973 Error = RtlNtStatusToDosError(Status); 00974 goto Cleanup; 00975 } 00976 } 00977 00978 Ret = TRUE; 00979 00980 /* Perform resource cleanup */ 00981 Cleanup: 00982 if (hReplaced) NtClose(hReplaced); 00983 if (hReplacement) NtClose(hReplacement); 00984 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 00985 00986 if (NtReplacementName.Buffer) 00987 RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName.Buffer); 00988 if (NtReplacedName.Buffer) 00989 RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName.Buffer); 00990 00991 /* If there was an error, set the error code */ 00992 if(!Ret) 00993 { 00994 TRACE("ReplaceFileW failed (error=%d)\n", Error); 00995 SetLastError(Error); 00996 } 00997 return Ret; 00998 } 00999 01000 /* 01001 * @unimplemented 01002 */ 01003 BOOL 01004 WINAPI 01005 PrivMoveFileIdentityW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3) 01006 { 01007 STUB; 01008 return FALSE; 01009 } 01010 01011 /* EOF */ Generated on Sun May 27 2012 04:18:13 for ReactOS by
1.7.6.1
|