Leaked source code of windows server 2003
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.

610 lines
16 KiB

  1. #include <cdlpch.h>
  2. #include <winineti.h>
  3. #include <shellapi.h>
  4. // Globals
  5. #ifdef LOGO3_SUPPORT_AUTOINSTALL
  6. CList<Logo3CodeDLBSC *, Logo3CodeDLBSC *> g_CDLList;
  7. CMutexSem g_mxsCDL;
  8. UINT g_Timer;
  9. #endif
  10. Logo3CodeDLBSC::Logo3CodeDLBSC(CSoftDist *pSoftDist,
  11. IBindStatusCallback *pClientBSC,
  12. LPSTR szCodeBase, LPWSTR wzDistUnit)
  13. : _cRef(1)
  14. , _pIBinding(NULL)
  15. , _pClientBSC(pClientBSC)
  16. , _bPrecacheOnly(FALSE)
  17. , _pbc(NULL)
  18. , _pSoftDist(pSoftDist)
  19. #ifdef LOGO3_SUPPORT_AUTOINSTALL
  20. , _uiTimer(0)
  21. , _hProc(INVALID_HANDLE_VALUE)
  22. #endif
  23. {
  24. DEBUG_ENTER((DBG_DOWNLOAD,
  25. None,
  26. "Logo3CodeDLBSC::Logo3CodeDLBSC",
  27. "this=%#x, %#x, %#x, %.80q, %.80wq",
  28. this, pSoftDist, pClientBSC, szCodeBase, wzDistUnit
  29. ));
  30. DWORD len = 0;
  31. _szCodeBase = new char[lstrlen(szCodeBase) + 1];
  32. if (_szCodeBase)
  33. {
  34. lstrcpy(_szCodeBase, szCodeBase);
  35. }
  36. if (_pClientBSC)
  37. {
  38. _pClientBSC->AddRef();
  39. }
  40. if (_pSoftDist)
  41. {
  42. _pSoftDist->AddRef();
  43. }
  44. len = WideCharToMultiByte(CP_ACP,0, wzDistUnit, -1, NULL, 0, NULL, NULL);
  45. _szDistUnit = new TCHAR[len];
  46. if (_szDistUnit)
  47. {
  48. WideCharToMultiByte(CP_ACP, 0, wzDistUnit , -1, _szDistUnit,
  49. len, NULL, NULL);
  50. }
  51. DEBUG_LEAVE(0);
  52. }
  53. Logo3CodeDLBSC::~Logo3CodeDLBSC()
  54. {
  55. DEBUG_ENTER((DBG_DOWNLOAD,
  56. None,
  57. "Logo3CodeDLBSC::~Logo3CodeDLBSC",
  58. "this=%#x",
  59. this
  60. ));
  61. if (_pClientBSC)
  62. {
  63. _pClientBSC->Release();
  64. }
  65. if (_pbc)
  66. {
  67. _pbc->Release();
  68. }
  69. if (_pSoftDist)
  70. {
  71. _pSoftDist->Release();
  72. }
  73. delete [] _szCodeBase;
  74. delete [] _szDistUnit;
  75. DEBUG_LEAVE(0);
  76. }
  77. /*
  78. *
  79. * IUnknown Methods
  80. *
  81. */
  82. STDMETHODIMP Logo3CodeDLBSC::QueryInterface(REFIID riid, void **ppv)
  83. {
  84. DEBUG_ENTER((DBG_DOWNLOAD,
  85. Hresult,
  86. "Logo3CodeDLBSC::IUnknown::QueryInterface",
  87. "this=%#x, %#x, %#x",
  88. this, &riid, ppv
  89. ));
  90. HRESULT hr = E_NOINTERFACE;
  91. *ppv = NULL;
  92. if (riid == IID_IUnknown || riid == IID_IBindStatusCallback)
  93. {
  94. *ppv = (IBindStatusCallback *)this;
  95. }
  96. if (*ppv != NULL)
  97. {
  98. ((IUnknown *)*ppv)->AddRef();
  99. hr = S_OK;
  100. }
  101. DEBUG_LEAVE(hr);
  102. return hr;
  103. }
  104. STDMETHODIMP_(ULONG) Logo3CodeDLBSC::AddRef()
  105. {
  106. DEBUG_ENTER((DBG_DOWNLOAD,
  107. Dword,
  108. "Logo3CodeDLBSC::IUnknown::AddRef",
  109. "this=%#x",
  110. this
  111. ));
  112. ULONG ulRet = ++_cRef;
  113. DEBUG_LEAVE(ulRet);
  114. return ulRet;
  115. }
  116. STDMETHODIMP_(ULONG) Logo3CodeDLBSC::Release()
  117. {
  118. DEBUG_ENTER((DBG_DOWNLOAD,
  119. Dword,
  120. "Logo3CodeDLBSC::IUnknown::Release",
  121. "this=%#x",
  122. this
  123. ));
  124. if (--_cRef)
  125. {
  126. DEBUG_LEAVE(_cRef);
  127. return _cRef;
  128. }
  129. delete this;
  130. DEBUG_LEAVE(0);
  131. return 0;
  132. }
  133. /*
  134. *
  135. * IBindStatusCallback Methods
  136. *
  137. */
  138. STDMETHODIMP Logo3CodeDLBSC::OnStartBinding(DWORD grfBSCOption, IBinding *pib)
  139. {
  140. DEBUG_ENTER((DBG_DOWNLOAD,
  141. Hresult,
  142. "Logo3CodeDLBSC::IBindStatusCallback::OnStartBinding",
  143. "this=%#x, %#x, %#x",
  144. this, grfBSCOption, pib
  145. ));
  146. HRESULT hr = S_OK;
  147. if (_pIBinding != NULL)
  148. {
  149. _pIBinding->Release();
  150. }
  151. _pIBinding = pib;
  152. if (_pIBinding != NULL)
  153. {
  154. _pIBinding->AddRef();
  155. }
  156. if (_pClientBSC != NULL)
  157. {
  158. hr = _pClientBSC->OnStartBinding(grfBSCOption, pib);
  159. }
  160. DEBUG_LEAVE(hr);
  161. return hr;
  162. }
  163. STDMETHODIMP Logo3CodeDLBSC::OnStopBinding(HRESULT hr, LPCWSTR szError)
  164. {
  165. DEBUG_ENTER((DBG_DOWNLOAD,
  166. Hresult,
  167. "Logo3CodeDLBSC::IBindStatusCallback::OnStopBinding",
  168. "this=%#x, %#x, %.80wq",
  169. this, hr, szError
  170. ));
  171. #ifdef LOGO3_SUPPORT_AUTOINSTALL
  172. CLock lck(g_mxsCDL); // Mutex this method
  173. #endif
  174. DWORD dwSize = 0;
  175. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo = NULL;
  176. SHELLEXECUTEINFO sei;
  177. TCHAR achShortName[MAX_PATH];
  178. HANDLE hFile = INVALID_HANDLE_VALUE;
  179. LPWSTR pwzUrl = NULL;
  180. #ifdef LOGO3_SUPPORT_AUTOINSTALL
  181. // These vars are used for trust verification.
  182. // AS TODO: Get these values from QI'ing and QS'ing from the
  183. // client BindStatusCallback. For now, just use NULL values.
  184. IInternetHostSecurityManager *pHostSecurityManager = NULL;
  185. HWND hWnd = (HWND)INVALID_HANDLE_VALUE;
  186. PJAVA_TRUST pJavaTrust = NULL;
  187. #endif
  188. AddRef(); // RevokeBindStatusCallback() will destroy us too soon.
  189. if (_pIBinding != NULL)
  190. {
  191. _pIBinding->Release();
  192. _pIBinding = NULL;
  193. }
  194. #ifdef LOGO3_SUPPORT_AUTOINSTALL
  195. lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFO)achBuffer;
  196. dwSize = MAX_CACHE_ENTRY_INFO_SIZE;
  197. GetUrlCacheEntryInfo(_szCodeBase, lpCacheEntryInfo, &dwSize);
  198. GetShortPathName(lpCacheEntryInfo->lpszLocalFileName, achShortName,
  199. MAX_PATH);
  200. // Do trust verification
  201. if (!_bPrecacheOnly)
  202. {
  203. if ( (hFile = CreateFile(achShortName, GENERIC_READ, FILE_SHARE_READ,
  204. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0))
  205. == INVALID_HANDLE_VALUE)
  206. {
  207. hr = HRESULT_FROM_WIN32(GetLastError());
  208. goto Exit;
  209. }
  210. Ansi2Unicode(_szCodeBase, &pwzUrl);
  211. hr = _wvt.VerifyTrust(hFile, hWnd, &pJavaTrust, pwzUrl,
  212. pHostSecurityManager);
  213. SAFEDELETE(pJavaTrust);
  214. SAFEDELETE(pwzUrl);
  215. CloseHandle(hFile);
  216. }
  217. #endif
  218. #ifdef LOGO3_SUPPORT_AUTOINSTALL
  219. if (_bPrecacheOnly)
  220. {
  221. #endif
  222. if (SUCCEEDED(hr))
  223. {
  224. // Mark all downloads of the same group to be downloaded
  225. hr = _pSoftDist->Logo3DownloadNext();
  226. }
  227. else
  228. {
  229. // Get last download's group and search for another one to download
  230. hr = _pSoftDist->Logo3DownloadRedundant();
  231. }
  232. if ((FAILED(hr) && hr != E_PENDING) || hr == S_FALSE)
  233. {
  234. _pClientBSC->OnStopBinding(hr, szError);
  235. RecordPrecacheValue(hr);
  236. }
  237. #ifdef LOGO3_SUPPORT_AUTOINSTALL
  238. }
  239. else
  240. {
  241. sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
  242. sei.hwnd = NULL;
  243. sei.lpVerb = NULL; // "Open" is the default verb
  244. sei.lpFile = achShortName;
  245. sei.lpParameters = NULL;
  246. sei.lpDirectory = NULL;
  247. sei.nShow = SW_SHOWDEFAULT;
  248. sei.lpIDList = NULL;
  249. sei.lpClass = NULL;
  250. sei.hkeyClass = 0;
  251. sei.dwHotKey = 0;
  252. sei.hIcon = INVALID_HANDLE_VALUE;
  253. sei.cbSize = sizeof(sei);
  254. if (!ShellExecuteEx(&sei)) {
  255. goto Exit;
  256. }
  257. _hProc = sei.hProcess;
  258. if (!g_Timer) {
  259. g_Timer = SetTimer(NULL, (UINT)this, TIMEOUT_INTERVAL, TimeOutProc);
  260. }
  261. g_CDLList.AddTail(this);
  262. AddRef();
  263. }
  264. #endif
  265. Assert(_pbc);
  266. RevokeBindStatusCallback(_pbc, this);
  267. _pbc->Release();
  268. _pbc = NULL;
  269. Release();
  270. DEBUG_LEAVE(hr);
  271. return hr;
  272. }
  273. STDMETHODIMP Logo3CodeDLBSC::OnObjectAvailable(REFIID riid, IUnknown *punk)
  274. {
  275. DEBUG_ENTER((DBG_DOWNLOAD,
  276. Hresult,
  277. "Logo3CodeDLBSC::IBindStatusCallback::OnObjectAvailable",
  278. "this=%#x, %#x, %#x",
  279. this, &riid, punk
  280. ));
  281. HRESULT hr = S_OK;
  282. if (_pClientBSC)
  283. {
  284. hr = _pClientBSC->OnObjectAvailable(riid, punk);
  285. }
  286. DEBUG_LEAVE(hr);
  287. return hr;
  288. }
  289. STDMETHODIMP Logo3CodeDLBSC::GetPriority(LONG *pnPriority)
  290. {
  291. DEBUG_ENTER((DBG_DOWNLOAD,
  292. Hresult,
  293. "Logo3CodeDLBSC::IBindStatusCallback::GetPriority",
  294. "this=%#x, %#x",
  295. this, pnPriority
  296. ));
  297. HRESULT hr = S_OK;
  298. if (_pClientBSC)
  299. {
  300. hr = _pClientBSC->GetPriority(pnPriority);
  301. }
  302. DEBUG_LEAVE(hr);
  303. return hr;
  304. }
  305. STDMETHODIMP Logo3CodeDLBSC::OnLowResource(DWORD dwReserved)
  306. {
  307. DEBUG_ENTER((DBG_DOWNLOAD,
  308. Hresult,
  309. "Logo3CodeDLBSC::IBindStatusCallback::OnLowResource",
  310. "this=%#x, %#x",
  311. this, dwReserved
  312. ));
  313. HRESULT hr = S_OK;
  314. if (_pClientBSC)
  315. {
  316. hr = _pClientBSC->OnLowResource(dwReserved);
  317. }
  318. DEBUG_LEAVE(hr);
  319. return hr;
  320. }
  321. STDMETHODIMP Logo3CodeDLBSC::OnProgress(ULONG ulProgress, ULONG ulProgressMax,
  322. ULONG ulStatusCode,
  323. LPCWSTR szStatusText)
  324. {
  325. DEBUG_ENTER((DBG_DOWNLOAD,
  326. Hresult,
  327. "Logo3CodeDLBSC::IBindStatusCallback::OnProgress",
  328. "this=%#x, %#x, %#x, %#x, %.80wq",
  329. this, ulProgress, ulProgressMax, ulStatusCode, szStatusText
  330. ));
  331. HRESULT hr = S_OK;
  332. if (_pClientBSC)
  333. {
  334. hr = _pClientBSC->OnProgress(ulProgress, ulProgressMax,
  335. ulStatusCode, szStatusText);
  336. }
  337. DEBUG_LEAVE(hr);
  338. return hr;
  339. }
  340. STDMETHODIMP Logo3CodeDLBSC::GetBindInfo(DWORD *pgrfBINDF, BINDINFO *pbindInfo)
  341. {
  342. DEBUG_ENTER((DBG_DOWNLOAD,
  343. Hresult,
  344. "Logo3CodeDLBSC::IBindStatusCallback::GetBindInfo",
  345. "this=%#x, %#x, %#x",
  346. this, pgrfBINDF, pbindInfo
  347. ));
  348. HRESULT hr = S_OK;
  349. *pgrfBINDF |= BINDF_ASYNCHRONOUS;
  350. if (_pClientBSC)
  351. {
  352. hr = _pClientBSC->GetBindInfo(pgrfBINDF, pbindInfo);
  353. if (*pgrfBINDF & BINDF_SILENTOPERATION)
  354. {
  355. _bPrecacheOnly = TRUE;
  356. }
  357. }
  358. DEBUG_LEAVE(S_OK);
  359. return S_OK;
  360. }
  361. STDMETHODIMP Logo3CodeDLBSC::OnDataAvailable(DWORD grfBSCF, DWORD dwSize,
  362. FORMATETC *pformatetc,
  363. STGMEDIUM *pstgmed)
  364. {
  365. DEBUG_ENTER((DBG_DOWNLOAD,
  366. Hresult,
  367. "Logo3CodeDLBSC::IBindStatusCallback::OnDataAvailable",
  368. "this=%#x, %#x, %#x, %#x, %#x",
  369. this, grfBSCF, dwSize, pformatetc, pstgmed
  370. ));
  371. HRESULT hr = S_OK;
  372. if (_pClientBSC)
  373. {
  374. hr = _pClientBSC->OnDataAvailable(grfBSCF, dwSize, pformatetc,
  375. pstgmed);
  376. }
  377. DEBUG_LEAVE(S_OK);
  378. return S_OK;
  379. }
  380. void Logo3CodeDLBSC::SetBindCtx(IBindCtx *pbc)
  381. {
  382. DEBUG_ENTER((DBG_DOWNLOAD,
  383. None,
  384. "Logo3CodeDLBSC::SetBindCtx",
  385. "this=%#x, %#x",
  386. this, pbc
  387. ));
  388. _pbc = pbc;
  389. if (_pbc)
  390. {
  391. _pbc->AddRef();
  392. }
  393. DEBUG_LEAVE(0);
  394. }
  395. STDMETHODIMP Logo3CodeDLBSC::RecordPrecacheValue(HRESULT hr)
  396. {
  397. DEBUG_ENTER((DBG_DOWNLOAD,
  398. Hresult,
  399. "Logo3CodeDLBSC::RecordPrecacheValue",
  400. "this=%#x, %#x",
  401. this, hr
  402. ));
  403. HRESULT hrRet = S_OK;
  404. DWORD lResult = 0;
  405. HKEY hkeyLogo3 = 0;
  406. HKEY hkeyVersion = 0;
  407. char achBuffer[MAX_CACHE_ENTRY_INFO_SIZE];
  408. static const char *szAvailableVersion = "AvailableVersion";
  409. static const char *szPrecache = "Precache";
  410. if (_szDistUnit != NULL)
  411. {
  412. wnsprintf(achBuffer, sizeof(achBuffer)-1, "%s\\%s", REGSTR_PATH_LOGO3_SETTINGS, _szDistUnit);
  413. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, achBuffer, 0, KEY_ALL_ACCESS,
  414. &hkeyLogo3) == ERROR_SUCCESS)
  415. {
  416. if (RegOpenKeyEx(hkeyLogo3, szAvailableVersion,
  417. 0, KEY_ALL_ACCESS, &hkeyVersion) != ERROR_SUCCESS)
  418. {
  419. if ((lResult = RegCreateKey(hkeyLogo3, szAvailableVersion,
  420. &hkeyVersion)) != ERROR_SUCCESS)
  421. {
  422. hrRet = HRESULT_FROM_WIN32(lResult);
  423. goto Exit;
  424. }
  425. }
  426. // record result of caching bits.
  427. HRESULT hrRecord = hr;
  428. if (FAILED(hr))
  429. {
  430. hrRecord = ERROR_IO_INCOMPLETE;
  431. }
  432. lResult = ::RegSetValueEx(hkeyVersion, szPrecache, NULL, REG_DWORD,
  433. (unsigned char *)&hrRecord, sizeof(DWORD));
  434. if (lResult != ERROR_SUCCESS)
  435. {
  436. hrRet = HRESULT_FROM_WIN32(lResult);
  437. goto Exit;
  438. }
  439. }
  440. }
  441. else {
  442. hrRet = E_INVALIDARG;
  443. }
  444. Exit:
  445. if (hkeyLogo3)
  446. {
  447. RegCloseKey(hkeyLogo3);
  448. }
  449. if (hkeyVersion)
  450. {
  451. RegCloseKey(hkeyVersion);
  452. }
  453. DEBUG_LEAVE(hrRet);
  454. return hrRet;
  455. }
  456. #ifdef LOGO3_SUPPORT_AUTOINSTALL
  457. void Logo3CodeDLBSC::TimeOut()
  458. {
  459. DEBUG_ENTER((DBG_DOWNLOAD,
  460. None,
  461. "Logo3CodeDLBSC::TimeOut",
  462. "this=%#x",
  463. this
  464. ));
  465. CLock lck(g_mxsCDL); // Mutex req for CDLList
  466. LISTPOSITION pos = NULL;
  467. if (WaitForSingleObjectEx(_hProc, 0, FALSE) == WAIT_OBJECT_0)
  468. {
  469. Assert(_pClientBSC);
  470. _pClientBSC->OnStopBinding(S_OK, NULL);
  471. // Remove self from code download list
  472. pos = g_CDLList.Find(this);
  473. Assert(pos);
  474. g_CDLList.RemoveAt(pos);
  475. Release();
  476. // If no more code downloads, kill the timer
  477. if (!g_CDLList.GetCount()) {
  478. KillTimer(NULL, g_Timer);
  479. g_Timer = 0;
  480. }
  481. }
  482. DEBUG_LEAVE(0);
  483. }
  484. void CALLBACK TimeOutProc(HWND hwnd, UINT msg, UINT idEvent, DWORD dwTime)
  485. {
  486. DEBUG_ENTER((DBG_DOWNLOAD,
  487. None,
  488. "TimeOutProc",
  489. "%#x, %#x, %#x, %#x",
  490. hwnd, msg, idEvent, dwTime
  491. ));
  492. LISTPOSITION pos = NULL;
  493. Logo3CodeDLBSC *bsc = NULL;
  494. lpos = g_CDLList.GetHeadPosition();
  495. while (lpos) {
  496. bsc = g_CDLList.GetNext(pos);
  497. Assert(bsc);
  498. bsc->TimeOut();
  499. }
  500. DEBUG_LEAVE(0);
  501. }
  502. #endif