229 lines
6.3 KiB
C++
229 lines
6.3 KiB
C++
#include "stdinc.h"
|
|
#include <windows.h>
|
|
#include "sxsp.h"
|
|
#include <stdio.h>
|
|
#include <setupapi.h>
|
|
#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;
|
|
}
|