/************************************************************************ Copyright (c) 2000 - 2000 Microsoft Corporation Module Name : cache.cpp Abstract : Sources files for file cache management Author : Revision History : ***********************************************************************/ #include "stdafx.h" #include #include #if !defined(BITS_V12_ON_NT4) #include "cache.tmh" #endif BOOL CProgressiveDL::OpenLocalDownloadFile( LPCTSTR Path, UINT64 Offset, UINT64 Size, FILETIME UrlModificationTime, // 0 if unknown FILETIME * pFileCreationTime ) { HANDLE hFile; bool bOpenExisting; if (Offset > 0) { // Storing the creation time via SetFileTime doesn't provide ironclad reliability due to granularity problems. // A tighter condition for a changed server file would be to check the "etag" header if available from the server. bOpenExisting = true; hFile = CreateFile( Path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if (hFile == INVALID_HANDLE_VALUE ) { DWORD dwError = GetLastError(); LogError("error %!winerr!, opening '%S'", dwError, Path ); SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, dwError, "CreateFile" ); return FALSE; } LARGE_INTEGER liFileSize; if ( !GetFileSizeEx( hFile, &liFileSize ) ) { DWORD dwError = GetLastError(); CloseHandle( hFile ); LogError("error %!winerr!, retrieving size of '%S'", dwError, Path ); SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, dwError, "GetFileSizeEx" ); return FALSE; } if ( Size != liFileSize.QuadPart ) { CloseHandle( hFile ); LogError("File size of '%S' changed", Path ); m_pQMInfo->result = QM_SERVER_FILE_CHANGED; return FALSE; } LARGE_INTEGER liOffset; liOffset.QuadPart = Offset; if (!SetFilePointerEx( hFile, liOffset, NULL, // don't need the new file pointer FILE_BEGIN )) { DWORD dwError = GetLastError(); CloseHandle( hFile ); LogError("error %!winerr!, seeking to current position in '%S'", dwError, Path ); SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, dwError, "SetFilePointerEx" ); return FALSE; } } else { bOpenExisting = false; hFile = CreateFile( Path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL ); if (hFile == INVALID_HANDLE_VALUE ) { SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, GetLastError(), "CreateFile" ); return FALSE; } // Reserve space for the file upfront. LARGE_INTEGER liOffset; liOffset.QuadPart = Size; if (!SetFilePointerEx( hFile, liOffset, NULL, FILE_BEGIN )) { DWORD dwError = GetLastError(); CloseHandle( hFile ); LogError( "error %!winerr! setting end of file, out of disk space?", dwError ); SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, dwError, "SetFilePointerEx" ); return FALSE; } if ( !SetEndOfFile( hFile ) ) { DWORD dwError = GetLastError(); CloseHandle( hFile ); LogError( "error %!winerr! setting end of file, out of disk space?", dwError ); SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, dwError, "SetFilePointerEx" ); return FALSE; } liOffset.QuadPart = 0; if (!SetFilePointerEx( hFile, liOffset, NULL, FILE_BEGIN )) { DWORD dwError = GetLastError(); CloseHandle( hFile ); LogError( "error %!winerr! returning to the beginning of the file", dwError ); SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, dwError, "SetFilePointerEx" ); return FALSE; } if ( UrlModificationTime.dwHighDateTime || UrlModificationTime.dwLowDateTime ) { if (!SetFileTime( hFile, &UrlModificationTime, NULL, NULL ) ) { DWORD dwError = GetLastError(); CloseHandle( hFile ); LogError( "error %!winerr! setting creation time", dwError ); if (dwError == ERROR_INVALID_PARAMETER) { dwError = BG_E_INVALID_SERVER_RESPONSE; } SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, dwError, "SetFileTime" ); return FALSE; } } } if (!GetFileTime( hFile, pFileCreationTime, NULL, NULL ) ) { DWORD dwError = GetLastError(); CloseHandle( hFile ); LogError( "error %!winerr!, unable to get file creation time", dwError ); SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, dwError, "GetFileTime" ); return FALSE; } if ( bOpenExisting ) { if ( UrlModificationTime.dwHighDateTime || UrlModificationTime.dwLowDateTime ) { if ( CompareFileTime( &UrlModificationTime, pFileCreationTime ) > 0 ) { // UrlModificationTime is newer CloseHandle( hFile ); LogError("File time of '%S' changed", Path ); m_pQMInfo->result = QM_SERVER_FILE_CHANGED; return FALSE; } } } m_hFile = hFile; m_CurrentOffset = Offset; return TRUE; } BOOL CProgressiveDL::CloseLocalFile() { if (m_hFile == INVALID_HANDLE_VALUE) { return FALSE; } CloseHandle( m_hFile ); m_hFile = INVALID_HANDLE_VALUE; return TRUE; } BOOL CProgressiveDL::WriteBlockToCache( LPBYTE lpBuffer, DWORD dwRead ) { DWORD dwWritten = 0; ASSERT( m_hFile != INVALID_HANDLE_VALUE ); if (! WriteFile( m_hFile, lpBuffer, dwRead, &dwWritten, NULL) || (dwRead != dwWritten)) { SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, GetLastError(), "WriteFile" ); return FALSE; } m_CurrentOffset += dwWritten; return TRUE; } BOOL CProgressiveDL::SetFileTimes() { ASSERT( m_hFile != INVALID_HANDLE_VALUE ); if ( !m_wupdinfo->UrlModificationTime.dwHighDateTime && !m_wupdinfo->UrlModificationTime.dwLowDateTime ) { LogWarning( "Server doesn't support modification times, can't set it on the files." ); return TRUE; } if ( !SetFileTime( m_hFile, &m_wupdinfo->UrlModificationTime, &m_wupdinfo->UrlModificationTime, &m_wupdinfo->UrlModificationTime ) ) { DWORD dwError = GetLastError(); LogError( "Unable to get times on the local file, error %!winerr!", dwError ); SetError( SOURCE_QMGR_FILE, ERROR_STYLE_WIN32, dwError, "SetFileTime" ); return FALSE; } return TRUE; }