/************************************************************************** * ReplaceFileW (KERNEL32.@) * ReplaceFile (KERNEL32.@) */ BOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName,LPCWSTR lpReplacementFileName, LPCWSTR lpBackupFileName, DWORD dwReplaceFlags, LPVOID lpExclude, LPVOID lpReserved) { HANDLE hReplaced, hReplacement; BOOL skipBackup = FALSE; if(dwReplaceFlags) FIXME("Ignoring flags %x\n", dwReplaceFlags); /* First two arguments are mandatory */ if(!lpReplacedFileName || !lpReplacementFileName) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } /* * Lock the "replacement" file, fail if it does not exist */ if((hReplacement = CreateFileW(lpReplacementFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } if(!LockFile( hReplacement, 0, 0, 0, 0 )) { CloseHandle( hReplacement ); SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } /* * Lock the "replaced" file while we're working. */ if((hReplaced = CreateFileW(lpReplacedFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) { /* If "replaced" does not exist then create it for the lock, but skip backup */ if((hReplaced = CreateFileW(lpReplacedFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { UnlockFile( hReplacement, 0, 0, 0, 0 ); CloseHandle( hReplacement ); SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } skipBackup = TRUE; } if(!LockFile( hReplaced, 0, 0, 0, 0 )) { UnlockFile( hReplacement, 0, 0, 0, 0 ); CloseHandle( hReplacement ); CloseHandle( hReplaced ); SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } /* * If the user wants a backup then that needs to be performed first */ if( lpBackupFileName && !skipBackup ) { /* If an existing backup exists then copy over it */ if(!CopyFileW( lpReplacedFileName, lpBackupFileName, FALSE )) { SetLastError( ERROR_INVALID_PARAMETER ); goto replace_fail; } } /* * Now that the backup has been performed (if requested), copy the replacement * into place */ if(!CopyFileW( lpReplacementFileName, lpReplacedFileName, FALSE )) { /* Assume that all access denied errors are a write problem. */ if(GetLastError() == ERROR_ACCESS_DENIED) SetLastError( ERROR_UNABLE_TO_REMOVE_REPLACED ); else SetLastError( ERROR_UNABLE_TO_MOVE_REPLACEMENT ); goto replace_fail; } /* Delete the replacement file */ if(!DeleteFileW( lpReplacementFileName )) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } /* Unlock the handles */ UnlockFile( hReplacement, 0, 0, 0, 0 ); CloseHandle( hReplacement ); UnlockFile( hReplaced, 0, 0, 0, 0 ); CloseHandle( hReplaced ); /* All done, file replacement successful */ return TRUE; replace_fail: UnlockFile( hReplacement, 0, 0, 0, 0 ); CloseHandle( hReplacement ); UnlockFile( hReplaced, 0, 0, 0, 0 ); CloseHandle( hReplaced ); return FALSE; }