278 lines
8.4 KiB
C++
278 lines
8.4 KiB
C++
|
#include "stdafx.h"
|
||
|
#include "iudl.h"
|
||
|
#include "selfupd.h"
|
||
|
#include "loadengine.h"
|
||
|
#include "update.h"
|
||
|
#include <iucommon.h>
|
||
|
#include <logging.h>
|
||
|
#include <shlwapi.h>
|
||
|
#include <fileutil.h>
|
||
|
#include <iu.h>
|
||
|
#include <trust.h>
|
||
|
#include <UrlAgent.h>
|
||
|
#include "wusafefn.h"
|
||
|
|
||
|
extern HANDLE g_hEngineLoadQuit;
|
||
|
extern CIUUrlAgent *g_pIUUrlAgent;
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// LoadIUEngine()
|
||
|
//
|
||
|
// load the engine if it's not up-to-date; perform engine's self-update here
|
||
|
//
|
||
|
// NOTE: CDM.DLL assumes LoadIUEngine does NOT make any use of COM. If this
|
||
|
// changes then CDM will have to change at the same time.
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
HMODULE WINAPI LoadIUEngine(BOOL fSynch, BOOL fOfflineMode)
|
||
|
{
|
||
|
LOG_Block("LoadIUEngine()");
|
||
|
HRESULT hr = E_FAIL;
|
||
|
HMODULE hEngineModule = NULL;
|
||
|
|
||
|
TCHAR szEnginePath[MAX_PATH + 1];
|
||
|
TCHAR szEngineNewPath[MAX_PATH + 1];
|
||
|
int cch = 0;
|
||
|
int iVerCheck = 0;
|
||
|
|
||
|
if (!fSynch)
|
||
|
{
|
||
|
//
|
||
|
// this version does not accept async load engine
|
||
|
//
|
||
|
LOG_ErrorMsg(E_INVALIDARG);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
LPTSTR ptszLivePingServerUrl = NULL;
|
||
|
LPTSTR ptszCorpPingServerUrl = NULL;
|
||
|
|
||
|
if (NULL != (ptszCorpPingServerUrl = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR))))
|
||
|
{
|
||
|
if (FAILED(g_pIUUrlAgent->GetCorpPingServer(ptszCorpPingServerUrl, INTERNET_MAX_URL_LENGTH)))
|
||
|
{
|
||
|
LOG_Out(_T("failed to get corp WU ping server URL"));
|
||
|
SafeHeapFree(ptszCorpPingServerUrl);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LOG_Out(_T("failed to allocate memory for ptszCorpPingServerUrl"));
|
||
|
}
|
||
|
|
||
|
// clear the quit event in case this gets called after a previous quit attempt.
|
||
|
ResetEvent(g_hEngineLoadQuit);
|
||
|
|
||
|
// This is the first load of the engine for this instance, check for selfupdate first.
|
||
|
// First step is to check for an updated iuident.cab and download it.
|
||
|
|
||
|
if (!fOfflineMode)
|
||
|
{
|
||
|
//
|
||
|
// download iuident and populate g_pIUUrlAgent
|
||
|
//
|
||
|
CleanUpIfFailedAndMsg(DownloadIUIdent_PopulateData());
|
||
|
|
||
|
//
|
||
|
// get live ping server url
|
||
|
//
|
||
|
ptszLivePingServerUrl = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
|
||
|
CleanUpFailedAllocSetHrMsg(ptszLivePingServerUrl);
|
||
|
|
||
|
if (FAILED(g_pIUUrlAgent->GetLivePingServer(ptszLivePingServerUrl, INTERNET_MAX_URL_LENGTH)))
|
||
|
{
|
||
|
LOG_Out(_T("failed to get live ping server URL"));
|
||
|
SafeHeapFree(ptszLivePingServerUrl);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now do the self update check
|
||
|
// for the current implementation, fSync must be TRUE!
|
||
|
//
|
||
|
hr = SelfUpdateCheck(fSynch, TRUE, NULL, NULL, NULL);
|
||
|
|
||
|
if (IU_SELFUPDATE_FAILED == hr)
|
||
|
{
|
||
|
LOG_Error(_T("SelfUpdate Failed, using current Engine DLL"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (WAIT_TIMEOUT != WaitForSingleObject(g_hEngineLoadQuit, 0))
|
||
|
{
|
||
|
LOG_ErrorMsg(E_ABORT);
|
||
|
goto CleanUp;
|
||
|
}
|
||
|
|
||
|
// try loading iuenginenew.dll first
|
||
|
|
||
|
//
|
||
|
// first, contrsuct file path form sys dir
|
||
|
//
|
||
|
cch = GetSystemDirectory(szEnginePath, ARRAYSIZE(szEnginePath));
|
||
|
CleanUpIfFalseAndSetHrMsg(cch == 0 || cch >= ARRAYSIZE(szEnginePath), HRESULT_FROM_WIN32(GetLastError()));
|
||
|
|
||
|
(void) StringCchCopy(szEngineNewPath, ARRAYSIZE(szEngineNewPath), szEnginePath);
|
||
|
|
||
|
hr = PathCchAppend(szEnginePath, ARRAYSIZE(szEnginePath), ENGINEDLL);
|
||
|
CleanUpIfFailedAndMsg(hr);
|
||
|
|
||
|
hr = PathCchAppend(szEngineNewPath, ARRAYSIZE(szEngineNewPath), ENGINENEWDLL);
|
||
|
CleanUpIfFailedAndMsg(hr);
|
||
|
|
||
|
//
|
||
|
// try to verify trust of engine new
|
||
|
//
|
||
|
if (FileExists(szEngineNewPath) &&
|
||
|
S_OK == VerifyFileTrust(szEngineNewPath, NULL, ReadWUPolicyShowTrustUI()) &&
|
||
|
SUCCEEDED(CompareFileVersion(szEnginePath, szEngineNewPath, &iVerCheck)) &&
|
||
|
iVerCheck < 0)
|
||
|
{
|
||
|
hEngineModule = LoadLibraryFromSystemDir(ENGINENEWDLL);
|
||
|
if (NULL != hEngineModule)
|
||
|
{
|
||
|
LOG_Internet(_T("IUCtl Using IUENGINENEW.DLL"));
|
||
|
}
|
||
|
}
|
||
|
if (NULL == hEngineModule)
|
||
|
{
|
||
|
LOG_Internet(_T("IUCtl Using IUENGINE.DLL"));
|
||
|
hEngineModule = LoadLibraryFromSystemDir(_T("iuengine.dll"));
|
||
|
}
|
||
|
//
|
||
|
// If load engine succeeded, start misc worker threads
|
||
|
//
|
||
|
if (NULL != hEngineModule)
|
||
|
{
|
||
|
PFN_AsyncExtraWorkUponEngineLoad pfnAsyncExtraWorkUponEngineLoad =
|
||
|
(PFN_AsyncExtraWorkUponEngineLoad) GetProcAddress(hEngineModule, "AsyncExtraWorkUponEngineLoad");
|
||
|
|
||
|
if (NULL != pfnAsyncExtraWorkUponEngineLoad)
|
||
|
{
|
||
|
pfnAsyncExtraWorkUponEngineLoad();
|
||
|
}
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
|
||
|
CleanUp:
|
||
|
PingEngineUpdate(
|
||
|
hEngineModule,
|
||
|
&g_hEngineLoadQuit,
|
||
|
1,
|
||
|
ptszLivePingServerUrl,
|
||
|
ptszCorpPingServerUrl,
|
||
|
hr);
|
||
|
|
||
|
SafeHeapFree(ptszLivePingServerUrl);
|
||
|
SafeHeapFree(ptszCorpPingServerUrl);
|
||
|
return hEngineModule;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// UnLoadIUEngine()
|
||
|
//
|
||
|
// release the engine dll if ref cnt of engine is down to zero
|
||
|
//
|
||
|
// NOTE: CDM.DLL assumes UnLoadIUEngine does NOT make any use of COM. If this
|
||
|
// changes then CDM will have to change at the same time.
|
||
|
//
|
||
|
// NOTE: DeleteEngUpdateInstance must be called before calling this function
|
||
|
// for any callers EXCEPT CDM (which uses the ShutdownThreads export as
|
||
|
// a hack to delete the global CDM instance of the CEngUpdate class
|
||
|
// if it was created by calling SetGlobalOfflineFlag.
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
void WINAPI UnLoadIUEngine(HMODULE hEngineModule)
|
||
|
{
|
||
|
LOG_Block("UnLoadIUEngine()");
|
||
|
TCHAR szSystemDir[MAX_PATH+1];
|
||
|
TCHAR szEngineDllPath[MAX_PATH+1];
|
||
|
TCHAR szEngineNewDllPath[MAX_PATH+1];
|
||
|
int iVerCheck = 0;
|
||
|
|
||
|
//
|
||
|
// the engine might have some outstanding threads working,
|
||
|
// so we need to let the engine shut down these threads gracefully
|
||
|
//
|
||
|
PFN_ShutdownThreads pfnShutdownThreads = (PFN_ShutdownThreads) GetProcAddress(hEngineModule, "ShutdownThreads");
|
||
|
if (NULL != pfnShutdownThreads)
|
||
|
{
|
||
|
pfnShutdownThreads();
|
||
|
}
|
||
|
|
||
|
|
||
|
FreeLibrary(hEngineModule);
|
||
|
|
||
|
GetSystemDirectory(szSystemDir, ARRAYSIZE(szSystemDir));
|
||
|
|
||
|
|
||
|
PathCchCombine(szEngineNewDllPath,ARRAYSIZE(szEngineNewDllPath), szSystemDir, ENGINENEWDLL);
|
||
|
|
||
|
|
||
|
|
||
|
HKEY hkey = NULL;
|
||
|
DWORD dwStatus = 0;
|
||
|
DWORD dwSize = sizeof(dwStatus);
|
||
|
if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_IUCTL, &hkey))
|
||
|
{
|
||
|
RegQueryValueEx(hkey, REGVAL_SELFUPDATESTATUS, NULL, NULL, (LPBYTE)&dwStatus, &dwSize);
|
||
|
}
|
||
|
if (FileExists(szEngineNewDllPath) &&
|
||
|
S_OK == VerifyFileTrust(szEngineNewDllPath, NULL, ReadWUPolicyShowTrustUI()) &&
|
||
|
SELFUPDATE_COMPLETE_UPDATE_BINARY_REQUIRED == dwStatus)
|
||
|
{
|
||
|
// an iuenginenew.dll exists, try replacing the engine.dll This will fail if this is
|
||
|
// not the last process using the engine. This is not a problem, when that process
|
||
|
// finishes it will rename the DLL.
|
||
|
//
|
||
|
// the check we do before we rename the file:
|
||
|
// 1. enginenew exists
|
||
|
// 2. enginenew signed by Microsoft cert
|
||
|
// 3. enginenew has higher version then iuengine.dll
|
||
|
//
|
||
|
PathCchCombine(szEngineDllPath,ARRAYSIZE(szEngineDllPath),szSystemDir, ENGINEDLL);
|
||
|
|
||
|
if (SUCCEEDED(CompareFileVersion(szEngineDllPath, szEngineNewDllPath, &iVerCheck)) &&
|
||
|
iVerCheck < 0 &&
|
||
|
TRUE == MoveFileEx(szEngineNewDllPath, szEngineDllPath, MOVEFILE_REPLACE_EXISTING))
|
||
|
{
|
||
|
// Rename was Successful.. reset RegKey Information about SelfUpdate Status
|
||
|
// Because the rename was successful we know no other processes are interacting
|
||
|
// It should be safe to set the reg key.
|
||
|
dwStatus = 0;
|
||
|
RegSetValueEx(hkey, REGVAL_SELFUPDATESTATUS, 0, REG_DWORD, (LPBYTE)&dwStatus, sizeof(dwStatus));
|
||
|
}
|
||
|
}
|
||
|
else if (SELFUPDATE_COMPLETE_UPDATE_BINARY_REQUIRED == dwStatus)
|
||
|
{
|
||
|
// registry indicates rename required, but enginenew DLL does not exist. Reset registry
|
||
|
dwStatus = 0;
|
||
|
RegSetValueEx(hkey, REGVAL_SELFUPDATESTATUS, 0, REG_DWORD, (LPBYTE)&dwStatus, sizeof(dwStatus));
|
||
|
}
|
||
|
if (NULL != hkey)
|
||
|
{
|
||
|
RegCloseKey(hkey);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CtlCancelEngineLoad()
|
||
|
//
|
||
|
// Asynchronous Callers can use this abort the LoadEngine SelfUpdate Process
|
||
|
//
|
||
|
// NOTE: CDM.DLL assumes UnLoadIUEngine does NOT make any use of COM. If this
|
||
|
// changes then CDM will have to change at the same time.
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT WINAPI CtlCancelEngineLoad()
|
||
|
{
|
||
|
if (NULL != g_hEngineLoadQuit)
|
||
|
{
|
||
|
SetEvent(g_hEngineLoadQuit);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// no event was available
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|