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.

1659 lines
57 KiB

  1. #include <windows.h>
  2. #include <objbase.h>
  3. #include <shlobj.h>
  4. #include <fusenetincludes.h>
  5. #include <activator.h>
  6. #include <versionmanagement.h>
  7. #include <shellapi.h> // for shellexecuteex
  8. #include <shellres.h>
  9. #define INITGUID
  10. #include <guiddef.h>
  11. // used in OnProgress(), copied from guids.c
  12. DEFINE_GUID( IID_IAssemblyManifestImport,
  13. 0x696fb37f,0xda64,0x4175,0x94,0xe7,0xfd,0xc8,0x23,0x45,0x39,0xc4);
  14. // Update services
  15. #include "server.h"
  16. DEFINE_GUID(IID_IAssemblyUpdate,
  17. 0x301b3415,0xf52d,0x4d40,0xbd,0xf7,0x31,0xd8,0x27,0x12,0xc2,0xdc);
  18. DEFINE_GUID(CLSID_CAssemblyUpdate,
  19. 0x37b088b8,0x70ef,0x4ecf,0xb1,0x1e,0x1f,0x3f,0x4d,0x10,0x5f,0xdd);
  20. extern HRESULT GetLastWin32Error();
  21. #define WZ_TYPE_DOTNET L".NetAssembly"
  22. #define WZ_TYPE_WIN32 L"win32Executable"
  23. #define WZ_TYPE_AVALON L"avalon"
  24. #define WZ_TYPE_CONSOLE L"win32Console"
  25. #define TYPE_DOTNET 1
  26. #define TYPE_WIN32 2
  27. #define TYPE_AVALON 3
  28. #define TYPE_CONSOLE 4
  29. #if 1
  30. #include "ndphostthunk.cpp"
  31. #else // old code
  32. // CLR Hosting
  33. #import "..\..\clrhost\asmexec.tlb" raw_interfaces_only
  34. using namespace asmexec;
  35. #endif
  36. // debug msg stuff
  37. void Msg(LPCWSTR pwz);
  38. void ShowError(LPCWSTR pwz);
  39. void ShowError(HRESULT hr, LPCWSTR pwz=NULL);
  40. // ----------------------------------------------------------------------------
  41. typedef struct
  42. {
  43. LPCWSTR pwzTitle;
  44. LPCWSTR pwzText;
  45. } SHOWDIALOG_MSG;
  46. #define DIALOG_OK 1
  47. #define DIALOG_CANCEL 2
  48. #define DIALOG_CLOSE 3
  49. //IDC_TEXT
  50. INT_PTR CALLBACK DialogBoxProc(
  51. HWND hwndDlg, // handle to dialog box
  52. UINT uMsg, // message
  53. WPARAM wParam, // first message parameter
  54. LPARAM lParam // second message parameter
  55. )
  56. {
  57. //
  58. // Dialog proc for dialog window
  59. //
  60. switch( uMsg )
  61. {
  62. case WM_INITDIALOG:
  63. {
  64. SHOWDIALOG_MSG* pMsg = (SHOWDIALOG_MSG*) lParam;
  65. if (pMsg->pwzTitle)
  66. SetWindowText( hwndDlg, (LPWSTR) pMsg->pwzTitle);
  67. if (pMsg->pwzText)
  68. {
  69. HWND hwndText = GetDlgItem( hwndDlg, IDC_TEXT );
  70. if (hwndText)
  71. SetWindowText( hwndText, (LPWSTR) pMsg->pwzText);
  72. }
  73. }
  74. return TRUE;
  75. case WM_COMMAND:
  76. switch( LOWORD( wParam ) )
  77. {
  78. #ifdef IDC_OK
  79. case IDC_OK:
  80. EndDialog( hwndDlg, DIALOG_OK );
  81. return TRUE;
  82. #endif
  83. #ifdef IDC_CANCEL
  84. case IDC_CANCEL:
  85. EndDialog( hwndDlg, DIALOG_CANCEL );
  86. return TRUE;
  87. #endif
  88. default:
  89. return FALSE;
  90. }
  91. case WM_NOTIFY:
  92. if ((IDC_TEXT == LOWORD(wParam) ) &&
  93. ((NM_CLICK == ((LPNMHDR)lParam)->code) ||
  94. (NM_RETURN == ((LPNMHDR)lParam)->code)))
  95. {
  96. PNMLINK pNMLink = (PNMLINK) lParam;
  97. // check szURL empty
  98. if (pNMLink->item.szUrl[0] == L'\0')
  99. return FALSE;
  100. SHELLEXECUTEINFO sei = { 0 };
  101. sei.cbSize = sizeof(SHELLEXECUTEINFO);
  102. sei.fMask = SEE_MASK_DOENVSUBST | SEE_MASK_NO_CONSOLE; //SEE_MASK_FLAG_NO_UI |
  103. sei.nShow = SW_SHOWNORMAL;
  104. // ISSUE-06/14/02-felixybc shellexecute should work as such
  105. // for some unknown reason it is failing with module not found
  106. //sei.lpFile = pNMLink->item.szUrl;
  107. sei.lpParameters=pNMLink->item.szUrl;
  108. sei.lpFile=L"iexplore.exe";
  109. //
  110. sei.lpVerb = L"open";
  111. // ISSUE: check return with IF_WIN32_FALSE_EXIT(), check hInstApp for detail error
  112. ShellExecuteEx(&sei);
  113. return TRUE;
  114. }
  115. else
  116. // WM_NOTIFY not handled.
  117. return FALSE;
  118. default:
  119. return FALSE;
  120. }
  121. }
  122. extern HINSTANCE g_DllInstance;
  123. HRESULT ShowDialog(HWND hWndParent, WORD wDlgId, LPCWSTR pwzText, LPCWSTR pwzTitle, DWORD& dwReturnValue)
  124. {
  125. HRESULT hr = S_OK;
  126. MAKE_ERROR_MACROS_STATIC(hr);
  127. INT_PTR iptrReturn = 0;
  128. SHOWDIALOG_MSG msg = {0};
  129. /* INITCOMMONCONTROLSEX iccex;
  130. iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  131. iccex.dwICC = ICC_LINK_CLASS | ICC_WIN95_CLASSES | ICC_STANDARD_CLASSES;
  132. IF_FALSE_EXIT(InitCommonControlsEx(&iccex), E_FAIL);*/
  133. msg.pwzTitle = pwzTitle;
  134. msg.pwzText = pwzText;
  135. IF_WIN32_FALSE_EXIT((iptrReturn = DialogBoxParam(g_DllInstance, MAKEINTRESOURCE(wDlgId), hWndParent, DialogBoxProc, (LPARAM) &msg) > 0));
  136. dwReturnValue = PtrToLong((VOID *)iptrReturn);
  137. exit:
  138. return hr;
  139. }
  140. // ----------------------------------------------------------------------------
  141. HRESULT
  142. RunCommand(LPCWSTR wzAppFileName, LPWSTR pwzCommandline, LPCWSTR wzCurrentDir, BOOL fWait)
  143. {
  144. HRESULT hr = S_OK;
  145. MAKE_ERROR_MACROS_STATIC(hr);
  146. STARTUPINFO si;
  147. PROCESS_INFORMATION pi;
  148. ZeroMemory(&si, sizeof(si));
  149. ZeroMemory(&pi, sizeof(pi));
  150. si.cb = sizeof(si);
  151. // wzCurrentDir: The string must be a full path and file name that includes a drive letter; or NULL
  152. // note: pwzCommandline is LPWSTR, NOT LPCWSTR
  153. IF_WIN32_FALSE_EXIT(CreateProcess(wzAppFileName, pwzCommandline, NULL, NULL, FALSE, 0, NULL, wzCurrentDir, &si, &pi));
  154. if (fWait)
  155. {
  156. IF_FALSE_EXIT(!(WaitForSingleObject(pi.hProcess, 180000L) == WAIT_TIMEOUT), HRESULT_FROM_WIN32(ERROR_TIMEOUT));
  157. }
  158. exit:
  159. if(pi.hProcess)
  160. {
  161. BOOL bReturn = CloseHandle(pi.hProcess);
  162. if (SUCCEEDED(hr) && !bReturn)
  163. hr = GetLastWin32Error();
  164. }
  165. if(pi.hThread)
  166. {
  167. BOOL bReturn = CloseHandle(pi.hThread);
  168. if (SUCCEEDED(hr) && !bReturn)
  169. hr = GetLastWin32Error();
  170. }
  171. return hr;
  172. }
  173. HRESULT
  174. RunCommandConsole(LPCWSTR wzAppFileName, LPCWSTR wzCurrentDir, BOOL fWait)
  175. {
  176. HRESULT hr = S_OK;
  177. MAKE_ERROR_MACROS_STATIC(hr);
  178. LPWSTR pwzPath = NULL;
  179. LPWSTR pwzBuffer = NULL;
  180. DWORD ccPath = 0;
  181. CString sAppdir;
  182. CString sSystemDir;
  183. CString sCurrentDir;
  184. CString sCmdExe;
  185. CString sCommandLine;
  186. CString sPath;
  187. // App dir
  188. IF_FAILED_EXIT(sAppdir.Assign(wzCurrentDir));
  189. // System directory.
  190. // bugbug - platforms; use GetRealWindowsDirectory instead?
  191. IF_WIN32_FALSE_EXIT((ccPath = GetSystemDirectory(NULL, 0)));
  192. IF_FALSE_EXIT(ccPath+1 > ccPath, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW)); // check overflow
  193. ccPath+=1;
  194. IF_ALLOC_FAILED_EXIT(pwzBuffer = new WCHAR[ccPath]);
  195. IF_WIN32_FALSE_EXIT(GetSystemDirectory(pwzBuffer, ccPath));
  196. IF_FAILED_EXIT(sSystemDir.Assign(pwzBuffer));
  197. // Current dir = root dir
  198. *(pwzBuffer+ sizeof("c:\\")-1) = L'\0';
  199. IF_FAILED_EXIT(sCurrentDir.Assign(pwzBuffer));
  200. // Path to cmd.exe
  201. IF_FAILED_EXIT(sCmdExe.Assign(sSystemDir));
  202. IF_FAILED_EXIT(sCmdExe.Append(L"\\cmd.exe"));
  203. // command line
  204. IF_FAILED_EXIT(sCommandLine.Assign(L"/k \""));
  205. IF_FAILED_EXIT(sCommandLine.Append(wzAppFileName));
  206. IF_FAILED_EXIT(sCommandLine.Append(L"\""));
  207. // Get current path.
  208. IF_WIN32_FALSE_EXIT((ccPath = GetEnvironmentVariable(L"PATH", NULL, 0)));
  209. IF_ALLOC_FAILED_EXIT(pwzPath = new WCHAR[ccPath]);
  210. IF_WIN32_FALSE_EXIT(GetEnvironmentVariable(L"PATH", pwzPath, ccPath));
  211. IF_FAILED_EXIT(sPath.TakeOwnership(pwzPath, ccPath));
  212. pwzPath = NULL;
  213. // Append app path to current path.
  214. IF_FAILED_EXIT(sPath.Append(sAppdir));
  215. // set new path env variable.
  216. IF_WIN32_FALSE_EXIT(SetEnvironmentVariable(L"PATH", sPath._pwz));
  217. IF_FAILED_EXIT(RunCommand(sCmdExe._pwz, sCommandLine._pwz, sCurrentDir._pwz,fWait));
  218. exit:
  219. SAFEDELETEARRAY(pwzPath);
  220. SAFEDELETEARRAY(pwzBuffer);
  221. return hr;
  222. }
  223. // ----------------------------------------------------------------------------
  224. // note: this append a '.manifest' file extension to the given pwzRealName
  225. HRESULT
  226. CopyToUSStartMenu(LPCWSTR pwzFilePath, LPCWSTR pwzRealName, BOOL bOverwrite, LPWSTR* ppwzResultFilePath)
  227. {
  228. HRESULT hr = S_OK;
  229. MAKE_ERROR_MACROS_STATIC(hr);
  230. LPWSTR pwz = NULL;
  231. CString sPath;
  232. IF_ALLOC_FAILED_EXIT(pwz = new WCHAR[MAX_PATH]);
  233. pwz[0] = L'\0';
  234. // should it create the folder? C:\Documents and Settings\username\Start Menu\Programs
  235. // "Start Menu\Programs" is localized in non-english windows
  236. IF_FAILED_EXIT(SHGetFolderPath(NULL, CSIDL_PROGRAMS | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, pwz));
  237. IF_FAILED_EXIT(sPath.TakeOwnership(pwz, 0));
  238. pwz = NULL;
  239. // ISSUE-2002/03/27-felixybc Check returned path from SHGetFolderPath has no trailing '\'
  240. IF_FAILED_EXIT(sPath.Append(L"\\"));
  241. IF_FAILED_EXIT(sPath.Append(pwzRealName));
  242. IF_FAILED_EXIT(sPath.Append(L".manifest"));
  243. if (!CopyFile(pwzFilePath, sPath._pwz, !bOverwrite))
  244. {
  245. hr = GetLastWin32Error();
  246. ASSERT(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)); // do not assert if file already exists
  247. goto exit;
  248. }
  249. // return the file path
  250. IF_FAILED_EXIT(sPath.ReleaseOwnership(ppwzResultFilePath));
  251. exit:
  252. SAFEDELETEARRAY(pwz);
  253. return hr;
  254. }
  255. // ----------------------------------------------------------------------------
  256. // ISSUE-2002/03/30-felixybc Temp wrapper code
  257. // wrapper for CAssemblyUpdate::RegisterAssemblySubscriptionEx
  258. HRESULT
  259. RegisterAssemblySubscriptionEx(IAssemblyUpdate *pAssemblyUpdate,
  260. LPWSTR pwzDisplayName, LPWSTR pwzUrl, IManifestInfo *pSubscriptionInfo)
  261. {
  262. HRESULT hr = S_OK;
  263. MAKE_ERROR_MACROS_STATIC(hr);
  264. DWORD *pdw = NULL;
  265. BOOL *pb = NULL;
  266. DWORD dwInterval = 0, dwUnit = 0, dwEvent = 0;
  267. BOOL bDemandConnection = FALSE;
  268. DWORD dwCB = 0, dwFlag = 0;
  269. IF_FAILED_EXIT(pSubscriptionInfo->Get(MAN_INFO_SUBSCRIPTION_SYNCHRONIZE_INTERVAL, (LPVOID *)&pdw, &dwCB, &dwFlag));
  270. IF_FALSE_EXIT(pdw != NULL, E_UNEXPECTED);
  271. dwInterval = *pdw;
  272. SAFEDELETEARRAY(pdw);
  273. IF_FAILED_EXIT(pSubscriptionInfo->Get(MAN_INFO_SUBSCRIPTION_INTERVAL_UNIT, (LPVOID *)&pdw, &dwCB, &dwFlag));
  274. IF_FALSE_EXIT(pdw != NULL, E_UNEXPECTED);
  275. dwUnit = *pdw;
  276. SAFEDELETEARRAY(pdw);
  277. IF_FAILED_EXIT(pSubscriptionInfo->Get(MAN_INFO_SUBSCRIPTION_SYNCHRONIZE_EVENT, (LPVOID *)&pdw, &dwCB, &dwFlag));
  278. IF_FALSE_EXIT(pdw != NULL, E_UNEXPECTED);
  279. dwEvent = *pdw;
  280. SAFEDELETEARRAY(pdw);
  281. IF_FAILED_EXIT(pSubscriptionInfo->Get(MAN_INFO_SUBSCRIPTION_EVENT_DEMAND_CONNECTION, (LPVOID *)&pb, &dwCB, &dwFlag));
  282. IF_FALSE_EXIT(pb != NULL, E_UNEXPECTED);
  283. bDemandConnection = *pb;
  284. SAFEDELETEARRAY(pb);
  285. IF_FAILED_EXIT(pAssemblyUpdate->RegisterAssemblySubscriptionEx(pwzDisplayName,
  286. pwzUrl, dwInterval, dwUnit, dwEvent, bDemandConnection));
  287. exit:
  288. return hr;
  289. }
  290. // ----------------------------------------------------------------------------
  291. // BUGBUG hacky should move this from extricon.cpp to util.cpp and declare in project.hpp
  292. extern LONG GetRegKeyValue(HKEY hkeyParent, PCWSTR pcwzSubKey,
  293. PCWSTR pcwzValue, PDWORD pdwValueType,
  294. PBYTE pbyteBuf, PDWORD pdwcbBufLen);
  295. // ISSUE-2002/03/30-felixybc Temp read subscription info code
  296. // note: replace this with generic subscription info stored -> IManifestInfo type == MAN_INFO_SUBSCRIPTION
  297. // return: S_OK - success
  298. // error - error or missing reg key or reg value type not DWORD
  299. HRESULT
  300. CheckSubscribedWithEventSync(LPASSEMBLY_IDENTITY pAsmId, DWORD* pdwEvent)
  301. {
  302. // copied from service\server\update.cpp
  303. #define WZ_SYNC_EVENT L"SyncEvent"
  304. #define REG_KEY_FUSION_SUBS L"Software\\Microsoft\\Fusion\\Installer\\1.0.0.0\\Subscription"
  305. HRESULT hr = S_OK;
  306. MAKE_ERROR_MACROS_STATIC(hr);
  307. DWORD dwType = 0;
  308. DWORD dwValue = -1;
  309. DWORD dwSize = 0;
  310. CString sSubsKey;
  311. LPWSTR pwzName = NULL;
  312. IF_FAILED_EXIT(pAsmId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzName, &dwSize));
  313. IF_FALSE_EXIT(hr == S_OK, E_FAIL);
  314. IF_FAILED_EXIT(sSubsKey.Assign(REG_KEY_FUSION_SUBS));
  315. IF_FAILED_EXIT(sSubsKey.Append(L"\\"));
  316. IF_FAILED_EXIT(sSubsKey.Append(pwzName));
  317. dwSize = sizeof(dwValue);
  318. if (GetRegKeyValue(HKEY_CURRENT_USER,
  319. sSubsKey._pwz, WZ_SYNC_EVENT,
  320. &dwType, (PBYTE) &dwValue, &dwSize)
  321. == ERROR_SUCCESS)
  322. {
  323. *pdwEvent = dwValue;
  324. hr = S_OK;
  325. }
  326. else
  327. {
  328. hr = GetLastWin32Error();
  329. }
  330. exit:
  331. SAFEDELETEARRAY(pwzName);
  332. return hr;
  333. }
  334. // ----------------------------------------------------------------------------
  335. // ---------------------------------------------------------------------------
  336. // CreateActivator
  337. // ---------------------------------------------------------------------------
  338. STDAPI
  339. CreateActivator(
  340. LPACTIVATOR *ppActivator,
  341. CDebugLog * pDbgLog,
  342. DWORD dwFlags)
  343. {
  344. HRESULT hr = S_OK;
  345. MAKE_ERROR_MACROS_STATIC(hr);
  346. CActivator *pAct = NULL;
  347. pAct = new(CActivator) (pDbgLog);
  348. IF_ALLOC_FAILED_EXIT(pAct);
  349. exit:
  350. *ppActivator = pAct;//static_cast<IActivator*> (pAct);
  351. return hr;
  352. }
  353. // ---------------------------------------------------------------------------
  354. // ctor
  355. // ---------------------------------------------------------------------------
  356. CActivator::CActivator(CDebugLog * pDbgLog)
  357. : _dwSig('vtca'), _cRef(1), _hr(S_OK),
  358. _pManImport(NULL), _pAsmId(NULL), _pAppInfo(NULL),
  359. _pManEmit(NULL), _pwzAppRootDir(NULL), _pwzAppManifestPath(NULL),
  360. _pwzCodebase(NULL), _dwManifestType(MANIFEST_TYPE_UNKNOWN),
  361. _bIs1stTimeInstall(FALSE), _bIsCheckingRequiredUpdate(FALSE),
  362. #ifdef DEVMODE
  363. _bIsDevMode(FALSE),
  364. #endif
  365. _pSecurityMgr(NULL), _hrManEmit(S_OK), _ptPlatform(NULL),
  366. _dwMissingPlatform(0)
  367. {
  368. _pDbgLog = pDbgLog;
  369. if(_pDbgLog)
  370. _pDbgLog->AddRef();
  371. }
  372. // ---------------------------------------------------------------------------
  373. // dtor
  374. // ---------------------------------------------------------------------------
  375. CActivator::~CActivator()
  376. {
  377. if (_ptPlatform)
  378. {
  379. for (DWORD dw = 0; dw < _dwMissingPlatform; dw++)
  380. {
  381. SAFEDELETEARRAY((_ptPlatform[dw]).pwzName);
  382. SAFEDELETEARRAY((_ptPlatform[dw]).pwzURL);
  383. }
  384. SAFEDELETEARRAY(_ptPlatform);
  385. }
  386. SAFERELEASE(_pSecurityMgr);
  387. SAFERELEASE(_pManEmit);
  388. SAFERELEASE(_pAsmId);
  389. SAFERELEASE(_pAppInfo);
  390. SAFERELEASE(_pManImport);
  391. SAFERELEASE(_pDbgLog);
  392. SAFEDELETEARRAY(_pwzAppManifestPath);
  393. SAFEDELETEARRAY(_pwzAppRootDir);
  394. SAFEDELETEARRAY(_pwzCodebase);
  395. }
  396. // ---------------------------------------------------------------------------
  397. // CActivator::Initialize
  398. //
  399. // pwzFileURL can be NULL
  400. // ---------------------------------------------------------------------------
  401. HRESULT CActivator::Initialize(LPCWSTR pwzFilePath, LPCWSTR pwzFileURL)
  402. {
  403. IManifestInfo *pDependAsmInfo = NULL;
  404. DWORD dwCount, dwFlag = 0;
  405. IF_NULL_EXIT(pwzFilePath, E_INVALIDARG);
  406. if (pwzFileURL != NULL)
  407. IF_FAILED_EXIT(_sWebManifestURL.Assign((LPWSTR)pwzFileURL));
  408. // valid start conditions to invoke this function, passing
  409. // 1. path to desktop manifest (install redirect to subscription manifest on server)
  410. // 2. path to desktop manifest (install redirect to applicaion manifest on server)
  411. // 3. path to application manifest (no install, run from source)
  412. // 4. URL to subscription manifest on server
  413. // 5. URL to application manifest on server
  414. if (FAILED(_hr=CreateAssemblyManifestImport(&_pManImport, pwzFilePath, _pDbgLog, 0)))
  415. {
  416. Msg(L"Error in loading and parsing the manifest file.");
  417. goto exit;
  418. }
  419. IF_FAILED_EXIT(_pManImport->ReportManifestType(&_dwManifestType));
  420. if (_dwManifestType == MANIFEST_TYPE_UNKNOWN)
  421. {
  422. Msg(L"This manifest does not have a known format type.");
  423. _hr = E_ABORT;
  424. goto exit;
  425. }
  426. // allow only valid start conditions
  427. if (_sWebManifestURL._cc != 0 &&
  428. _dwManifestType != MANIFEST_TYPE_SUBSCRIPTION &&
  429. _dwManifestType != MANIFEST_TYPE_APPLICATION)
  430. {
  431. Msg(L"Not supported: URL pointing to a desktop manifest.");
  432. _hr = E_ABORT;
  433. goto exit;
  434. }
  435. if (_sWebManifestURL._cc == 0 &&
  436. _dwManifestType != MANIFEST_TYPE_DESKTOP &&
  437. _dwManifestType != MANIFEST_TYPE_APPLICATION)
  438. {
  439. Msg(L"This manifest does not have the proper format and cannot be used to start an application.");
  440. _hr = E_ABORT;
  441. goto exit;
  442. }
  443. // get data from the manifest file
  444. if (_dwManifestType != MANIFEST_TYPE_SUBSCRIPTION)
  445. {
  446. if (FAILED(_hr=_pManImport->GetAssemblyIdentity(&_pAsmId)))
  447. {
  448. Msg(L"This manifest does not have the proper format and contains no assembly identity.");
  449. goto exit;
  450. }
  451. }
  452. if (_dwManifestType != MANIFEST_TYPE_APPLICATION)
  453. {
  454. // BUGBUG: hardcoded index '0'
  455. IF_FAILED_EXIT(_pManImport->GetNextAssembly(0, &pDependAsmInfo));
  456. if (pDependAsmInfo)
  457. {
  458. if (_dwManifestType == MANIFEST_TYPE_SUBSCRIPTION)
  459. #ifdef DEVMODE
  460. {
  461. #endif
  462. pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_ID, (LPVOID *)&_pAsmId, &dwCount, &dwFlag);
  463. #ifdef DEVMODE
  464. DWORD *pdw = NULL;
  465. // is it devMode?
  466. IF_FAILED_EXIT(pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_TYPE, (LPVOID *)&pdw, &dwCount, &dwFlag));
  467. IF_FALSE_EXIT(pdw != NULL, E_UNEXPECTED);
  468. if (*pdw == DEPENDENT_ASM_INSTALL_TYPE_DEVSYNC)
  469. _bIsDevMode = TRUE;
  470. SAFEDELETEARRAY(pdw);
  471. }
  472. #endif
  473. pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_CODEBASE, (LPVOID *)&_pwzCodebase, &dwCount, &dwFlag);
  474. }
  475. if (!_pAsmId || !_pwzCodebase)
  476. {
  477. Msg(L"This subscription manifest contains no dependent assembly identity or a subscription codebase.");
  478. _hr = E_FAIL;
  479. goto exit;
  480. }
  481. }
  482. else
  483. {
  484. if (_sWebManifestURL._cc != 0)
  485. {
  486. // if URL->app manifest (case 5), codebase is that URL
  487. // note: if path->app manifest (case 3), this does NOT apply
  488. // BUGBUG: HACK: this implies re-download of the app manifest. pref?
  489. size_t ccCodebase = wcslen(pwzFileURL)+1;
  490. _pwzCodebase = new WCHAR[ccCodebase];
  491. IF_ALLOC_FAILED_EXIT(_pwzCodebase);
  492. memcpy(_pwzCodebase, pwzFileURL, ccCodebase * sizeof(WCHAR));
  493. }
  494. }
  495. if (_sWebManifestURL._cc == 0 &&
  496. _dwManifestType == MANIFEST_TYPE_APPLICATION)
  497. {
  498. // run from source
  499. // set _pwzAppRootDir, _pwzAppManifestPath
  500. CString sManifestFilePath;
  501. CString sManifestFileDir;
  502. IF_FAILED_EXIT(sManifestFilePath.Assign(pwzFilePath));
  503. IF_FAILED_EXIT(sManifestFileDir.Assign(sManifestFilePath));
  504. IF_FAILED_EXIT(sManifestFileDir.RemoveLastElement());
  505. IF_FAILED_EXIT(sManifestFileDir.Append(L"\\"));
  506. IF_FAILED_EXIT(sManifestFileDir.ReleaseOwnership(&_pwzAppRootDir));
  507. IF_FAILED_EXIT(sManifestFilePath.ReleaseOwnership(&_pwzAppManifestPath));
  508. }
  509. exit:
  510. SAFERELEASE(pDependAsmInfo)
  511. return _hr;
  512. }
  513. // ---------------------------------------------------------------------------
  514. // CActivator::Process
  515. // ---------------------------------------------------------------------------
  516. HRESULT CActivator::Process()
  517. {
  518. LPWSTR pwzDesktopManifestTempPath = NULL;
  519. DWORD dwCount = 0, dwFlag = 0;
  520. IF_NULL_EXIT(_pAsmId, E_UNEXPECTED); // not initialized
  521. if (_sWebManifestURL._cc == 0 &&
  522. _dwManifestType == MANIFEST_TYPE_APPLICATION)
  523. {
  524. // run from source
  525. if (FAILED(_hr=_pManImport->GetManifestApplicationInfo(&_pAppInfo)) || _hr==S_FALSE)
  526. {
  527. // can't continue without this...
  528. _hr = E_ABORT;
  529. Msg(L"The application manifest does not have the shell information and cannot be used to start an application.");
  530. goto exit;
  531. }
  532. // bypass other processing
  533. // _pwzAppRootDir, _pwzAppManifestPath are already set in Initialize
  534. _hr = S_FALSE;
  535. goto exit;
  536. }
  537. // search cache, download/install if necessary
  538. // BUGBUG: UGLY - pManImport & pwzFileURL are needed only for desktop manifest stuff.
  539. // This and below subscription registration should be cleaned up once assemblydownload is restructured.
  540. /// (see checks for "_sWebManifestURL._cc != 0 && dwManifestType == MANIFEST_TYPE_SUBSCRIPTION")
  541. IF_FAILED_EXIT(ResolveAndInstall(&pwzDesktopManifestTempPath));
  542. // register for updates
  543. if (_bIs1stTimeInstall && _sWebManifestURL._cc != 0 && _dwManifestType == MANIFEST_TYPE_SUBSCRIPTION)
  544. {
  545. // note: this code must be identical to what assemblydownload.cpp DoCacheUpdate() does!
  546. LPWSTR pwzName = NULL;
  547. if ((_hr = _pAsmId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzName, &dwCount)) != S_OK)
  548. {
  549. ShowError(_hr, L"Error in retrieving assembly name. Cannot register subscription for updates.");
  550. // note: This- no asm name- should not be allowed!
  551. }
  552. else
  553. {
  554. IAssemblyUpdate *pAssemblyUpdate = NULL;
  555. // register for updates
  556. _hr = CoCreateInstance(CLSID_CAssemblyUpdate, NULL, CLSCTX_LOCAL_SERVER,
  557. IID_IAssemblyUpdate, (void**)&pAssemblyUpdate);
  558. if (SUCCEEDED(_hr))
  559. {
  560. IManifestInfo* pSubsInfo = NULL;
  561. if (SUCCEEDED(_hr = _pManImport->GetSubscriptionInfo(&pSubsInfo)))
  562. {
  563. _hr = RegisterAssemblySubscriptionEx(pAssemblyUpdate, pwzName,
  564. _sWebManifestURL._pwz, pSubsInfo);
  565. pSubsInfo->Release();
  566. }
  567. pAssemblyUpdate->Release();
  568. }
  569. if (FAILED(_hr))
  570. {
  571. ShowError(_hr, L"Error in update services. Cannot register subscription for updates.");
  572. //goto exit; do not terminate!fail gracefully
  573. }
  574. // BUGBUG: need a way to recover from this and register later
  575. delete[] pwzName;
  576. }
  577. }
  578. // CVersionManagement's RegisterInstall() below requires a manifest import to an application manifest
  579. if (_sWebManifestURL._cc != 0 || pwzDesktopManifestTempPath)
  580. {
  581. // if URL, crack the app manifest to get shell state info
  582. // BUGBUG: if URL->app manifest (case 5), pwzFilePath is a copy and is already cracked-so no need in that case?
  583. _pManImport->Release();
  584. if (FAILED(_hr=CreateAssemblyManifestImport(&_pManImport, _pwzAppManifestPath, _pDbgLog, 0)))
  585. {
  586. Msg(L"Error in loading and parsing the application manifest file.");
  587. goto exit;
  588. }
  589. }
  590. if (FAILED(_hr=_pManImport->GetManifestApplicationInfo(&_pAppInfo)) || _hr==S_FALSE)
  591. {
  592. // can't continue without this...
  593. _hr = E_ABORT;
  594. Msg(L"This manifest does not have the shell information and cannot be used to start an application.");
  595. goto exit;
  596. }
  597. // copy desktop manifest, if present
  598. // even if the app deployment can possibly be broken and will not execute
  599. if (pwzDesktopManifestTempPath)
  600. {
  601. LPWSTR pwzFriendlyName = NULL;
  602. // BUGBUG: should get status on the desktop manifest generated, not copy in some cases, eg. file size == 0 or XMLDOM errors
  603. // use _hrManEmit to check
  604. if (FAILED(_hr = _pAppInfo->Get(MAN_INFO_APPLICATION_FRIENDLYNAME, (LPVOID *)&pwzFriendlyName, &dwCount, &dwFlag)))
  605. {
  606. Msg(L"This application does not have a friendly name specified, no desktop manifest is generated and the installation is not registered.");
  607. }
  608. else
  609. {
  610. // BUGBUG: should somehow continue even w/o a friendly name? name conflict?
  611. IF_FALSE_EXIT(pwzFriendlyName != NULL, E_UNEXPECTED);
  612. LPWSTR pwzDesktopManifestPath = NULL;
  613. _hr = CopyToUSStartMenu(pwzDesktopManifestTempPath, pwzFriendlyName, FALSE, &pwzDesktopManifestPath);
  614. delete[] pwzFriendlyName;
  615. // note: if a file with the same name already exists, the desktop manifest is not copied over
  616. // and so, this existing file will not be deleted when this app is uninstalled.
  617. // ISSUE-2002/03/27-felixybc finalize on what to do if file already exists - this could be a name squatting attack
  618. IF_FALSE_EXIT(!(FAILED(_hr) && _hr != HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)), _hr); // _hr from CopyToUSStartMenu() above...
  619. LPVERSION_MANAGEMENT pVerMan = NULL;
  620. if (SUCCEEDED(_hr = CreateVersionManagement(&pVerMan, 0)))
  621. {
  622. HRESULT hrVerMan = S_OK;
  623. if (FAILED(hrVerMan = pVerMan->RegisterInstall(_pManImport, pwzDesktopManifestPath)))
  624. {
  625. ShowError(hrVerMan, L"Error registering installation. Uninstall of this application cannot be done in Add/Remove Programs.");
  626. //goto exit; did not change _hr
  627. }
  628. }
  629. delete [] pwzDesktopManifestPath;
  630. if (pVerMan)
  631. pVerMan->Release();
  632. // _hr from CreateVersionManagement() above...
  633. IF_FAILED_EXIT(_hr);
  634. }
  635. }
  636. exit:
  637. if (pwzDesktopManifestTempPath)
  638. {
  639. // delete the temp file for desktop manifest
  640. BOOL bReturn = DeleteFile(pwzDesktopManifestTempPath);
  641. if (SUCCEEDED(_hr) && !bReturn)
  642. _hr = GetLastWin32Error(); // else ignore return value
  643. delete[] pwzDesktopManifestTempPath;
  644. }
  645. return _hr;
  646. }
  647. // ---------------------------------------------------------------------------
  648. // CActivator::Execute
  649. // ---------------------------------------------------------------------------
  650. HRESULT CActivator::Execute()
  651. {
  652. LPWSTR pwzEntrypoint = NULL;
  653. LPWSTR pwzType = NULL;
  654. LPWSTR pwzAssemblyName = NULL;
  655. LPWSTR pwzAssemblyClass = NULL;
  656. LPWSTR pwzAssemblyMethod = NULL;
  657. LPWSTR pwzAssemblyArgs = NULL;
  658. LPWSTR pwzCmdLine = NULL;
  659. int iAppType = 0;
  660. DWORD dwCount, dwFlag = 0;
  661. IF_NULL_EXIT(_pAppInfo, E_UNEXPECTED); // not processed
  662. // execute the app
  663. IF_FAILED_EXIT(_pAppInfo->Get(MAN_INFO_APPLICATION_ENTRYPOINT, (LPVOID *)&pwzEntrypoint, &dwCount, &dwFlag));
  664. if(pwzEntrypoint && *pwzEntrypoint == L'\0')
  665. SAFEDELETEARRAY(pwzEntrypoint);
  666. if (FAILED(_hr = _pAppInfo->Get(MAN_INFO_APPLICATION_ENTRYIMAGETYPE, (LPVOID *)&pwzType, &dwCount, &dwFlag)))
  667. {
  668. Msg(L"Error in retrieving application type. Cannot continue.");
  669. goto exit;
  670. }
  671. IF_FALSE_EXIT(pwzType != NULL, E_UNEXPECTED);
  672. IF_FAILED_EXIT(FusionCompareString(pwzType, WZ_TYPE_DOTNET, 0));
  673. if (_hr == S_OK)
  674. iAppType = TYPE_DOTNET;
  675. else
  676. {
  677. IF_FAILED_EXIT(FusionCompareString(pwzType, WZ_TYPE_WIN32, 0));
  678. if (_hr == S_OK)
  679. iAppType = TYPE_WIN32;
  680. else
  681. {
  682. IF_FAILED_EXIT(FusionCompareString(pwzType, WZ_TYPE_AVALON, 0));
  683. if (_hr == S_OK)
  684. iAppType = TYPE_AVALON;
  685. else
  686. {
  687. IF_FAILED_EXIT(FusionCompareString(pwzType, WZ_TYPE_CONSOLE, 0));
  688. if (_hr == S_OK)
  689. iAppType = TYPE_CONSOLE;
  690. else
  691. {
  692. // unknown type
  693. Msg(L"Unsupported application type. Cannot continue.");
  694. _hr = E_ABORT;
  695. goto exit;
  696. }
  697. }
  698. }
  699. }
  700. if( (iAppType == TYPE_CONSOLE) || (iAppType == TYPE_WIN32) )
  701. {
  702. if(!pwzEntrypoint)
  703. {
  704. Msg(L"Entry point not specified. Could not run this application.");
  705. goto exit;
  706. }
  707. size_t ccWorkingDir = wcslen(_pwzAppRootDir);
  708. size_t ccEntryPoint = wcslen(pwzEntrypoint)+1;
  709. pwzCmdLine = new WCHAR[ccWorkingDir+ccEntryPoint]; // 2 strings + '\0'
  710. IF_ALLOC_FAILED_EXIT(pwzCmdLine);
  711. memcpy(pwzCmdLine, _pwzAppRootDir, ccWorkingDir * sizeof(WCHAR));
  712. memcpy(pwzCmdLine+ccWorkingDir, pwzEntrypoint, ccEntryPoint * sizeof(WCHAR));
  713. // check if the entry point is in cache or not
  714. BOOL bExists = FALSE;
  715. IF_FAILED_EXIT(CheckFileExistence(pwzCmdLine, &bExists));
  716. if (!bExists)
  717. {
  718. Msg(L"Entry point does not exist. Cannot continue.");
  719. _hr = E_ABORT;
  720. goto exit;
  721. }
  722. }
  723. if (iAppType == TYPE_DOTNET || iAppType == TYPE_AVALON)
  724. {
  725. #if 0
  726. DWORD dwZone;
  727. #endif
  728. // ISSUE - note: ndphost should do the checking below instead
  729. IF_FAILED_EXIT(_pAppInfo->Get(MAN_INFO_APPLICATION_ASSEMBLYNAME,
  730. (LPVOID *)&pwzAssemblyName, &dwCount, &dwFlag));
  731. if(pwzAssemblyName && *pwzAssemblyName == L'\0')
  732. SAFEDELETEARRAY(pwzAssemblyName);
  733. IF_FAILED_EXIT(_pAppInfo->Get(MAN_INFO_APPLICATION_ASSEMBLYCLASS,
  734. (LPVOID *)&pwzAssemblyClass, &dwCount, &dwFlag));
  735. if(pwzAssemblyClass && *pwzAssemblyClass == L'\0')
  736. SAFEDELETEARRAY(pwzAssemblyClass);
  737. IF_FAILED_EXIT(_pAppInfo->Get(MAN_INFO_APPLICATION_ASSEMBLYMETHOD,
  738. (LPVOID *)&pwzAssemblyMethod, &dwCount, &dwFlag));
  739. if(pwzAssemblyMethod && *pwzAssemblyMethod == L'\0')
  740. SAFEDELETEARRAY(pwzAssemblyMethod);
  741. IF_FAILED_EXIT(_pAppInfo->Get(MAN_INFO_APPLICATION_ASSEMBLYARGS,
  742. (LPVOID *)&pwzAssemblyArgs, &dwCount, &dwFlag));
  743. if(pwzAssemblyArgs && *pwzAssemblyArgs == L'\0')
  744. SAFEDELETEARRAY(pwzAssemblyArgs);
  745. if(!pwzAssemblyName)
  746. {
  747. Msg(L"The application manifest does not have an activation assembly.");
  748. _hr = E_ABORT;
  749. goto exit;
  750. }
  751. if(pwzEntrypoint)
  752. {
  753. Msg(L"Entrypoint cannot be specified for managed code application types.");
  754. _hr = E_ABORT;
  755. goto exit;
  756. }
  757. if((pwzAssemblyClass && !pwzAssemblyMethod)
  758. || (!pwzAssemblyClass && pwzAssemblyMethod)
  759. || (pwzAssemblyArgs && !pwzAssemblyClass))
  760. {
  761. Msg(L"Both AssemblyClass and AssemblyMethod must be specified.");
  762. _hr = E_ABORT;
  763. goto exit;
  764. }
  765. // note: at this point the codebase can be: URL to app manifest _or_ URL to subscription manifest
  766. // (depends on how 1st time install is started with)
  767. if ((_sWebManifestURL._cc != 0 ||
  768. _dwManifestType != MANIFEST_TYPE_APPLICATION) && // run from source
  769. _pwzCodebase == NULL)
  770. {
  771. Msg(L"This application does not have a codebase specified. Cannot continue to execute .NetAssembly.");
  772. _hr = E_ABORT;
  773. goto exit;
  774. }
  775. #if 0
  776. if (_pSecurityMgr == NULL)
  777. {
  778. // lazy init.
  779. _hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER,
  780. IID_IInternetSecurityManager, (void**)&_pSecurityMgr);
  781. if (FAILED(_hr))
  782. _pSecurityMgr = NULL;
  783. IF_FAILED_EXIT(_hr);
  784. }
  785. // BUGBUG?: shouldn't use codebase from ref manifest to set zone?
  786. IF_FAILED_EXIT(_pSecurityMgr->MapUrlToZone(_pwzCodebase, &dwZone, 0));
  787. #endif
  788. #if 0 // old code
  789. // BUGBUG: hack for avalon (bug # 875)
  790. SetCurrentDirectory(_pwzAppRootDir);
  791. try
  792. {
  793. IAsmExecutePtr pIAsmExecute(__uuidof(AsmExecute));
  794. long lRetVal = -1;
  795. long lFlag = 0x3;
  796. LPWSTR pwzArg = NULL;
  797. // BUGBUG: change AsmExec if it's no longer needed to send commandline argument
  798. // clean up interface
  799. if (iAppType == TYPE_AVALON)
  800. {
  801. // call with manifest file path as a parameter
  802. //pwzArg = pwzAppManifestPath; avalon arg hack
  803. // pass Avalon flag
  804. lFlag = 0x1003;
  805. // BUGBUG: a hack to show debug msg
  806. AllocConsole();
  807. }
  808. //parameters: Codebase/filepath Flag Zone Url Arg
  809. // BUGBUG: DWORD is unsigned and long is signed
  810. _hr = pIAsmExecute->Execute(_bstr_t(pwzCmdLine), lFlag, dwZone, _bstr_t(_pwzCodebase), _bstr_t(pwzArg), &lRetVal);
  811. // BUGBUG: do something about lRetVal
  812. }
  813. catch (_com_error &e)
  814. {
  815. _hr = e.Error();
  816. Msg((LPWSTR)e.ErrorMessage());
  817. }
  818. // BUGBUG: get/display the actual error message
  819. // _hr from Execute() or inside catch(){} above
  820. if (FAILED(_hr))
  821. goto exit;
  822. #else
  823. CString sHostPath;
  824. CString sCommandLine;
  825. // IF_FAILED_EXIT(MakeCommandLine(_pwzAppRootDir, pwzAssemblyName, pwzAssemblyClass, pwzAssemblyMethod, pwzAssemblyArgs, _pwzCodebase, dwZone, sHostPath, sCommandLine));
  826. IF_FAILED_EXIT(MakeCommandLine(_pwzAppManifestPath, _pwzCodebase, sHostPath, sCommandLine));
  827. IF_FAILED_EXIT(RunCommand(sHostPath._pwz, sCommandLine._pwz, _pwzAppRootDir, FALSE));
  828. #endif
  829. }
  830. else if (iAppType == TYPE_WIN32)
  831. {
  832. // BUGBUG: Win32 app has no sandboxing... use SAFER?
  833. // BUGBUG: start directory: what if the exe is in a subdir of pwzAppRootDir?
  834. // CreateProcess dislike having the filename in the path for the start directory
  835. if (FAILED(_hr=RunCommand(pwzCmdLine, NULL, _pwzAppRootDir, FALSE)))
  836. {
  837. ShowError(_hr, L"Win32Executable: Create process error.");
  838. _hr = E_ABORT;
  839. goto exit;
  840. }
  841. }
  842. else if (iAppType == TYPE_CONSOLE)
  843. {
  844. // BUGBUG: Win32 app has no sandboxing... use SAFER?
  845. // BUGBUG: start directory: what if the exe is in a subdir of pwzAppRootDir?
  846. // CreateProcess dislike having the filename in the path for the start directory
  847. if (FAILED(_hr=RunCommandConsole(pwzCmdLine, _pwzAppRootDir, FALSE)))
  848. {
  849. ShowError(_hr, L"Win32Console: Create process error.");
  850. _hr = E_ABORT;
  851. goto exit;
  852. }
  853. }
  854. //else
  855. // unknown type....
  856. exit:
  857. SAFEDELETEARRAY(pwzEntrypoint);
  858. SAFEDELETEARRAY(pwzType);
  859. SAFEDELETEARRAY(pwzCmdLine);
  860. SAFEDELETEARRAY(pwzAssemblyName);
  861. SAFEDELETEARRAY(pwzAssemblyClass);
  862. SAFEDELETEARRAY(pwzAssemblyMethod);
  863. SAFEDELETEARRAY(pwzAssemblyArgs);
  864. return _hr;
  865. }
  866. // ---------------------------------------------------------------------------
  867. // CActivator::OnProgress
  868. // ---------------------------------------------------------------------------
  869. HRESULT CActivator::OnProgress(DWORD dwNotification, HRESULT hrNotification,
  870. LPCWSTR szNotification, DWORD dwProgress,
  871. DWORD dwProgressMax, IUnknown *pUnk)
  872. {
  873. LPASSEMBLY_MANIFEST_IMPORT pManifestImport = NULL;
  874. LPASSEMBLY_IDENTITY pAsmId = NULL;
  875. IManifestInfo *pDependAsmInfo = NULL;
  876. // only handles notification it cares
  877. if (dwNotification == ASM_NOTIFICATION_SUBSCRIPTION_MANIFEST ||
  878. dwNotification == ASM_NOTIFICATION_APPLICATION_MANIFEST)
  879. {
  880. // szNotification == URL to manifest
  881. IF_NULL_EXIT(szNotification, E_INVALIDARG);
  882. // pUnk == manifest import of manifest
  883. IF_FAILED_EXIT(pUnk->QueryInterface(IID_IAssemblyManifestImport, (LPVOID*) &pManifestImport));
  884. if (dwNotification == ASM_NOTIFICATION_SUBSCRIPTION_MANIFEST)
  885. {
  886. LPWSTR pwzName = NULL;
  887. DWORD dwCount = 0;
  888. IF_FAILED_EXIT(_pAsmId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzName, &dwCount));
  889. {
  890. IAssemblyUpdate *pAssemblyUpdate = NULL;
  891. // register for updates
  892. _hr = CoCreateInstance(CLSID_CAssemblyUpdate, NULL, CLSCTX_LOCAL_SERVER,
  893. IID_IAssemblyUpdate, (void**)&pAssemblyUpdate);
  894. if (SUCCEEDED(_hr))
  895. {
  896. IManifestInfo* pSubsInfo = NULL;
  897. if (SUCCEEDED(_hr = pManifestImport->GetSubscriptionInfo(&pSubsInfo)))
  898. {
  899. _hr = RegisterAssemblySubscriptionEx(pAssemblyUpdate, pwzName,
  900. (LPWSTR) szNotification, pSubsInfo);
  901. pSubsInfo->Release();
  902. }
  903. pAssemblyUpdate->Release();
  904. }
  905. delete[] pwzName;
  906. // do not fail... should show UI?
  907. if (FAILED(_hr))
  908. _hr = S_OK;
  909. // goto exit;
  910. // BUGBUG: need a way to recover from this and register later
  911. }
  912. // export dependency/dependentassembly/assemblyIdentity & subscription
  913. if (_pManEmit)
  914. _hrManEmit = _pManEmit->SetDependencySubscription(pManifestImport, (LPWSTR)szNotification);
  915. else if (_bIsCheckingRequiredUpdate)
  916. {
  917. // if _bIsCheckingRequiredUpdate, _pManEmit == NULL,
  918. // and must be downloading subscription manifest
  919. // check if required update
  920. BOOL bIsToDownload = FALSE; // default is normal
  921. // BUGBUG: hardcoded index '0'
  922. IF_FAILED_EXIT(pManifestImport->GetNextAssembly(0, &pDependAsmInfo));
  923. IF_FALSE_EXIT(_hr == S_OK, E_FAIL);
  924. if (pDependAsmInfo)
  925. {
  926. LPASSEMBLY_CACHE_IMPORT pCacheImport = NULL;
  927. DWORD dwFlag= 0;
  928. //already has it?
  929. IF_FAILED_EXIT(pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_ID, (LPVOID *)&pAsmId, &dwCount, &dwFlag));
  930. IF_FALSE_EXIT(pAsmId != NULL, E_UNEXPECTED);
  931. IF_FAILED_EXIT(CreateAssemblyCacheImport(&pCacheImport, pAsmId, CACHEIMP_CREATE_RETRIEVE));
  932. if (_hr == S_FALSE)
  933. {
  934. // no, does not have it
  935. DWORD *pdw = NULL;
  936. // is it required?
  937. IF_FAILED_EXIT(pDependAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_TYPE, (LPVOID *)&pdw, &dwCount, &dwFlag));
  938. IF_FALSE_EXIT(pdw != NULL, E_UNEXPECTED);
  939. if (*pdw == DEPENDENT_ASM_INSTALL_TYPE_REQUIRED)
  940. bIsToDownload = TRUE; // yes, it is required
  941. #ifdef DEVMODE
  942. else if (*pdw == DEPENDENT_ASM_INSTALL_TYPE_DEVSYNC)
  943. bIsToDownload = TRUE; // yes, it is devsync, assume required
  944. #endif
  945. SAFEDELETEARRAY(pdw);
  946. }
  947. SAFERELEASE(pCacheImport);
  948. }
  949. if (!bIsToDownload)
  950. _hr = E_ABORT; // signal abort the download
  951. }
  952. }
  953. else if (dwNotification == ASM_NOTIFICATION_APPLICATION_MANIFEST)
  954. {
  955. // check for dependent platforms
  956. IF_FAILED_EXIT(CheckPlatformRequirementsEx(pManifestImport, _pDbgLog, &_dwMissingPlatform, &_ptPlatform));
  957. IF_TRUE_EXIT((_dwMissingPlatform > 0), E_ABORT);
  958. if (_pManEmit)
  959. {
  960. // export assemblyIdentity & application
  961. // ignore failure
  962. _hrManEmit = _pManEmit->ImportManifestInfo(pManifestImport);
  963. // export dependency/dependentassembly/assemblyIdentity & subscription
  964. // ignore failure, if already called once this is ignored
  965. _hrManEmit = _pManEmit->SetDependencySubscription(pManifestImport, (LPWSTR)szNotification);
  966. }
  967. }
  968. }
  969. else
  970. _hr = S_OK;
  971. exit:
  972. SAFERELEASE(pAsmId);
  973. SAFERELEASE(pDependAsmInfo);
  974. SAFERELEASE(pManifestImport);
  975. return _hr;
  976. }
  977. // IUnknown methods
  978. // ---------------------------------------------------------------------------
  979. // CActivator::QI
  980. // ---------------------------------------------------------------------------
  981. STDMETHODIMP
  982. CActivator::QueryInterface(REFIID riid, void** ppvObj)
  983. {
  984. if ( IsEqualIID(riid, IID_IUnknown)
  985. // || IsEqualIID(riid, IID_IActivator)
  986. )
  987. {
  988. *ppvObj = this; //static_cast<IActivator*> (this);
  989. AddRef();
  990. return S_OK;
  991. }
  992. else
  993. {
  994. *ppvObj = NULL;
  995. return E_NOINTERFACE;
  996. }
  997. }
  998. // ---------------------------------------------------------------------------
  999. // CActivator::AddRef
  1000. // ---------------------------------------------------------------------------
  1001. STDMETHODIMP_(ULONG)
  1002. CActivator::AddRef()
  1003. {
  1004. return InterlockedIncrement ((LONG*) &_cRef);
  1005. }
  1006. // ---------------------------------------------------------------------------
  1007. // CActivator::Release
  1008. // ---------------------------------------------------------------------------
  1009. STDMETHODIMP_(ULONG)
  1010. CActivator::Release()
  1011. {
  1012. ULONG lRet = InterlockedDecrement ((LONG*) &_cRef);
  1013. if (!lRet)
  1014. delete this;
  1015. return lRet;
  1016. }
  1017. // ----------------------------------------------------------------------------
  1018. HRESULT CreateTempFile(LPCWSTR pcwzPrefix, LPWSTR *ppwzFilePath)
  1019. {
  1020. #define DEFAULT_PATH_LEN MAX_PATH
  1021. #define TEMP_FILE_NAME_LEN sizeof("preuuuu.TMP") // from msdn
  1022. HRESULT hr = S_OK;
  1023. MAKE_ERROR_MACROS_STATIC(hr);
  1024. LPWSTR pwzTempPath = NULL;
  1025. LPWSTR pwzTempFilePath = NULL;
  1026. IF_NULL_EXIT(pcwzPrefix, E_INVALIDARG);
  1027. IF_NULL_EXIT(ppwzFilePath, E_INVALIDARG);
  1028. *ppwzFilePath = NULL;
  1029. IF_FALSE_EXIT(lstrlen(pcwzPrefix) == 3, E_INVALIDARG);
  1030. // assemble temp file path
  1031. IF_ALLOC_FAILED_EXIT(pwzTempPath = new WCHAR[DEFAULT_PATH_LEN]);
  1032. // ISSUE-2002/03/31-felixybc GetTempPath can overrun the buffer?
  1033. DWORD dwLen = GetTempPath(DEFAULT_PATH_LEN, pwzTempPath);
  1034. IF_WIN32_FALSE_EXIT(dwLen);
  1035. if (dwLen >= DEFAULT_PATH_LEN)
  1036. {
  1037. // resize, add 1 for terminating null
  1038. IF_FALSE_EXIT(dwLen+1 > dwLen, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW)); // check overflow
  1039. SAFEDELETEARRAY(pwzTempPath);
  1040. IF_ALLOC_FAILED_EXIT(pwzTempPath = new WCHAR[dwLen+1]);
  1041. DWORD dwLenNew = GetTempPath(dwLen+1, pwzTempPath);
  1042. IF_WIN32_FALSE_EXIT(dwLenNew);
  1043. IF_FALSE_EXIT(dwLenNew < dwLen+1, E_FAIL); // why is it still not enough?
  1044. }
  1045. DWORD dwBufLen = lstrlen(pwzTempPath)+1;
  1046. // note: can do a better check here
  1047. IF_FALSE_EXIT(dwBufLen > 1, E_FAIL);
  1048. // allocate buffer large enough for temp path and temp file name
  1049. DWORD dwLenNew = (dwBufLen > DEFAULT_PATH_LEN)? dwBufLen : DEFAULT_PATH_LEN;
  1050. dwLenNew += TEMP_FILE_NAME_LEN;
  1051. // check for overflow
  1052. IF_FALSE_EXIT(dwLenNew > dwBufLen, E_FAIL);
  1053. IF_ALLOC_FAILED_EXIT(pwzTempFilePath = new WCHAR[dwLenNew]);
  1054. // *pwzTempFilePath = L'\0';
  1055. // note: temp file to be deleted by the caller
  1056. IF_WIN32_FALSE_EXIT(GetTempFileName(pwzTempPath, pcwzPrefix, 0, pwzTempFilePath));
  1057. *ppwzFilePath = pwzTempFilePath;
  1058. pwzTempFilePath = NULL;
  1059. exit:
  1060. /* if (FAILED(hr) && pwzTempFilePath != NULL)
  1061. {
  1062. if (*pwzTempFilePath != L'\0')
  1063. {
  1064. // ignore if error deleting the file
  1065. DeleteFile(pwzTempFilePath);
  1066. }
  1067. }*/
  1068. SAFEDELETEARRAY(pwzTempFilePath);
  1069. SAFEDELETEARRAY(pwzTempPath);
  1070. return hr;
  1071. }
  1072. // ---------------------------------------------------------------------------
  1073. // CActivator::ResolveAndInstall
  1074. // note: parameter _pwzCodebase can be NULL
  1075. // must delete if *ppwzDesktopManifestPathName != NULL
  1076. // ---------------------------------------------------------------------------
  1077. HRESULT CActivator::ResolveAndInstall(LPWSTR *ppwzDesktopManifestPathName)
  1078. {
  1079. LPASSEMBLY_CACHE_IMPORT pCacheImport = NULL;
  1080. DWORD dwCC = 0;
  1081. _bIs1stTimeInstall = FALSE;
  1082. // look into the cache
  1083. IF_FAILED_EXIT(CreateAssemblyCacheImport(&pCacheImport, _pAsmId, CACHEIMP_CREATE_RESOLVE_REF));
  1084. // hr from CreateAssemblyCacheImport() above
  1085. // Case 1, cached copy exist
  1086. // _hr == S_OK
  1087. if (_hr == S_OK && _dwManifestType == MANIFEST_TYPE_DESKTOP)
  1088. {
  1089. // BUGBUG: broken if subscribed then run with a desktop manifest generated with URL to app manifest
  1090. // should check and ignore if desktop manifest redirect to applicaion manifest on server
  1091. // as there is no way to check for update/changes in subscription manifest, even if subscribed so
  1092. // correct fix is to use subscription manifest's URL stored
  1093. // check if subscribed with event sync
  1094. DWORD dwSyncEvent = MAN_INFO_SUBSCRIPTION_MAX;
  1095. _hr = CheckSubscribedWithEventSync(_pAsmId, &dwSyncEvent);
  1096. // ISSUE-2002/04/12-felixybc If the value is absent, ERROR_NO_MORE_FILES is returned.
  1097. // Note that dwSyncEvent is unmodified.
  1098. if (_hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES))
  1099. IF_FAILED_EXIT(_hr);
  1100. if (dwSyncEvent == SUBSCRIPTION_SYNC_EVENT_ON_APP_STARTUP)
  1101. {
  1102. LPASSEMBLY_DOWNLOAD pAsmDownload = NULL;
  1103. // event sync onApplicationStartup == required update
  1104. // _pwzCodebase != NULL
  1105. // check policy before download
  1106. IF_FAILED_EXIT(CheckZonePolicy(_pwzCodebase));
  1107. IF_FAILED_EXIT(CreateAssemblyDownload(&pAsmDownload, _pDbgLog, 0));
  1108. _bIsCheckingRequiredUpdate = TRUE;
  1109. // (synchronous & ui & bindsink) download from codebase
  1110. _hr=pAsmDownload->DownloadManifestAndDependencies(_pwzCodebase, this, DOWNLOAD_FLAGS_PROGRESS_UI | DOWNLOAD_FLAGS_NOTIFY_BINDSINK);
  1111. pAsmDownload->Release();
  1112. _bIsCheckingRequiredUpdate = FALSE;
  1113. // hr from DownloadManifestAndDependencies() above
  1114. if (FAILED(_hr))
  1115. {
  1116. if (_hr != E_ABORT)
  1117. {
  1118. HRESULT hrTemp;
  1119. CString sErrMsg;
  1120. if(SUCCEEDED(hrTemp = _pDbgLog->GetLoggedMsgs(0, sErrMsg)))
  1121. {
  1122. hrTemp = sErrMsg.Append(L"Error in file download while checking for required update. Cannot continue.");
  1123. if(SUCCEEDED(hrTemp))
  1124. {
  1125. ShowError(sErrMsg._pwz);
  1126. _hr = E_ABORT;
  1127. }
  1128. }
  1129. }
  1130. goto exit;
  1131. }
  1132. IF_FAILED_EXIT(HandlePlatformCheckResult());
  1133. SAFERELEASE(pCacheImport);
  1134. // either no required update needed, or another version have been completely downloaded at this time...
  1135. // BUGBUG: Determine if abort done by our bindsink when no required update - thus no need to re-create cache import.
  1136. // get cache dir again to ensure running the highest version
  1137. IF_FAILED_EXIT(CreateAssemblyCacheImport(&pCacheImport, _pAsmId, CACHEIMP_CREATE_RESOLVE_REF));
  1138. if (_hr == S_FALSE)
  1139. {
  1140. // should never happen, at least 1 was found before
  1141. Msg(L"No completed cached version found. Possible cache corruption. Cannot continue.");
  1142. _hr = E_ABORT;
  1143. goto exit;
  1144. }
  1145. }
  1146. else
  1147. // if _hr == error, ignore
  1148. _hr = S_OK;
  1149. }
  1150. // Case 2, cached copy (of the referenced version) not exist
  1151. else if (_hr == S_FALSE)
  1152. {
  1153. LPASSEMBLY_DOWNLOAD pAsmDownload = NULL;
  1154. // BUGBUG?: what if it is not a partial ref but there's actually another version installed?
  1155. if (_pwzCodebase == NULL)
  1156. {
  1157. Msg(L"No completed cached version of this application found and this manifest cannot be used to initiate an install. Cannot continue.");
  1158. _hr = E_FAIL;
  1159. goto exit;
  1160. }
  1161. // create temp file name
  1162. IF_FAILED_EXIT(CreateTempFile(L"DMA", ppwzDesktopManifestPathName)); // desktop manifest file
  1163. _bIs1stTimeInstall = TRUE;
  1164. // check policy before download
  1165. IF_FAILED_EXIT(CheckZonePolicy(_pwzCodebase));
  1166. #ifdef DEVMODE
  1167. IF_FAILED_EXIT(CreateAssemblyDownload(&pAsmDownload, _pDbgLog, (_bIsDevMode ? DOWNLOAD_DEVMODE : 0)));
  1168. #else
  1169. IF_FAILED_EXIT(CreateAssemblyDownload(&pAsmDownload, _pDbgLog, 0));
  1170. #endif
  1171. // should generate the desktop manifest file if 1st time install (from mimehandler or not)
  1172. // or even if it subsequently fails
  1173. // ignore error
  1174. _hrManEmit=CreateAssemblyManifestEmit(&_pManEmit, *ppwzDesktopManifestPathName, MANIFEST_TYPE_DESKTOP);
  1175. // BUGBUG: UGLY - _pManImport & _sWebManifestURL._pwz are needed only for desktop manifest stuff.
  1176. // ???
  1177. // This should be cleaned up once assemblydownload is restructured.
  1178. // (see checks for "_sWebManifestURL._cc != 0 && dwManifestType == MANIFEST_TYPE_SUBSCRIPTION")
  1179. if (_sWebManifestURL._cc != 0 && _dwManifestType == MANIFEST_TYPE_SUBSCRIPTION && _pManEmit)
  1180. {
  1181. // export dependency/dependentassembly/assemblyIdentity & subscription
  1182. // ignore failure
  1183. _hrManEmit = _pManEmit->SetDependencySubscription(_pManImport, _sWebManifestURL._pwz);
  1184. }
  1185. //BUGBUG: need ref def matching checks for desktop->subscription->app manifests' ids
  1186. // (synchronous & ui & bindsink) download from codebase
  1187. _hr=pAsmDownload->DownloadManifestAndDependencies(_pwzCodebase, this, DOWNLOAD_FLAGS_PROGRESS_UI | DOWNLOAD_FLAGS_NOTIFY_BINDSINK);
  1188. pAsmDownload->Release();
  1189. if (_pManEmit)
  1190. {
  1191. // write out desktop manifest
  1192. _hrManEmit = _pManEmit->Commit();
  1193. SAFERELEASE(_pManEmit);
  1194. }
  1195. // hr from DownloadManifestAndDependencies() above
  1196. if (FAILED(_hr))
  1197. {
  1198. if (_hr == E_ABORT)
  1199. {
  1200. // Msg(L"File download canceled.");
  1201. }
  1202. else
  1203. {
  1204. HRESULT hrTemp;
  1205. CString sErrMsg;
  1206. if(SUCCEEDED(hrTemp = _pDbgLog->GetLoggedMsgs(0, sErrMsg)))
  1207. {
  1208. hrTemp = sErrMsg.Append(L"Error in file download. Cannot continue.");
  1209. if(SUCCEEDED(hrTemp))
  1210. {
  1211. ShowError(sErrMsg._pwz);
  1212. _hr = E_ABORT;
  1213. }
  1214. }
  1215. }
  1216. goto exit;
  1217. }
  1218. IF_FAILED_EXIT(HandlePlatformCheckResult());
  1219. // another version might have been completed at this time...
  1220. // get cache dir again to ensure running the highest version
  1221. IF_FAILED_EXIT(CreateAssemblyCacheImport(&pCacheImport, _pAsmId, CACHEIMP_CREATE_RESOLVE_REF));
  1222. if (_hr == S_FALSE)
  1223. {
  1224. Msg(L"No completed cached version found. Possible error in download cache commit. Cannot continue.");
  1225. _hr = E_ABORT;
  1226. goto exit;
  1227. }
  1228. }
  1229. IF_FAILED_EXIT(pCacheImport->GetManifestFileDir(&_pwzAppRootDir, &dwCC));
  1230. IF_FALSE_EXIT(dwCC >= sizeof("c:\\"), E_FAIL); // this should never happen
  1231. IF_FAILED_EXIT(pCacheImport->GetManifestFilePath(&_pwzAppManifestPath, &dwCC));
  1232. exit:
  1233. SAFERELEASE(pCacheImport);
  1234. if (FAILED(_hr))
  1235. {
  1236. SAFEDELETEARRAY(_pwzAppRootDir);
  1237. SAFEDELETEARRAY(_pwzAppManifestPath);
  1238. }
  1239. return _hr;
  1240. }
  1241. // ----------------------------------------------------------------------------
  1242. HRESULT CActivator::HandlePlatformCheckResult()
  1243. {
  1244. if (_dwMissingPlatform > 0)
  1245. {
  1246. // L"Single link: <a href=\"http://foo\" id=\"id1\">link</a>"
  1247. DWORD dwReturn = 0;
  1248. CString sText;
  1249. IF_FAILED_EXIT(sText.Assign(L"The required version of "));
  1250. IF_FAILED_EXIT(sText.Append((_ptPlatform[0]).pwzName));
  1251. IF_FAILED_EXIT(sText.Append(L" is not available on this system.\n\nMore information about this platform can be found at \n<a href=\""));
  1252. IF_FAILED_EXIT(sText.Append((_ptPlatform[0]).pwzURL));
  1253. IF_FAILED_EXIT(sText.Append(L"\">"));
  1254. IF_FAILED_EXIT(sText.Append((_ptPlatform[0]).pwzURL));
  1255. IF_FAILED_EXIT(sText.Append(L"</a>"));
  1256. IF_FAILED_EXIT(ShowDialog(NULL, IDD_LINKDIALOG, sText._pwz, L"Platform Update Required", dwReturn));
  1257. _hr = E_ABORT;
  1258. goto exit;
  1259. }
  1260. else
  1261. _hr = S_OK;
  1262. exit:
  1263. return _hr;
  1264. }
  1265. // ----------------------------------------------------------------------------
  1266. // BUGBUG: this should be in-sync with what server does to register update
  1267. #define REG_KEY_FUSION_SETTINGS L"Software\\Microsoft\\Fusion\\Installer\\1.0.0.0\\Policy"
  1268. #define REG_VAL_INTRANET_DISALLOW L"Download from Intranet Disallowed"
  1269. #define REG_VAL_TRUSTED_DISALLOW L"Download from Trusted Zone Disallowed"
  1270. #define REG_VAL_INTERNET_DISALLOW L"Download from Internet Disallowed"
  1271. #define REG_VAL_UNTRUSTED_DISALLOW L"Download from Untrusted Zone Disallowed"
  1272. // ---------------------------------------------------------------------------
  1273. // CActivator::CheckZonePolicy
  1274. // return: S_OK for yes/ok, E_ABORT for no/abort
  1275. // default is allow all
  1276. // ---------------------------------------------------------------------------
  1277. HRESULT CActivator::CheckZonePolicy(LPWSTR pwzURL)
  1278. {
  1279. DWORD dwZone = 0;
  1280. DWORD dwType = 0;
  1281. DWORD dwValue = -1;
  1282. DWORD dwSize = sizeof(dwValue);
  1283. if (_pSecurityMgr == NULL)
  1284. {
  1285. // lazy init.
  1286. _hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER,
  1287. IID_IInternetSecurityManager, (void**)&_pSecurityMgr);
  1288. if (FAILED(_hr))
  1289. _pSecurityMgr = NULL;
  1290. IF_FAILED_EXIT(_hr);
  1291. }
  1292. IF_FAILED_EXIT(_pSecurityMgr->MapUrlToZone(pwzURL, &dwZone, 0));
  1293. // BUGBUG: hack up code here... not much error checking...
  1294. switch(dwZone)
  1295. {
  1296. case 1: // Intranet Zone
  1297. // Get registry entry
  1298. if (GetRegKeyValue(HKEY_CURRENT_USER,
  1299. REG_KEY_FUSION_SETTINGS, REG_VAL_INTRANET_DISALLOW,
  1300. &dwType, (PBYTE) &dwValue, &dwSize)
  1301. == ERROR_SUCCESS)
  1302. {
  1303. if (dwValue == 1)
  1304. {
  1305. _hr = E_ABORT;
  1306. Msg(L"Zone policy: Download from Intranet is disallowed. Aborting...");
  1307. }
  1308. }
  1309. break;
  1310. case 2: // Trusted Zone
  1311. // Get registry entry
  1312. if (GetRegKeyValue(HKEY_CURRENT_USER,
  1313. REG_KEY_FUSION_SETTINGS, REG_VAL_TRUSTED_DISALLOW,
  1314. &dwType, (PBYTE) &dwValue, &dwSize)
  1315. == ERROR_SUCCESS)
  1316. {
  1317. if (dwValue == 1)
  1318. {
  1319. _hr = E_ABORT;
  1320. Msg(L"Zone policy: Download from Trusted Zone is disallowed. Aborting...");
  1321. }
  1322. }
  1323. break;
  1324. case 3: // Internet Zone
  1325. // Get registry entry
  1326. if (GetRegKeyValue(HKEY_CURRENT_USER,
  1327. REG_KEY_FUSION_SETTINGS, REG_VAL_INTERNET_DISALLOW,
  1328. &dwType, (PBYTE) &dwValue, &dwSize)
  1329. == ERROR_SUCCESS)
  1330. {
  1331. if (dwValue == 1)
  1332. {
  1333. _hr = E_ABORT;
  1334. Msg(L"Zone policy: Download from Internet is disallowed. Aborting...");
  1335. }
  1336. }
  1337. break;
  1338. default:
  1339. case 4: // Untrusted Zone
  1340. // Get registry entry
  1341. if (GetRegKeyValue(HKEY_CURRENT_USER,
  1342. REG_KEY_FUSION_SETTINGS, REG_VAL_UNTRUSTED_DISALLOW,
  1343. &dwType, (PBYTE) &dwValue, &dwSize)
  1344. == ERROR_SUCCESS)
  1345. {
  1346. if (dwValue == 1)
  1347. {
  1348. _hr = E_ABORT;
  1349. Msg(L"Zone policy: Download from Untrusted Zone is disallowed. Aborting...");
  1350. }
  1351. }
  1352. break;
  1353. case 0: //Local machine
  1354. break;
  1355. }
  1356. exit:
  1357. return _hr;
  1358. }