Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

277 lines
8.4 KiB

  1. #include "stdafx.h"
  2. #include "iudl.h"
  3. #include "selfupd.h"
  4. #include "loadengine.h"
  5. #include "update.h"
  6. #include <iucommon.h>
  7. #include <logging.h>
  8. #include <shlwapi.h>
  9. #include <fileutil.h>
  10. #include <iu.h>
  11. #include <trust.h>
  12. #include <UrlAgent.h>
  13. #include "wusafefn.h"
  14. extern HANDLE g_hEngineLoadQuit;
  15. extern CIUUrlAgent *g_pIUUrlAgent;
  16. /////////////////////////////////////////////////////////////////////////////
  17. // LoadIUEngine()
  18. //
  19. // load the engine if it's not up-to-date; perform engine's self-update here
  20. //
  21. // NOTE: CDM.DLL assumes LoadIUEngine does NOT make any use of COM. If this
  22. // changes then CDM will have to change at the same time.
  23. /////////////////////////////////////////////////////////////////////////////
  24. HMODULE WINAPI LoadIUEngine(BOOL fSynch, BOOL fOfflineMode)
  25. {
  26. LOG_Block("LoadIUEngine()");
  27. HRESULT hr = E_FAIL;
  28. HMODULE hEngineModule = NULL;
  29. TCHAR szEnginePath[MAX_PATH + 1];
  30. TCHAR szEngineNewPath[MAX_PATH + 1];
  31. int cch = 0;
  32. int iVerCheck = 0;
  33. if (!fSynch)
  34. {
  35. //
  36. // this version does not accept async load engine
  37. //
  38. LOG_ErrorMsg(E_INVALIDARG);
  39. return NULL;
  40. }
  41. LPTSTR ptszLivePingServerUrl = NULL;
  42. LPTSTR ptszCorpPingServerUrl = NULL;
  43. if (NULL != (ptszCorpPingServerUrl = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR))))
  44. {
  45. if (FAILED(g_pIUUrlAgent->GetCorpPingServer(ptszCorpPingServerUrl, INTERNET_MAX_URL_LENGTH)))
  46. {
  47. LOG_Out(_T("failed to get corp WU ping server URL"));
  48. SafeHeapFree(ptszCorpPingServerUrl);
  49. }
  50. }
  51. else
  52. {
  53. LOG_Out(_T("failed to allocate memory for ptszCorpPingServerUrl"));
  54. }
  55. // clear the quit event in case this gets called after a previous quit attempt.
  56. ResetEvent(g_hEngineLoadQuit);
  57. // This is the first load of the engine for this instance, check for selfupdate first.
  58. // First step is to check for an updated iuident.cab and download it.
  59. if (!fOfflineMode)
  60. {
  61. //
  62. // download iuident and populate g_pIUUrlAgent
  63. //
  64. CleanUpIfFailedAndMsg(DownloadIUIdent_PopulateData());
  65. //
  66. // get live ping server url
  67. //
  68. ptszLivePingServerUrl = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
  69. CleanUpFailedAllocSetHrMsg(ptszLivePingServerUrl);
  70. if (FAILED(g_pIUUrlAgent->GetLivePingServer(ptszLivePingServerUrl, INTERNET_MAX_URL_LENGTH)))
  71. {
  72. LOG_Out(_T("failed to get live ping server URL"));
  73. SafeHeapFree(ptszLivePingServerUrl);
  74. }
  75. //
  76. // Now do the self update check
  77. // for the current implementation, fSync must be TRUE!
  78. //
  79. hr = SelfUpdateCheck(fSynch, TRUE, NULL, NULL, NULL);
  80. if (IU_SELFUPDATE_FAILED == hr)
  81. {
  82. LOG_Error(_T("SelfUpdate Failed, using current Engine DLL"));
  83. }
  84. }
  85. if (WAIT_TIMEOUT != WaitForSingleObject(g_hEngineLoadQuit, 0))
  86. {
  87. LOG_ErrorMsg(E_ABORT);
  88. goto CleanUp;
  89. }
  90. // try loading iuenginenew.dll first
  91. //
  92. // first, contrsuct file path form sys dir
  93. //
  94. cch = GetSystemDirectory(szEnginePath, ARRAYSIZE(szEnginePath));
  95. CleanUpIfFalseAndSetHrMsg(cch == 0 || cch >= ARRAYSIZE(szEnginePath), HRESULT_FROM_WIN32(GetLastError()));
  96. (void) StringCchCopy(szEngineNewPath, ARRAYSIZE(szEngineNewPath), szEnginePath);
  97. hr = PathCchAppend(szEnginePath, ARRAYSIZE(szEnginePath), ENGINEDLL);
  98. CleanUpIfFailedAndMsg(hr);
  99. hr = PathCchAppend(szEngineNewPath, ARRAYSIZE(szEngineNewPath), ENGINENEWDLL);
  100. CleanUpIfFailedAndMsg(hr);
  101. //
  102. // try to verify trust of engine new
  103. //
  104. if (FileExists(szEngineNewPath) &&
  105. S_OK == VerifyFileTrust(szEngineNewPath, NULL, ReadWUPolicyShowTrustUI()) &&
  106. SUCCEEDED(CompareFileVersion(szEnginePath, szEngineNewPath, &iVerCheck)) &&
  107. iVerCheck < 0)
  108. {
  109. hEngineModule = LoadLibraryFromSystemDir(ENGINENEWDLL);
  110. if (NULL != hEngineModule)
  111. {
  112. LOG_Internet(_T("IUCtl Using IUENGINENEW.DLL"));
  113. }
  114. }
  115. if (NULL == hEngineModule)
  116. {
  117. LOG_Internet(_T("IUCtl Using IUENGINE.DLL"));
  118. hEngineModule = LoadLibraryFromSystemDir(_T("iuengine.dll"));
  119. }
  120. //
  121. // If load engine succeeded, start misc worker threads
  122. //
  123. if (NULL != hEngineModule)
  124. {
  125. PFN_AsyncExtraWorkUponEngineLoad pfnAsyncExtraWorkUponEngineLoad =
  126. (PFN_AsyncExtraWorkUponEngineLoad) GetProcAddress(hEngineModule, "AsyncExtraWorkUponEngineLoad");
  127. if (NULL != pfnAsyncExtraWorkUponEngineLoad)
  128. {
  129. pfnAsyncExtraWorkUponEngineLoad();
  130. }
  131. hr = S_OK;
  132. }
  133. CleanUp:
  134. PingEngineUpdate(
  135. hEngineModule,
  136. &g_hEngineLoadQuit,
  137. 1,
  138. ptszLivePingServerUrl,
  139. ptszCorpPingServerUrl,
  140. hr);
  141. SafeHeapFree(ptszLivePingServerUrl);
  142. SafeHeapFree(ptszCorpPingServerUrl);
  143. return hEngineModule;
  144. }
  145. /////////////////////////////////////////////////////////////////////////////
  146. // UnLoadIUEngine()
  147. //
  148. // release the engine dll if ref cnt of engine is down to zero
  149. //
  150. // NOTE: CDM.DLL assumes UnLoadIUEngine does NOT make any use of COM. If this
  151. // changes then CDM will have to change at the same time.
  152. //
  153. // NOTE: DeleteEngUpdateInstance must be called before calling this function
  154. // for any callers EXCEPT CDM (which uses the ShutdownThreads export as
  155. // a hack to delete the global CDM instance of the CEngUpdate class
  156. // if it was created by calling SetGlobalOfflineFlag.
  157. /////////////////////////////////////////////////////////////////////////////
  158. void WINAPI UnLoadIUEngine(HMODULE hEngineModule)
  159. {
  160. LOG_Block("UnLoadIUEngine()");
  161. TCHAR szSystemDir[MAX_PATH+1];
  162. TCHAR szEngineDllPath[MAX_PATH+1];
  163. TCHAR szEngineNewDllPath[MAX_PATH+1];
  164. int iVerCheck = 0;
  165. //
  166. // the engine might have some outstanding threads working,
  167. // so we need to let the engine shut down these threads gracefully
  168. //
  169. PFN_ShutdownThreads pfnShutdownThreads = (PFN_ShutdownThreads) GetProcAddress(hEngineModule, "ShutdownThreads");
  170. if (NULL != pfnShutdownThreads)
  171. {
  172. pfnShutdownThreads();
  173. }
  174. FreeLibrary(hEngineModule);
  175. GetSystemDirectory(szSystemDir, ARRAYSIZE(szSystemDir));
  176. PathCchCombine(szEngineNewDllPath,ARRAYSIZE(szEngineNewDllPath), szSystemDir, ENGINENEWDLL);
  177. HKEY hkey = NULL;
  178. DWORD dwStatus = 0;
  179. DWORD dwSize = sizeof(dwStatus);
  180. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_IUCTL, &hkey))
  181. {
  182. RegQueryValueEx(hkey, REGVAL_SELFUPDATESTATUS, NULL, NULL, (LPBYTE)&dwStatus, &dwSize);
  183. }
  184. if (FileExists(szEngineNewDllPath) &&
  185. S_OK == VerifyFileTrust(szEngineNewDllPath, NULL, ReadWUPolicyShowTrustUI()) &&
  186. SELFUPDATE_COMPLETE_UPDATE_BINARY_REQUIRED == dwStatus)
  187. {
  188. // an iuenginenew.dll exists, try replacing the engine.dll This will fail if this is
  189. // not the last process using the engine. This is not a problem, when that process
  190. // finishes it will rename the DLL.
  191. //
  192. // the check we do before we rename the file:
  193. // 1. enginenew exists
  194. // 2. enginenew signed by Microsoft cert
  195. // 3. enginenew has higher version then iuengine.dll
  196. //
  197. PathCchCombine(szEngineDllPath,ARRAYSIZE(szEngineDllPath),szSystemDir, ENGINEDLL);
  198. if (SUCCEEDED(CompareFileVersion(szEngineDllPath, szEngineNewDllPath, &iVerCheck)) &&
  199. iVerCheck < 0 &&
  200. TRUE == MoveFileEx(szEngineNewDllPath, szEngineDllPath, MOVEFILE_REPLACE_EXISTING))
  201. {
  202. // Rename was Successful.. reset RegKey Information about SelfUpdate Status
  203. // Because the rename was successful we know no other processes are interacting
  204. // It should be safe to set the reg key.
  205. dwStatus = 0;
  206. RegSetValueEx(hkey, REGVAL_SELFUPDATESTATUS, 0, REG_DWORD, (LPBYTE)&dwStatus, sizeof(dwStatus));
  207. }
  208. }
  209. else if (SELFUPDATE_COMPLETE_UPDATE_BINARY_REQUIRED == dwStatus)
  210. {
  211. // registry indicates rename required, but enginenew DLL does not exist. Reset registry
  212. dwStatus = 0;
  213. RegSetValueEx(hkey, REGVAL_SELFUPDATESTATUS, 0, REG_DWORD, (LPBYTE)&dwStatus, sizeof(dwStatus));
  214. }
  215. if (NULL != hkey)
  216. {
  217. RegCloseKey(hkey);
  218. }
  219. }
  220. /////////////////////////////////////////////////////////////////////////////
  221. // CtlCancelEngineLoad()
  222. //
  223. // Asynchronous Callers can use this abort the LoadEngine SelfUpdate Process
  224. //
  225. // NOTE: CDM.DLL assumes UnLoadIUEngine does NOT make any use of COM. If this
  226. // changes then CDM will have to change at the same time.
  227. /////////////////////////////////////////////////////////////////////////////
  228. HRESULT WINAPI CtlCancelEngineLoad()
  229. {
  230. if (NULL != g_hEngineLoadQuit)
  231. {
  232. SetEvent(g_hEngineLoadQuit);
  233. }
  234. else
  235. {
  236. // no event was available
  237. return E_FAIL;
  238. }
  239. return S_OK;
  240. }