|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
Fns.cpp
Abstract:
Contains all of the functions used by the application.
Notes:
Unicode only - Windows 2000, XP & Server 2003
History:
01/02/2002 rparsons Created 01/08/2002 rparsons Restructured a bit to add some required functionality 01/10/2002 rparsons Change wsprintf to snwprintf 01/18/2002 rparsons Major changes - made more installer like 02/15/2002 rparsons Install SDBInst on W2K. Include strsafe. 04/19/2002 rparsons Install different catalogs for Server 2003 & XP.
--*/ #include "main.h"
extern APPINFO g_ai;
/*++
Routine Description:
Retrieve file version info from a file.
The version is specified in the dwFileVersionMS and dwFileVersionLS fields of a VS_FIXEDFILEINFO, as filled in by the win32 version APIs.
If the file is not a coff image or does not have version resources, the function fails.
Arguments:
pwszFileName - Supplies the full path of the file whose version data is desired.
pdwlVersion - Receives the version stamp of the file. If the file is not a coff image or does not contain the appropriate version resource data, the function fails. Return Value:
TRUE on success, FALSE otherwise.
--*/ BOOL GetVersionInfoFromImage( IN LPWSTR pwszFileName, OUT PDWORDLONG pdwlVersion ) { UINT cchSize; DWORD cbSize, dwIgnored; BOOL bResult = FALSE; PVOID pVersionBlock = NULL; VS_FIXEDFILEINFO* pffi = NULL;
if (!pwszFileName || !pdwlVersion) { DPF(dlError, "[GetVersionInfoFromImage] Invalid arguments"); return FALSE; }
cbSize = GetFileVersionInfoSize(pwszFileName, &dwIgnored);
if (0 == cbSize) { DPF(dlError, "[GetVersionInfoFromImage] 0x%08X Failed to get version size", GetLastError()); return FALSE; }
//
// Allocate memory block of sufficient size to hold version info block.
//
pVersionBlock = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbSize);
if (!pVersionBlock) { DPF(dlError, "[GetVersionInfoFromImage] Unable to allocate memory"); return FALSE; }
//
// Get the version block from the file.
//
if (!GetFileVersionInfo(pwszFileName, 0, cbSize, pVersionBlock)) { DPF(dlError, "[GetVersionInfoFromImage] 0x%08X Failed to get version info", GetLastError()); goto exit; }
//
// Get fixed version info.
//
if (!VerQueryValue(pVersionBlock, L"\\", (LPVOID*)&pffi, &cchSize)) { DPF(dlError, "[GetVersionInfoFromImage] 0x%08X Failed to fixed version info", GetLastError()); goto exit; }
//
// Return version to caller.
//
*pdwlVersion = (((DWORDLONG)pffi->dwFileVersionMS) << 32) + pffi->dwFileVersionLS;
bResult = TRUE;
exit:
if (pVersionBlock) { HeapFree(GetProcessHeap(), 0, pVersionBlock); }
return bResult; }
/*++
Routine Description:
Initializes our data structures with information about the files that we're installing/uninstalling.
Arguments:
None.
Return Value:
TRUE on success, FALSE otherwise.
--*/ BOOL InitializeFileInfo( void ) { UINT uCount = 0; HRESULT hr;
//
// Set up the information for each file.
// I realize that a for loop seems much more suitable here,
// but we have to match up the destination for each file.
// Ideally, we would have a INF file to read from that tells
// us where to install each file.
// For now, copying and pasting is all we need to do.
//
hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName), FILENAME_APPVERIF_EXE);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (1)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName), L"%ls\\"FILENAME_APPVERIF_EXE, g_ai.wszCurrentDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (2)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName), L"%ls\\"FILENAME_APPVERIF_EXE, g_ai.wszSysDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (3)"); return FALSE; }
if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName, &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) { DPF(dlError, "[InitializeFileInfo] Failed to get version info for %ls", g_ai.rgFileInfo[uCount].wszSrcFileName); return FALSE; }
if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) { if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName, &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) { DPF(dlError, "[InitializeFileInfo] Failed to get version info for %ls", g_ai.rgFileInfo[uCount].wszDestFileName); return FALSE; } }
uCount++;
//
// Next file.
//
hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName), FILENAME_APPVERIF_EXE_PDB);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (4)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName), L"%ls\\"FILENAME_APPVERIF_EXE_PDB, g_ai.wszCurrentDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (5)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName), L"%ls\\"FILENAME_APPVERIF_EXE_PDB, g_ai.wszSysDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (6)"); return FALSE; }
uCount++;
//
// Next file.
//
hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName), FILENAME_APPVERIF_CHM);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (7)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName), L"%ls\\"FILENAME_APPVERIF_CHM, g_ai.wszCurrentDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (8)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName), L"%ls\\"FILENAME_APPVERIF_CHM, g_ai.wszSysDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (9)"); return FALSE; }
uCount++;
//
// Next file.
//
hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName), FILENAME_ACVERFYR_DLL);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (10)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName), L"%ls\\"FILENAME_ACVERFYR_DLL, g_ai.wszCurrentDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (11)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName), L"%ls\\AppPatch\\"FILENAME_ACVERFYR_DLL, g_ai.wszWinDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (12)"); return FALSE; }
if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName, &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) { DPF(dlError, "[InitializeFileInfo] Failed to get version info for %ls", g_ai.rgFileInfo[uCount].wszSrcFileName); return FALSE; }
if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) { if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName, &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) { DPF(dlError, "[InitializeFileInfo] Failed to get version info for %ls", g_ai.rgFileInfo[uCount].wszDestFileName); return FALSE; } }
uCount++;
//
// Next file.
//
hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName), FILENAME_ACVERFYR_DLL_PDB);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (13)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName), L"%ls\\"FILENAME_ACVERFYR_DLL_PDB, g_ai.wszCurrentDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (14)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName), L"%ls\\AppPatch\\"FILENAME_ACVERFYR_DLL_PDB, g_ai.wszWinDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (15)"); return FALSE; }
uCount++;
//
// Next file.
//
hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName), FILENAME_ACVERFYR_DLL);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (16)"); return FALSE; }
g_ai.rgFileInfo[uCount].bWin2KOnly = TRUE;
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName), L"%ls\\"FILENAME_ACVERFYR_DLL_W2K, g_ai.wszCurrentDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (17)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName), L"%ls\\AppPatch\\"FILENAME_ACVERFYR_DLL, g_ai.wszWinDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (18)"); return FALSE; }
if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName, &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) { DPF(dlError, "[InitializeFileInfo] Failed to get version info for %ls", g_ai.rgFileInfo[uCount].wszSrcFileName); return FALSE; }
if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) { if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName, &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) { DPF(dlError, "[InitializeFileInfo] Failed to get version info for %ls", g_ai.rgFileInfo[uCount].wszDestFileName); return FALSE; } }
uCount++;
//
// Next file.
//
hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName), FILENAME_ACVERFYR_DLL_PDB);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (19)"); return FALSE; }
g_ai.rgFileInfo[uCount].bWin2KOnly = TRUE;
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName), L"%ls\\"FILENAME_ACVERFYR_DLL_W2K_PDB, g_ai.wszCurrentDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (20)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName), L"%ls\\AppPatch\\"FILENAME_ACVERFYR_DLL_PDB, g_ai.wszWinDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (21)"); return FALSE; }
uCount++;
//
// Next file.
//
hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName), FILENAME_MSVCP60_DLL);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (22)"); return FALSE; }
g_ai.rgFileInfo[uCount].bWin2KOnly = TRUE;
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName), L"%ls\\"FILENAME_MSVCP60_DLL, g_ai.wszCurrentDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (23)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName), L"%ls\\"FILENAME_MSVCP60_DLL, g_ai.wszWinDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (24)"); return FALSE; }
if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName, &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) { DPF(dlError, "[InitializeFileInfo] Failed to get version info for %ls", g_ai.rgFileInfo[uCount].wszSrcFileName); return FALSE; }
if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) { if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName, &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) { DPF(dlError, "[InitializeFileInfo] Failed to get version info for %ls", g_ai.rgFileInfo[uCount].wszDestFileName); return FALSE; } }
uCount++;
//
// Next file.
//
hr = StringCchCopy(g_ai.rgFileInfo[uCount].wszFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszFileName), FILENAME_SDBINST_EXE);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (25)"); return FALSE; }
g_ai.rgFileInfo[uCount].bWin2KOnly = TRUE;
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszSrcFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszSrcFileName), L"%ls\\"FILENAME_SDBINST_EXE, g_ai.wszCurrentDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (26)"); return FALSE; }
hr = StringCchPrintf(g_ai.rgFileInfo[uCount].wszDestFileName, ARRAYSIZE(g_ai.rgFileInfo[uCount].wszDestFileName), L"%ls\\"FILENAME_SDBINST_EXE, g_ai.wszSysDir);
if (FAILED(hr)) { DPF(dlError, "[InitializeFileInfo] Buffer too small (27)"); return FALSE; }
if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszSrcFileName, &g_ai.rgFileInfo[uCount].dwlSrcFileVersion)) { DPF(dlError, "[InitializeFileInfo] Failed to get version info for %ls", g_ai.rgFileInfo[uCount].wszSrcFileName); return FALSE; }
if (GetFileAttributes(g_ai.rgFileInfo[uCount].wszDestFileName) != -1) { if (!GetVersionInfoFromImage(g_ai.rgFileInfo[uCount].wszDestFileName, &g_ai.rgFileInfo[uCount].dwlDestFileVersion)) { DPF(dlError, "[InitializeFileInfo] Failed to get version info for %ls", g_ai.rgFileInfo[uCount].wszDestFileName); return FALSE; } }
return TRUE; }
/*++
Routine Description:
Determines if any of the files we have to offer are newer than ones already installed.
Arguments:
None.
Return Value:
TRUE if we have at least one new file to offer. FALSE if we don't have at least one new file to offer.
--*/ BOOL InstallCheckFileVersions( void ) { UINT uCount; BOOL bReturn = FALSE;
for (uCount = 0; uCount < NUM_FILES; uCount++) { if (g_ai.rgFileInfo[uCount].dwlSrcFileVersion >= g_ai.rgFileInfo[uCount].dwlDestFileVersion) { g_ai.rgFileInfo[uCount].bInstall = TRUE; bReturn = TRUE; } }
return bReturn; }
/*++
Routine Description:
Determines if we have a newer version of appverif.exe or acverfyr.dll to offer.
Arguments:
None.
Return Value:
TRUE if our version is newer than the one installed. or if there is no version installed. FALSE otherwise.
--*/ BOOL IsPkgAppVerifNewer( void ) { //
// Check appverif.exe first.
//
if (g_ai.rgFileInfo[0].dwlSrcFileVersion >= g_ai.rgFileInfo[0].dwlDestFileVersion) { return TRUE; }
//
// Check acverfyr.dll if appverif.exe didn't pan out.
// Do this based on the platform.
//
if (g_ai.ePlatform == osWindowsXP || g_ai.ePlatform == osWindowsDotNet) { if (g_ai.rgFileInfo[1].dwlSrcFileVersion >= g_ai.rgFileInfo[1].dwlDestFileVersion) { return TRUE; } } else { if (g_ai.rgFileInfo[2].dwlSrcFileVersion >= g_ai.rgFileInfo[2].dwlDestFileVersion) { return TRUE; } }
//
// Perhaps we have a newer version of sdbinst to offer.
//
if (g_ai.ePlatform == osWindows2000) { if (g_ai.rgFileInfo[8].dwlSrcFileVersion >= g_ai.rgFileInfo[8].dwlDestFileVersion) { return TRUE; } }
return FALSE; }
/*++
Routine Description:
Performs a file copy, even if it's in use.
Arguments:
pwszSourceFileName - Name of the source file to copy. pwszDestFileName - Name of the destination file to replace.
Return Value:
TRUE on success, FALSE otherwise.
--*/ BOOL ForceCopy( IN LPCWSTR pwszSourceFileName, IN LPCWSTR pwszDestFileName ) { WCHAR wszTempPath[MAX_PATH]; WCHAR wszDelFileName[MAX_PATH]; DWORD cchSize;
if (!pwszSourceFileName || !pwszDestFileName) { DPF(dlError, "[ForceCopy] Invalid parameters"); return FALSE; }
DPF(dlInfo, "[ForceCopy] Source file: %ls", pwszSourceFileName); DPF(dlInfo, "[ForceCopy] Destination file: %ls", pwszDestFileName);
if (!CopyFile(pwszSourceFileName, pwszDestFileName, FALSE)) {
cchSize = GetTempPath(ARRAYSIZE(wszTempPath), wszTempPath);
if (cchSize > ARRAYSIZE(wszTempPath) || cchSize == 0) { DPF(dlError, "[ForceCopy] Buffer for temp path is too small"); return FALSE; }
if (!GetTempFileName(wszTempPath, L"del", 0, wszDelFileName)) { DPF(dlError, "[ForceCopy] 0x%08X Failed to get temp file", GetLastError()); return FALSE; }
if (!MoveFileEx(pwszDestFileName, wszDelFileName, MOVEFILE_REPLACE_EXISTING)) { DPF(dlError, "[ForceCopy] 0x%08X Failed to replace file", GetLastError()); return FALSE; }
if (!MoveFileEx(wszDelFileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) { DPF(dlError, "[ForceCopy] 0x%08X Failed to delete file", GetLastError()); return FALSE; }
if (!CopyFile(pwszSourceFileName, pwszDestFileName, FALSE)) { DPF(dlError, "[ForceCopy] 0x%08X Failed to copy file", GetLastError()); return FALSE; } }
return TRUE; }
/*++
Routine Description:
Prints a formatted string to the debugger.
Arguments:
dwDetail - Specifies the level of the information provided. pszFmt - The string to be displayed. ... - A va_list of insertion strings.
Return Value:
None.
--*/ void __cdecl DebugPrintfEx( IN DEBUGLEVEL dwDetail, IN LPSTR pszFmt, ... ) { char szT[1024]; va_list arglist; int len;
va_start(arglist, pszFmt);
//
// Reserve one character for the potential '\n' that we may be adding.
//
StringCchVPrintfA(szT, sizeof(szT) - 1, pszFmt, arglist);
va_end(arglist);
//
// Make sure we have a '\n' at the end of the string
//
len = strlen(szT);
if (len > 0 && szT[len - 1] != '\n') { szT[len] = '\n'; szT[len + 1] = 0; }
switch (dwDetail) { case dlPrint: DbgPrint("[MSG ] "); break;
case dlError: DbgPrint("[FAIL] "); break;
case dlWarning: DbgPrint("[WARN] "); break;
case dlInfo: DbgPrint("[INFO] "); break;
default: DbgPrint("[XXXX] "); break; }
DbgPrint("%s", szT); }
/*++
Routine Description:
Initializes the installer. Sets up paths, version information, etc.
Arguments:
None.
Return Value:
TRUE on success. FALSE on failure. -1 if the operating system is not supported.
--*/ int InitializeInstaller( void ) { OSVERSIONINFO osvi; WCHAR* pTemp = NULL; UINT cchSize; DWORD cchReturned; HRESULT hr;
//
// Find out what operating system we're running on.
//
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!GetVersionEx(&osvi)) { DPF(dlError, "[InitializeInstaller] 0x%08X Failed to get OS version info", GetLastError()); return FALSE; }
//
// No support for Win9x or NT4.
//
if (osvi.dwMajorVersion == 4) { DPF(dlInfo, "[InitializeInstaller] OS not supported"); return -1; }
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) { g_ai.ePlatform = osWindows2000; } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { g_ai.ePlatform = osWindowsXP; } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion >= 2) { g_ai.ePlatform = osWindowsDotNet; }
//
// Find out where we're running from.
//
g_ai.wszModuleName[ARRAYSIZE(g_ai.wszModuleName) - 1] = 0; cchReturned = GetModuleFileName(NULL, g_ai.wszModuleName, ARRAYSIZE(g_ai.wszModuleName));
if (g_ai.wszModuleName[ARRAYSIZE(g_ai.wszModuleName) - 1] != 0 || cchReturned == 0) { DPF(dlError, "[InitializeInstaller] 0x%08X Failed to get module file name", GetLastError()); return FALSE; }
//
// Save away our current directory for later use.
//
hr = StringCchCopy(g_ai.wszCurrentDir, ARRAYSIZE(g_ai.wszCurrentDir), g_ai.wszModuleName);
if (FAILED(hr)) { DPF(dlError, "[InitializeInstaller] 0x%08X String copy failed", hr); return FALSE; }
pTemp = wcsrchr(g_ai.wszCurrentDir, '\\');
if (pTemp) { *pTemp = 0; }
//
// Save away paths to the Windows & System32 directories for later use.
//
cchSize = GetSystemWindowsDirectory(g_ai.wszWinDir, ARRAYSIZE(g_ai.wszWinDir));
if (cchSize > ARRAYSIZE(g_ai.wszWinDir) || cchSize == 0) { DPF(dlError, "[InitializeInstaller] 0x%08X Failed to get Windows directory", GetLastError()); return FALSE; }
cchSize = GetSystemDirectory(g_ai.wszSysDir, ARRAYSIZE(g_ai.wszSysDir));
if (cchSize > ARRAYSIZE(g_ai.wszSysDir) || cchSize == 0) { DPF(dlError, "[InitializeInstaller] 0x%08X Failed to get system directory", GetLastError()); return FALSE; }
return TRUE; }
/*++
Routine Description:
Launches the Application Verifier.
Arguments:
None.
Return Value:
None.
--*/ void InstallLaunchExe( void ) { STARTUPINFO si; PROCESS_INFORMATION pi; WCHAR wszAppVerifExe[MAX_PATH]; HRESULT hr;
hr = StringCchPrintf(wszAppVerifExe, ARRAYSIZE(wszAppVerifExe), L"%ls\\"FILENAME_APPVERIF_EXE, g_ai.wszSysDir);
if (FAILED(hr)) { DPF(dlError, "[InstallLaunchExe] Buffer too small"); return; }
ZeroMemory(&si, sizeof(STARTUPINFO)); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
if (!CreateProcess(wszAppVerifExe, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { DPF(dlError, "[InstallLaunchExe] 0x%08X Failed to launch %ls", GetLastError(), wszAppVerifExe); return; }
CloseHandle(pi.hProcess); CloseHandle(pi.hThread); }
/*++
Routine Description:
Installs the catalog file.
Arguments:
pwszCatFileName - Name of the catalog file to install.
Return Value:
TRUE on success, FALSE otherwise.
--*/ BOOL InstallCatalogFile( IN LPWSTR pwszCatFileName ) { HCATADMIN hCatAdmin; HCATINFO hCatInfo; GUID guidCatRoot;
if (!pwszCatFileName) { DPF(dlError, "[InstallCatalogFile] Invalid parameter"); return FALSE; }
StringToGuid(L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}", &guidCatRoot);
if (!CryptCATAdminAcquireContext(&hCatAdmin, &guidCatRoot, 0)) { DPF(dlError, "[InstallCatalogFile] 0x%08X Failed to acquire context", GetLastError()); return FALSE; }
hCatInfo = CryptCATAdminAddCatalog(hCatAdmin, pwszCatFileName, NULL, 0);
if (hCatInfo) { CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0); CryptCATAdminReleaseContext(hCatAdmin, 0); return TRUE; }
CryptCATAdminReleaseContext(hCatAdmin, 0);
DPF(dlError, "[InstallCatalogFile] 0x%08X Failed to add catalog %ls", GetLastError(), pwszCatFileName);
return FALSE; }
/*++
Routine Description:
Installs a certificate into the certificate store.
Arguments:
None.
Return Value:
TRUE on success, FALSE otherwise.
--*/ BOOL InstallCertificateFile( void ) { STARTUPINFO si; PROCESS_INFORMATION pi; WCHAR wszCertMgrName[MAX_PATH]; WCHAR wszCertMgrCmdLine[MAX_PATH]; HRESULT hr;
ZeroMemory(&si, sizeof(STARTUPINFO)); ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
si.cb = sizeof(STARTUPINFO);
//
// Set up the path to certmgr.exe.
//
hr = StringCchPrintf(wszCertMgrName, ARRAYSIZE(wszCertMgrName), L"%ls\\"CERTMGR_EXE, g_ai.wszCurrentDir);
if (FAILED(hr)) { DPF(dlError, "[InstallCertificateFile] Buffer too small (1)"); return FALSE; }
//
// Set up the command-line for certmgr.exe.
//
hr = StringCchPrintf(wszCertMgrCmdLine, ARRAYSIZE(wszCertMgrCmdLine), L"%ls\\%ls %ls", g_ai.wszCurrentDir, CERTMGR_EXE, CERTMGR_CMD);
if (FAILED(hr)) { DPF(dlError, "[InstallCertificateFile] Buffer too small (2)"); return FALSE; }
if (!CreateProcess(wszCertMgrName, wszCertMgrCmdLine, NULL, NULL, FALSE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) {
DPF(dlError, "[InstallCertificateFile] 0x%08X Failed to launch '%ls %ls'", GetLastError(), wszCertMgrName, wszCertMgrCmdLine); return FALSE; }
CloseHandle(pi.hProcess); CloseHandle(pi.hThread);
return TRUE; }
/*++
Routine Description:
Performs the installation of the catalog file on Windows XP or Windows Server 2003.
Arguments:
None.
Return Value:
TRUE on success, FALSE otherwise.
--*/ BOOL PerformCatalogInstall( void ) { WCHAR wszCatalog[MAX_PATH]; HRESULT hr;
if (g_ai.ePlatform == osWindowsXP) { hr = StringCchPrintf(wszCatalog, ARRAYSIZE(wszCatalog), L"%ls\\"FILENAME_DELTA_CAT_XP, g_ai.wszCurrentDir); } else if (g_ai.ePlatform == osWindowsDotNet) { hr = StringCchPrintf(wszCatalog, ARRAYSIZE(wszCatalog), L"%ls\\"FILENAME_DELTA_CAT_DOTNET, g_ai.wszCurrentDir); }
if (FAILED(hr)) { DPF(dlError, "[PerformCatalogInstall] Buffer too small"); return FALSE; }
return (InstallCatalogFile(wszCatalog)); }
/*++
Routine Description:
Copies the files that we've determined are newer to their specified destination.
Arguments:
None.
Return Value:
TRUE on success, FALSE otherwise.
--*/ BOOL InstallCopyFiles( void ) { UINT uCount;
while (TRUE) { for (uCount = 0; uCount < NUM_FILES; uCount++) { if (g_ai.rgFileInfo[uCount].bInstall) { //
// If we're on XP and the file is not specifically for
// Windows 2000, copy it over.
//
if (g_ai.ePlatform != osWindows2000 && g_ai.rgFileInfo[uCount].bWin2KOnly) { break; }
if (!ForceCopy(g_ai.rgFileInfo[uCount].wszSrcFileName, g_ai.rgFileInfo[uCount].wszDestFileName)) { DPF(dlError, "[InstallCopyFiles] Failed to copy %ls to %ls", g_ai.rgFileInfo[uCount].wszSrcFileName, g_ai.rgFileInfo[uCount].wszDestFileName); return FALSE; } } }
break; }
return TRUE; }
/*++
Routine Description:
Performs the installation. This is the main routine for the install.
Arguments:
hWndParent - Parent window handle for message boxes.
Return Value:
None.
--*/ void PerformInstallation( IN HWND hWndParent ) { WCHAR wszError[MAX_PATH];
SendMessage(g_ai.hWndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, NUM_PB_STEPS)); SendMessage(g_ai.hWndProgress, PBM_SETSTEP, 1, 0);
//
// Initialize our structure with new files that need to be installed.
// This should not fail because we've already performed a check and
// it told us that we had new files to install.
//
if (!InstallCheckFileVersions()) { DPF(dlError, "[PerformInstallation] Failed to check file versions"); goto InstallError; }
//
// If we're running on Windows XP or Server 2003, install a catalog file
// and our certificate. We have different catalogs for XP versus Server 2003.
//
if (g_ai.ePlatform == osWindowsXP || g_ai.ePlatform == osWindowsDotNet) { if (!PerformCatalogInstall()) { DPF(dlError, "[PerformInstallation] Failed to install catalog"); goto InstallError; }
SendMessage(g_ai.hWndProgress, PBM_STEPIT, 0, 0);
if (!InstallCertificateFile()) { DPF(dlError, "[PerformInstallation] Failed to install certificate"); goto InstallError; } }
SendMessage(g_ai.hWndProgress, PBM_STEPIT, 0, 0);
if (!InstallCopyFiles()) { DPF(dlError, "[PerformInstallation] Failed to copy files"); goto InstallError; }
SendMessage(g_ai.hWndProgress, PBM_STEPIT, 0, 0);
DPF(dlInfo, "[PerformInstallation] Installation completed successfully");
g_ai.bInstallSuccess = TRUE;
//
// Install successful.
//
SendMessage(g_ai.hWndProgress, PBM_SETPOS, NUM_PB_STEPS, 0); LoadString(g_ai.hInstance, IDS_INSTALL_COMPLETE, wszError, ARRAYSIZE(wszError)); SetDlgItemText(hWndParent, IDC_STATUS, wszError); EnableWindow(GetDlgItem(hWndParent, IDOK), TRUE); ShowWindow(GetDlgItem(hWndParent, IDC_LAUNCH), SW_SHOW);
return;
InstallError: SendMessage(g_ai.hWndProgress, PBM_SETPOS, NUM_PB_STEPS, 0); LoadString(g_ai.hInstance, IDS_INSTALL_FAILED, wszError, ARRAYSIZE(wszError)); SetDlgItemText(hWndParent, IDC_STATUS, wszError); EnableWindow(GetDlgItem(hWndParent, IDCANCEL), TRUE); }
|