#include "stdinc.h" #include #include "sxsp.h" #include #include #include "fusionhandle.h" #include "sxspath.h" #include "sxsapi.h" #include "sxsid.h" #include "sxsidp.h" #include "strongname.h" #include "fusiontrace.h" BOOL SxspCopyFile( DWORD dwFlags, PCWSTR pszSource, PCWSTR pszDestination ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess); BOOL fFileWasInUse = FALSE; DWORD dwCopyStyle = 0; PARAMETER_CHECK((dwFlags & ~(SXSP_COPY_FILE_FLAG_REPLACE_EXISTING | SXSP_COPY_FILE_FLAG_COMPRESSION_AWARE)) == 0); PARAMETER_CHECK(pszSource != NULL); PARAMETER_CHECK(pszDestination != NULL); #if 0 if (dwFlags & SXSP_COPY_FILE_FLAG_COMPRESSION_AWARE) { CSmallStringBuffer buffTempFile; BOOL fTemp; IFW32FALSE_EXIT(buffTempFile.Win32Assign(pszDestination, wcslen(pszDestination))); IFW32FALSE_EXIT(buffTempFile.Win32Append(L".$$$", 4)); dwCopyStyle |= SP_COPY_SOURCE_ABSOLUTE | SP_COPY_NOSKIP; if ((dwFlags & SXSP_COPY_FILE_FLAG_REPLACE_EXISTING) == 0) dwCopyStyle |= SP_COPY_FORCE_NOOVERWRITE; IFW32FALSE_ORIGINATE_AND_EXIT( ::SetupInstallFileExW( NULL, // optional HINF InfHandle NULL, // optional PINFCONTEXT InfContext pszSource, // source file NULL, // source path buffTempFile, // optional filename after copy dwCopyStyle, NULL, // optional copy msg handler NULL, // optional copy msg handler context &fFileWasInUse)); fTemp = ::MoveFileExW( buffTempFile, pszDestination, (dwFlags & SXSP_COPY_FILE_FLAG_REPLACE_EXISTING) ? MOVEFILE_REPLACE_EXISTING : 0); if (!fTemp) { const DWORD dwLastError = ::FusionpGetLastWin32Error(); fTemp = ::DeleteFileW(buffTempFile); if (!fTemp) { // Oh boy, cleaning up the temporary file didn't work. Queue the deletion... fTemp = ::MoveFileExW(buffTempFile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); // The worst case scenario here is that we have an extra file left around... forget it. } ORIGINATE_WIN32_FAILURE_AND_EXIT(MoveFileExW, dwLastError); } } else #endif { IFW32FALSE_ORIGINATE_AND_EXIT( ::CopyFileW( pszSource, pszDestination, (dwFlags & SXSP_COPY_FILE_FLAG_REPLACE_EXISTING) == 0)); } fSuccess = TRUE; Exit: return fSuccess; } BOOL SxspGetFileSize( DWORD dwFlags, PCWSTR file, ULONGLONG &fileSize ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess); PWSTR pszActualSource = NULL; fileSize = 0; PARAMETER_CHECK(file != NULL); PARAMETER_CHECK((dwFlags & ~(SXSP_GET_FILE_SIZE_FLAG_COMPRESSION_AWARE | SXSP_GET_FILE_SIZE_FLAG_GET_COMPRESSED_SOURCE_SIZE)) == 0); PARAMETER_CHECK((dwFlags & SXSP_GET_FILE_SIZE_FLAG_COMPRESSION_AWARE) || !(dwFlags & SXSP_GET_FILE_SIZE_FLAG_GET_COMPRESSED_SOURCE_SIZE)); if (dwFlags & SXSP_GET_FILE_SIZE_FLAG_COMPRESSION_AWARE) { DWORD dwTemp; DWORD dwSourceFileSize, dwTargetFileSize; UINT uiCompressionType; dwTemp = ::SetupGetFileCompressionInfoW( file, &pszActualSource, &dwSourceFileSize, &dwTargetFileSize, &uiCompressionType); if (dwTemp != ERROR_SUCCESS) ORIGINATE_WIN32_FAILURE_AND_EXIT(SetupGetFileCompressionInfoW, dwTemp); if (pszActualSource != NULL) ::LocalFree((HLOCAL) pszActualSource); pszActualSource = NULL; if (dwFlags & SXSP_GET_FILE_SIZE_FLAG_GET_COMPRESSED_SOURCE_SIZE) fileSize = dwSourceFileSize; else fileSize = dwTargetFileSize; } else { LARGE_INTEGER liFileSize = {0}; WIN32_FILE_ATTRIBUTE_DATA wfad; wfad.nFileSizeLow = 0; wfad.nFileSizeHigh = 0; IFW32FALSE_ORIGINATE_AND_EXIT(::GetFileAttributesExW(file, GetFileExInfoStandard, &wfad)); liFileSize.LowPart = wfad.nFileSizeLow; liFileSize.HighPart = wfad.nFileSizeHigh; fileSize = liFileSize.QuadPart; } fSuccess = TRUE; Exit: if (pszActualSource != NULL) { CSxsPreserveLastError ple; ::LocalFree((HLOCAL) pszActualSource); ple.Restore(); } return fSuccess; } BOOL SxspDoesFileExist( DWORD dwFlags, PCWSTR pszFileName, bool &rfExists ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess); PWSTR pszActualSource = NULL; rfExists = false; PARAMETER_CHECK(pszFileName != NULL); PARAMETER_CHECK((dwFlags & ~(SXSP_DOES_FILE_EXIST_FLAG_COMPRESSION_AWARE)) == 0); if (dwFlags & SXSP_DOES_FILE_EXIST_FLAG_COMPRESSION_AWARE) { DWORD dwTemp; DWORD dwSourceFileSize, dwTargetFileSize; UINT uiCompressionType; dwTemp = ::SetupGetFileCompressionInfoW( pszFileName, &pszActualSource, &dwSourceFileSize, &dwTargetFileSize, &uiCompressionType); if (pszActualSource != NULL) ::LocalFree((HLOCAL) pszActualSource); if (dwTemp == ERROR_FILE_NOT_FOUND) { // This case is OK. No error to return... } else if (dwTemp != ERROR_SUCCESS) ORIGINATE_WIN32_FAILURE_AND_EXIT(SetupGetFileCompressionInfoW, dwTemp); else { rfExists = true; } pszActualSource = NULL; } else { if (::GetFileAttributesW(pszFileName) == ((DWORD) -1)) { const DWORD dwLastError = ::GetLastError(); if (dwLastError != ERROR_FILE_NOT_FOUND) ORIGINATE_WIN32_FAILURE_AND_EXIT(GetFileAttributesW, dwLastError); } else rfExists = true; } fSuccess = TRUE; Exit: if (pszActualSource != NULL) { CSxsPreserveLastError ple; ::LocalFree((HLOCAL) pszActualSource); ple.Restore(); } return fSuccess; }