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.

4872 lines
153 KiB

  1. //*************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation 1998
  4. // All rights reserved
  5. //
  6. // Appinfo.cxx
  7. //
  8. //*************************************************************
  9. #include "appmgext.hxx"
  10. //
  11. // CAppInfo
  12. //
  13. // Initialization from the Directory.
  14. CAppInfo::CAppInfo(
  15. CManagedAppProcessor * pManApp,
  16. PACKAGEDISPINFO * pPackageInfo,
  17. BOOL bDemandInstall,
  18. BOOL & bStatus
  19. )
  20. {
  21. _pManApp = pManApp;
  22. _DemandInstall = bDemandInstall;
  23. _DeploymentId = pPackageInfo->PackageGuid;
  24. bStatus = Initialize( pPackageInfo );
  25. if ( ! bStatus )
  26. DebugMsg((DM_WARNING, IDS_APPINFO_FAIL, pPackageInfo->pszPackageName));
  27. }
  28. // Initialization from the registry.
  29. CAppInfo::CAppInfo(
  30. CManagedAppProcessor * pManApp,
  31. WCHAR * pwszDeploymentId,
  32. BOOL & bStatus
  33. )
  34. {
  35. _pManApp = pManApp;
  36. _DemandInstall = FALSE;
  37. StringToGuid( pwszDeploymentId, &_DeploymentId );
  38. _StatusList.Reset();
  39. bStatus = Initialize( NULL );
  40. if ( ! bStatus )
  41. DebugMsg((DM_WARNING, IDS_LOCALAPPINFO_FAIL, pwszDeploymentId));
  42. }
  43. // Initialization from a local script file.
  44. CAppInfo::CAppInfo(
  45. WCHAR * pwszDeploymentId
  46. )
  47. {
  48. _pManApp = 0;
  49. StringToGuid( pwszDeploymentId, &_DeploymentId );
  50. (void) Initialize( NULL );
  51. }
  52. BOOL
  53. CAppInfo::Initialize(
  54. PACKAGEDISPINFO * pPackageInfo
  55. )
  56. {
  57. HKEY hkApp;
  58. WCHAR wszDeploymentId[44];
  59. DWORD Length;
  60. DWORD Size;
  61. DWORD n, i;
  62. DWORD Status;
  63. WCHAR* wszSomId;
  64. HRESULT hr;
  65. _pwszDeploymentName = 0;
  66. _pwszGPOId = 0;
  67. _pwszGPOName = 0;
  68. _pwszSOMId = 0;
  69. _pwszGPODSPath = 0;
  70. _pwszProductId = 0;
  71. _pwszLocalScriptPath = 0;
  72. _pwszGPTScriptPath = 0;
  73. _Upgrades = 0;
  74. _pUpgrades = 0;
  75. _Overrides = 0;
  76. _pOverrides = 0;
  77. _pwszSupercededIds = 0;
  78. _pwszPublisher = 0;
  79. _pwszSupportURL = 0;
  80. _VersionHi = 0;
  81. _VersionLo = 0;
  82. _PathType = DrwFilePath;
  83. memset( &_USN, 0, sizeof(_USN) );
  84. _LangId = LANG_NEUTRAL;
  85. _LanguageWeight = 0;
  86. _AssignCount = 0;
  87. _LocalRevision = 0;
  88. memset( &_ScriptTime, 0, sizeof(_ScriptTime) );
  89. _DirectoryRevision = 0;
  90. _InstallUILevel = INSTALLUILEVEL_DEFAULT;
  91. _ActFlags = 0;
  92. _InstallState = INSTALLSTATE_UNKNOWN;
  93. _State = 0;
  94. _Action = ACTION_NONE;
  95. _Status = ERROR_SUCCESS;
  96. _bNeedsUnmanagedRemove = FALSE;
  97. _rgSecurityDescriptor = 0;
  98. _cbSecurityDescriptor = 0;
  99. _bSuperseded = FALSE;
  100. _bRollback = FALSE;
  101. _bRemovalLogged = FALSE;
  102. _bTransformConflict = FALSE;
  103. _bRestored = FALSE;
  104. _rgwszTransforms = NULL;
  105. _rgwszCategories = NULL;
  106. _cTransforms = 0;
  107. _cCategories = 0;
  108. _pwszPackageLocation = 0;
  109. _pwszRemovingDeploymentId = 0;
  110. _cArchitectures = 0;
  111. _rgArchitectures = NULL;
  112. _PrimaryArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
  113. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE;
  114. _dwRemovalCause = APP_ATTRIBUTE_REMOVALCAUSE_NONE;
  115. _bSupersedesAssigned = FALSE;
  116. _dwUserApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE;
  117. _wszDemandSpec = NULL;
  118. _wszDemandProp = NULL;
  119. if ( ! _pManApp )
  120. return FALSE;
  121. Status = ERROR_SUCCESS;
  122. Length = lstrlen( _pManApp->LocalScriptDir() );
  123. _pwszLocalScriptPath = new WCHAR[Length + 44];
  124. if ( ! _pwszLocalScriptPath )
  125. return FALSE;
  126. hr = StringCchCopy( _pwszLocalScriptPath, Length+44, _pManApp->LocalScriptDir() );
  127. if (FAILED(hr))
  128. {
  129. delete [] _pwszLocalScriptPath;
  130. return FALSE;
  131. }
  132. GuidToString( _DeploymentId, &_pwszLocalScriptPath[Length] );
  133. hr = StringCchCopy( &_pwszLocalScriptPath[Length+GUIDSTRLEN], 44-GUIDSTRLEN,L".aas" );
  134. if (FAILED(hr))
  135. {
  136. delete [] _pwszLocalScriptPath;
  137. return FALSE;
  138. }
  139. if ( CRsopAppContext::REMOVAL == _pManApp->GetRsopContext()->GetContext() )
  140. {
  141. _dwRemovalCause = APP_ATTRIBUTE_REMOVALCAUSE_USER;
  142. }
  143. else if ( _pManApp->GetRsopContext()->RemoveGPOApps() )
  144. {
  145. _dwRemovalCause = APP_ATTRIBUTE_REMOVALCAUSE_SCOPELOSS;
  146. }
  147. if ( pPackageInfo )
  148. {
  149. CGPOInfo* pGpoInfo;
  150. CGPOInfoList& GpoInfoList = _pManApp->GPOList();
  151. _VersionHi = pPackageInfo->dwVersionHi;
  152. _VersionLo = pPackageInfo->dwVersionLo;
  153. _LangId = pPackageInfo->LangId;
  154. _LanguageWeight = GetLanguagePriority(LANGIDFROMLCID(pPackageInfo->LangId),pPackageInfo->dwActFlags);
  155. _pwszGPTScriptPath = StringDuplicate( pPackageInfo->pszScriptPath );
  156. if ( ! _pwszGPTScriptPath && !(_pManApp->ARPList()))
  157. return FALSE;
  158. _pwszDeploymentName = StringDuplicate( pPackageInfo->pszPackageName );
  159. GuidToString( pPackageInfo->ProductCode, &_pwszProductId );
  160. GuidToString( pPackageInfo->GpoId, &_pwszGPOId );
  161. if ( _pwszGPOId )
  162. {
  163. pGpoInfo = GpoInfoList.Find( _pwszGPOId );
  164. _pwszGPOName = StringDuplicate( pGpoInfo ? pGpoInfo->GetGPOName() : L"" );
  165. }
  166. _pwszPublisher = StringDuplicate( pPackageInfo->pszPublisher );
  167. _pwszSupportURL = StringDuplicate( pPackageInfo->pszUrl );
  168. if ( _pManApp->GetRsopContext()->IsRsopEnabled() || _pManApp->ARPList() )
  169. Status = InitializeCategoriesList( pPackageInfo );
  170. if ( (ERROR_SUCCESS == Status ) &&
  171. _pManApp->GetRsopContext()->IsRsopEnabled() )
  172. {
  173. //
  174. // We perform RSoP specific initialization here. Note that if
  175. // any of these fails, we disable RSoP, but continue policy
  176. // application. Any partial initialization due to an
  177. // error will be cleaned up by the destructor
  178. //
  179. _pwszSOMId = StringDuplicate( pGpoInfo ? pGpoInfo->GetSOMPath() : L"" );
  180. //
  181. // Make copies of RSoP specific simple string data
  182. //
  183. if ( pPackageInfo->cbSecurityDescriptor )
  184. {
  185. _rgSecurityDescriptor = new BYTE[ pPackageInfo->cbSecurityDescriptor ];
  186. if ( _rgSecurityDescriptor && pPackageInfo->rgSecurityDescriptor )
  187. {
  188. _cbSecurityDescriptor = pPackageInfo->cbSecurityDescriptor;
  189. memcpy( _rgSecurityDescriptor, pPackageInfo->rgSecurityDescriptor, pPackageInfo->cbSecurityDescriptor );
  190. }
  191. }
  192. _pwszGPODSPath = StringDuplicate( pPackageInfo->pszGpoPath );
  193. //
  194. // Check for memory allocation failures
  195. //
  196. if ( ! _pwszSOMId || ! _pwszGPODSPath )
  197. {
  198. Status = ERROR_OUTOFMEMORY;
  199. }
  200. //
  201. // Now make copies of the more complex RSoP information
  202. //
  203. if ( ERROR_SUCCESS == Status )
  204. Status = InitializeRSOPTransformsList( pPackageInfo );
  205. if ( ERROR_SUCCESS == Status )
  206. Status = InitializeRSOPArchitectureInfo( pPackageInfo );
  207. if ( ERROR_SUCCESS != Status )
  208. {
  209. hr = HRESULT_FROM_WIN32( Status );
  210. _pManApp->GetRsopContext()->DisableRsop( hr );
  211. }
  212. }
  213. for ( n = 0; n < pPackageInfo->cUpgrades; n++ )
  214. {
  215. if ( pPackageInfo->prgUpgradeInfoList[n].Flag & (UPGFLG_Uninstall | UPGFLG_NoUninstall) )
  216. _Upgrades++;
  217. }
  218. if ( _Upgrades > 0 )
  219. {
  220. _pUpgrades = new UPGRADE_INFO[_Upgrades];
  221. if ( ! _pUpgrades )
  222. return FALSE;
  223. memset( _pUpgrades, 0, sizeof(UPGRADE_INFO) * _Upgrades );
  224. for ( n = 0, i = 0; n < pPackageInfo->cUpgrades; n++ )
  225. {
  226. if ( ! (pPackageInfo->prgUpgradeInfoList[n].Flag & (UPGFLG_Uninstall | UPGFLG_NoUninstall)) )
  227. continue;
  228. _pUpgrades[i].DeploymentId = pPackageInfo->prgUpgradeInfoList[n].PackageGuid;
  229. _pUpgrades[i].Flags = UPGRADE_OVER;
  230. if ( pPackageInfo->prgUpgradeInfoList[n].Flag & UPGFLG_Uninstall )
  231. _pUpgrades[i].Flags |= UPGRADE_UNINSTALL;
  232. else
  233. _pUpgrades[i].Flags |= UPGRADE_NOUNINSTALL;
  234. i++;
  235. }
  236. }
  237. memcpy( &_USN, &pPackageInfo->Usn, sizeof(_USN) );
  238. _DirectoryRevision = pPackageInfo->dwRevision;
  239. _InstallUILevel = pPackageInfo->InstallUiLevel;
  240. _PathType = pPackageInfo->PathType;
  241. _ActFlags = pPackageInfo->dwActFlags;
  242. }
  243. GuidToString( _DeploymentId, wszDeploymentId);
  244. if ( ERROR_SUCCESS == Status )
  245. {
  246. if ( ! _pManApp->GetRsopContext()->IsPlanningModeEnabled() )
  247. {
  248. //
  249. // Need to request set value access so that we may
  250. // delete the RemovedGPOState value if it exists -- because of this
  251. // we must revert since the user may not have write access
  252. //
  253. (void) _pManApp->Revert();
  254. Status = RegOpenKeyEx(
  255. _pManApp->AppmgmtKey(),
  256. wszDeploymentId,
  257. 0,
  258. KEY_READ | KEY_SET_VALUE,
  259. &hkApp );
  260. DWORD impStatus = _pManApp->Impersonate();
  261. if ( impStatus != ERROR_SUCCESS )
  262. {
  263. Status = impStatus;
  264. }
  265. }
  266. else
  267. {
  268. Status = ERROR_FILE_NOT_FOUND;
  269. }
  270. }
  271. if ( ERROR_SUCCESS == Status )
  272. {
  273. Size = sizeof(DWORD);
  274. _State = APPSTATE_PUBLISHED | APPSTATE_POLICYREMOVE_ORPHAN;
  275. (void) RegQueryValueEx(
  276. hkApp,
  277. APPSTATEVALUE,
  278. 0,
  279. NULL,
  280. (LPBYTE) &_State,
  281. &Size );
  282. Size = sizeof(DWORD);
  283. //
  284. // This is used to track the best case time when we could completely
  285. // delete an appmgmt key after an app is unassigned.
  286. //
  287. (void) RegQueryValueEx(
  288. hkApp,
  289. ASSIGNCOUNTVALUE,
  290. 0,
  291. NULL,
  292. (LPBYTE) &_AssignCount,
  293. &Size );
  294. Size = sizeof(DWORD);
  295. //
  296. // Beta2 systems didn't write this value. If it is not found we
  297. // just use the default value of 0.
  298. //
  299. (void) RegQueryValueEx(
  300. hkApp,
  301. REVISIONVALUE,
  302. 0,
  303. NULL,
  304. (LPBYTE) &_LocalRevision,
  305. &Size );
  306. if ( _LocalRevision > 0 )
  307. {
  308. Size = sizeof(_ScriptTime);
  309. (void) RegQueryValueEx(
  310. hkApp,
  311. SCRIPTTIMEVALUE,
  312. 0,
  313. NULL,
  314. (LPBYTE) &_ScriptTime,
  315. &Size );
  316. }
  317. if ( ! pPackageInfo )
  318. {
  319. //
  320. // This is needed so that if we are in a RemoveApp call in the service
  321. // we will get the proper UI level to write back for an assigned app.
  322. //
  323. Size = sizeof(DWORD);
  324. (void) RegQueryValueEx(
  325. hkApp,
  326. INSTALLUI,
  327. 0,
  328. NULL,
  329. (LPBYTE) &_InstallUILevel,
  330. &Size );
  331. ReadStringValue( hkApp, DEPLOYMENTNAMEVALUE, &_pwszDeploymentName );
  332. ReadStringValue( hkApp, GPONAMEVALUE, &_pwszGPOName );
  333. ReadStringValue( hkApp, GPOIDVALUE, &_pwszGPOId );
  334. ReadStringValue( hkApp, PRODUCTIDVALUE, &_pwszProductId );
  335. }
  336. //
  337. // During policy refresh, we need to ensure that apps that went out of
  338. // scope on one machine don't come back on another
  339. //
  340. if ( (ERROR_SUCCESS == Status ) &&
  341. _pManApp->RegularPolicyRun() )
  342. {
  343. DWORD dwRemovedState;
  344. LONG StatusRemovedState;
  345. Size = sizeof(DWORD);
  346. //
  347. // Check for an appstate saved if the app went out of scope
  348. //
  349. StatusRemovedState = RegQueryValueEx(
  350. hkApp,
  351. REMOVEDGPOSTATE,
  352. 0,
  353. NULL,
  354. (LPBYTE) &dwRemovedState,
  355. &Size );
  356. if ( ERROR_SUCCESS == StatusRemovedState )
  357. {
  358. BOOL bDeleteRemovedState;
  359. bDeleteRemovedState = FALSE;
  360. //
  361. // We only restore the old app state if this app is currently
  362. // set to be uninstalled or orphaned -- if not, this removed state is invalid
  363. // so we will delete it
  364. //
  365. if ( ! ( ( APPSTATE_UNINSTALLED & _State ) || ( APPSTATE_ORPHANED & _State ) ) )
  366. {
  367. bDeleteRemovedState = TRUE;
  368. }
  369. else if ( pPackageInfo || IsGpoInScope() )
  370. {
  371. //
  372. // The gpo for this app is back in scope, we will restore the state
  373. // to the previous state before it went out of scope on the other machine
  374. //
  375. _State = dwRemovedState;
  376. bDeleteRemovedState = TRUE;
  377. Size = sizeof(DWORD);
  378. //
  379. // Set the state value back to the original state
  380. //
  381. (void) RegSetValueEx(
  382. hkApp,
  383. APPSTATEVALUE,
  384. 0,
  385. REG_DWORD,
  386. (LPBYTE) &dwRemovedState,
  387. sizeof(DWORD) );
  388. _bRestored = TRUE;
  389. DebugMsg((DM_VERBOSE, IDS_ABORT_SCOPELOSS, _pwszDeploymentName ? _pwszDeploymentName : L"" , _pwszGPOName ? _pwszGPOName : L"", _State ));
  390. }
  391. if ( bDeleteRemovedState )
  392. {
  393. (void) RegDeleteValue( hkApp, REMOVEDGPOSTATE );
  394. }
  395. }
  396. }
  397. //
  398. // If the app is currently assigned, treat that as the reason for it being applied.
  399. // This may be overridden later if this app upgrades another
  400. //
  401. if ( ! ( APPSTATE_UNINSTALLED & _State ) && ( APPSTATE_ASSIGNED & _State ) )
  402. {
  403. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_ASSIGNED;
  404. }
  405. ReadStringValue( hkApp, SUPERCEDEDIDS, &_pwszSupercededIds );
  406. RegCloseKey( hkApp );
  407. }
  408. CheckScriptExistence();
  409. if ( ! _pwszDeploymentName ||
  410. ! _pwszGPOId ||
  411. ! _pwszGPOName ||
  412. ! _pwszProductId )
  413. return FALSE;
  414. return TRUE;
  415. }
  416. CAppInfo::~CAppInfo()
  417. {
  418. //
  419. // There are cases, like handling upgrades, where we copy the script
  420. // early on to ensure that we can access it. Later however, the same
  421. // app may be reset to do nothing or may fail to apply. This check here
  422. // deletes any script we copied which we don't need now.
  423. //
  424. if ( ((_Status != ERROR_SUCCESS) || (ACTION_NONE == _Action)) &&
  425. ! (_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED)) &&
  426. ((_State & APPSTATE_SCRIPT_NOT_EXISTED) && (_State & APPSTATE_SCRIPT_PRESENT)) )
  427. {
  428. if ( _pwszLocalScriptPath )
  429. DeleteFile( _pwszLocalScriptPath );
  430. }
  431. DWORD iCategory;
  432. for ( iCategory = 0; iCategory < _cCategories; iCategory++ )
  433. {
  434. delete [] _rgwszCategories[ iCategory ];
  435. }
  436. DWORD iTransform;
  437. for ( iTransform = 0; iTransform < _cTransforms; iTransform++ )
  438. {
  439. delete [] _rgwszTransforms[ iTransform ];
  440. }
  441. CAppStatus* pAppStatus;
  442. //
  443. // Clean up failure statuses
  444. //
  445. for (
  446. _StatusList.Reset();
  447. pAppStatus = (CAppStatus*) _StatusList.GetCurrentItem();
  448. )
  449. {
  450. _StatusList.MoveNext();
  451. delete pAppStatus;
  452. }
  453. delete [] _pwszDeploymentName;
  454. delete [] _pwszGPOName;
  455. delete [] _pwszGPOId;
  456. delete [] _pwszSOMId;
  457. delete [] _pwszGPODSPath;
  458. delete [] _pwszProductId;
  459. delete [] _pwszLocalScriptPath;
  460. delete [] _pwszGPTScriptPath;
  461. delete [] _pUpgrades;
  462. delete [] _pOverrides;
  463. delete [] _pwszSupercededIds;
  464. delete [] _pwszPublisher;
  465. delete [] _pwszSupportURL;
  466. delete [] _rgSecurityDescriptor;
  467. delete [] _rgwszCategories;
  468. delete [] _rgwszTransforms;
  469. delete [] _pwszPackageLocation;
  470. delete [] _pwszRemovingDeploymentId;
  471. delete [] _rgArchitectures;
  472. delete [] _wszDemandSpec;
  473. }
  474. DWORD
  475. CAppInfo::InitializePass0()
  476. {
  477. UPGRADE_INFO * pUpgradeInfo;
  478. if ( ! (_ActFlags & (ACTFLG_Assigned | ACTFLG_Published)) &&
  479. ! (_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED)) )
  480. return ERROR_SUCCESS;
  481. if ( ! _pManApp->ARPList() && (_State & APPSTATE_SCRIPT_EXISTED) )
  482. _InstallState = (*gpfnMsiQueryProductState)( _pwszProductId );
  483. for ( DWORD n = 0; n < _Upgrades; n++ )
  484. {
  485. CAppInfo * pBaseApp;
  486. if ( ! (_pUpgrades[n].Flags & UPGRADE_OVER) )
  487. continue;
  488. //
  489. // Note that an apps' override list will include apps it really will not
  490. // upgrade because of policy precedence violation. However, we keep these
  491. // in the list for our detection of upgrade relationships when doing
  492. // demand installs.
  493. //
  494. AddToOverrideList( &_pUpgrades[n].DeploymentId );
  495. pBaseApp = _pManApp->AppList().Find( _pUpgrades[n].DeploymentId );
  496. if ( ! pBaseApp )
  497. continue;
  498. pUpgradeInfo = new UPGRADE_INFO[pBaseApp->_Upgrades + 1];
  499. if ( ! pUpgradeInfo )
  500. {
  501. _Status = ERROR_OUTOFMEMORY;
  502. return ERROR_OUTOFMEMORY;
  503. }
  504. memcpy( pUpgradeInfo, pBaseApp->_pUpgrades, pBaseApp->_Upgrades * sizeof(UPGRADE_INFO) );
  505. _pUpgrades[n].pBaseApp = pBaseApp;
  506. if ( _pManApp->GPOList().Compare( _pwszGPOId, pBaseApp->_pwszGPOId ) >= 0 )
  507. {
  508. //
  509. // A valid upgrade of the base app. We set a backlink upgrade entry
  510. // for the base app.
  511. //
  512. pUpgradeInfo[pBaseApp->_Upgrades].DeploymentId = _DeploymentId;
  513. pUpgradeInfo[pBaseApp->_Upgrades].Flags = (_pUpgrades[n].Flags & ~UPGRADE_OVER) | UPGRADE_BY;
  514. pUpgradeInfo[pBaseApp->_Upgrades].pBaseApp = this;
  515. }
  516. else
  517. {
  518. //
  519. // An invalid upgrade of the base app because it reverses policy
  520. // precedence. We null out this' upgrade link and set a new
  521. // upgrade link for the base app. The base app becomes the upgrade
  522. // app. The upgrade is forced only if the base app is assigned.
  523. //
  524. // Note that the base app will set a backlink for 'this' in it's own
  525. // InitializePass0 since we process apps from least to highest
  526. // precedence.
  527. //
  528. //
  529. // We preserve the upgrade data for 'this', but remove the forward link flag
  530. // so that it will not be considered to upgrade anything else. We need to
  531. // preserve it so that RSoP logging will be able to log the fact that this
  532. // application upgrades another app
  533. //
  534. _pUpgrades[n].Flags &= ~UPGRADE_OVER;
  535. _pUpgrades[n].pBaseApp = NULL;
  536. pUpgradeInfo[pBaseApp->_Upgrades].DeploymentId = _DeploymentId;
  537. pUpgradeInfo[pBaseApp->_Upgrades].Flags = UPGRADE_UNINSTALL | UPGRADE_OVER | UPGRADE_REVERSED;
  538. if ( pBaseApp->_ActFlags & ACTFLG_Assigned )
  539. pUpgradeInfo[pBaseApp->_Upgrades].Flags |= UPGRADE_FORCE;
  540. pUpgradeInfo[pBaseApp->_Upgrades].pBaseApp = this;
  541. DebugMsg((DM_VERBOSE, IDS_UPGRADE_REVERSE, _pwszDeploymentName, _pwszGPOName, pBaseApp->_pwszDeploymentName, pBaseApp->_pwszGPOName));
  542. }
  543. delete pBaseApp->_pUpgrades;
  544. pBaseApp->_pUpgrades = pUpgradeInfo;
  545. pBaseApp->_Upgrades++;
  546. }
  547. return ERROR_SUCCESS;
  548. }
  549. void
  550. CAppInfo::SetActionPass1()
  551. {
  552. //
  553. // First pass for setting this app's processing actions. In pass1 we set
  554. // an initial state based solely on the individual app, disregarding at this
  555. // time any interaction with other apps being applied as part of the policy
  556. // run.
  557. //
  558. if ( _pManApp->ARPList() )
  559. {
  560. if ( (_ActFlags & (ACTFLG_Assigned | ACTFLG_Published)) && (_ActFlags & ACTFLG_UserInstall) )
  561. {
  562. SetAction(
  563. ACTION_INSTALL,
  564. APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE,
  565. NULL);
  566. }
  567. return;
  568. }
  569. if ( _DemandInstall )
  570. {
  571. SetAction(
  572. ACTION_APPLY,
  573. APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE,
  574. NULL);
  575. }
  576. if ( _pManApp->NoChanges() )
  577. {
  578. if ( _State & APPSTATE_ASSIGNED )
  579. {
  580. //
  581. // User assigned apps are always readvertised.
  582. // Machine assigned apps get readvertised if uninstalled outside of the scope
  583. // of appmgmt (policy/ARP).
  584. //
  585. if ( _pManApp->IsUserPolicy() || ! AppPresent(_InstallState) )
  586. {
  587. SetAction(
  588. ACTION_APPLY,
  589. APP_ATTRIBUTE_APPLYCAUSE_VALUE_ASSIGNED,
  590. NULL);
  591. _State |= APPSTATE_FULL_ADVERTISE;
  592. }
  593. }
  594. else if ( _State & APPSTATE_PUBLISHED )
  595. {
  596. if ( _State & APPSTATE_SCRIPT_NOT_EXISTED )
  597. {
  598. //
  599. // This is the roaming case where the app was installed on another
  600. // machine and the user is now logging onto a new machine.
  601. //
  602. SetAction(
  603. ACTION_APPLY,
  604. APP_ATTRIBUTE_APPLYCAUSE_VALUE_PROFILE,
  605. NULL);
  606. }
  607. else
  608. {
  609. if ( ( (INSTALLSTATE_UNKNOWN == _InstallState) || (INSTALLSTATE_ABSENT == _InstallState) ) &&
  610. ! _bRestored )
  611. {
  612. //
  613. // This is the case where a published app was uninstalled via some
  614. // non-mgmt mechanism like msiexec command line or the app's own
  615. // configuration via ARP. We respect this type of uninstall.
  616. //
  617. SetAction(
  618. ACTION_ORPHAN,
  619. APP_ATTRIBUTE_REMOVALCAUSE_PROFILE,
  620. NULL);
  621. DebugMsg((DM_VERBOSE, IDS_ORPHAN_ACTION4, _pwszDeploymentName, _pwszGPOName));
  622. }
  623. }
  624. }
  625. return;
  626. }
  627. BOOL bUninstalled;
  628. DWORD dwRemovalCause;
  629. bUninstalled = (_ActFlags & ACTFLG_Uninstall) && (_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED | APPSTATE_SCRIPT_EXISTED));
  630. if ( bUninstalled )
  631. {
  632. dwRemovalCause = APP_ATTRIBUTE_REMOVALCAUSE_ADMIN;
  633. }
  634. else
  635. {
  636. bUninstalled = (_State & APPSTATE_UNINSTALLED) && (_State & APPSTATE_SCRIPT_EXISTED);
  637. //
  638. // We now know that the app is in the uninstalled state, but the script is here, which means
  639. // that it was uninstalled on another machine if this is user policy. If this app is currently
  640. // assigned in the directory but uninstalled here, that means it was probably upgraded by an app
  641. // on the other machine by an application that no longer applies. In order to get this assigned
  642. // base app to return, we should prevent it from being marked as uninstalled.
  643. //
  644. if ( bUninstalled && _pManApp->IsUserPolicy() && ( _ActFlags & ACTFLG_Assigned ) )
  645. {
  646. bUninstalled = FALSE;
  647. DebugMsg((DM_VERBOSE, IDS_ASSIGNED_NOUNINSTALL_ROAM, _pwszDeploymentName, _pwszGPOName));
  648. }
  649. if ( bUninstalled )
  650. {
  651. dwRemovalCause = APP_ATTRIBUTE_REMOVALCAUSE_PROFILE;
  652. }
  653. }
  654. if ( bUninstalled )
  655. {
  656. SetAction(
  657. ACTION_UNINSTALL,
  658. dwRemovalCause,
  659. NULL);
  660. DebugMsg((DM_VERBOSE, IDS_UNINSTALL_ACTION1, _pwszDeploymentName, _pwszGPOName));
  661. }
  662. if ( ACTION_UNINSTALL == _Action )
  663. return;
  664. if ( ((_ActFlags & ACTFLG_Orphan) && (_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED | APPSTATE_SCRIPT_EXISTED))) ||
  665. ((_State & APPSTATE_ORPHANED) && (_State & APPSTATE_SCRIPT_EXISTED)) )
  666. {
  667. SetAction(
  668. ACTION_ORPHAN,
  669. APP_ATTRIBUTE_REMOVALCAUSE_ADMIN,
  670. NULL);
  671. DebugMsg((DM_VERBOSE, IDS_ORPHAN_ACTION1, _pwszDeploymentName, _pwszGPOName));
  672. }
  673. if ( ACTION_ORPHAN == _Action )
  674. return;
  675. //
  676. // Only look for apply actions if no one else has yet set our status
  677. // explicitly through an upgrade relationship or through the service.
  678. //
  679. // Our first check is for actions to take based on information coming
  680. // down from the directory.
  681. //
  682. if ( ACTION_NONE == _Action )
  683. {
  684. if ( _ActFlags & ACTFLG_Assigned )
  685. {
  686. if ( (_ActFlags & ACTFLG_InstallUserAssign) &&
  687. ((_State & APPSTATE_SCRIPT_NOT_EXISTED) || ! (_State & APPSTATE_INSTALL)) )
  688. {
  689. //
  690. // This is the new user assigned install option added after Windows2000.
  691. // We do an install just once at each computer. Thereafter it is treated
  692. // as a regular user assignment.
  693. //
  694. SetAction(
  695. ACTION_INSTALL,
  696. APP_ATTRIBUTE_APPLYCAUSE_VALUE_ASSIGNED,
  697. NULL);
  698. DebugMsg((DM_VERBOSE, IDS_INSTALL_ACTION2, _pwszDeploymentName, _pwszGPOName));
  699. }
  700. else if ( _pManApp->IsUserPolicy() ||
  701. ((_State & APPSTATE_ASSIGNED) && ! AppPresent(_InstallState)) )
  702. {
  703. SetAction(
  704. ACTION_APPLY,
  705. APP_ATTRIBUTE_APPLYCAUSE_VALUE_ASSIGNED,
  706. NULL);
  707. _State |= APPSTATE_FULL_ADVERTISE;
  708. DebugMsg((DM_VERBOSE, IDS_ASSIGN1_ACTION, _pwszDeploymentName, _pwszGPOName));
  709. }
  710. else
  711. {
  712. //
  713. // We only do an install for a machine assigned app once. After that
  714. // only a redeploy will cause any action.
  715. //
  716. if ( ! (_State & APPSTATE_ASSIGNED) )
  717. {
  718. SetAction(
  719. ACTION_INSTALL,
  720. APP_ATTRIBUTE_APPLYCAUSE_VALUE_ASSIGNED,
  721. NULL);
  722. DebugMsg((DM_VERBOSE, IDS_INSTALL_ACTION1, _pwszDeploymentName, _pwszGPOName));
  723. }
  724. }
  725. }
  726. //
  727. // We only apply published apps if we're logging onto a machine where
  728. // the published app has not yet been applied.
  729. //
  730. // If the script for the published app exists on the machine then it
  731. // was likely uninstalled via a means we do not detect, so we now
  732. // orphan it.
  733. //
  734. if ( (_ActFlags & ACTFLG_Published) && (_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED)) )
  735. {
  736. if ( _State & APPSTATE_SCRIPT_NOT_EXISTED )
  737. {
  738. SetAction(
  739. ACTION_APPLY,
  740. APP_ATTRIBUTE_APPLYCAUSE_VALUE_PROFILE,
  741. NULL);
  742. DebugMsg((DM_VERBOSE, IDS_ASSIGN3_ACTION, _pwszDeploymentName, _pwszGPOName));
  743. }
  744. else if ( _bRestored )
  745. {
  746. //
  747. // This is the roaming case where the app was uninstalled on another
  748. // machine because its gpo went out of scope, but on this machine
  749. // that gpo is in scope, so it needs to be readvertised since the
  750. // advertise data was removed on the other machine
  751. //
  752. //
  753. // Note that We set the apply cause value to none which will later force us
  754. // to generate an apply cause that takes into account the apply cause
  755. // currently in the rsop database. Since we do not know at this time what is
  756. // stored in RSoP, we cannot know the correct apply cause so we defer this
  757. // to the time at which we're accessing the database for logging.
  758. //
  759. SetAction(
  760. ACTION_APPLY,
  761. APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE,
  762. NULL);
  763. DebugMsg((DM_VERBOSE, IDS_ASSIGN5_ACTION, _pwszDeploymentName, _pwszGPOName));
  764. }
  765. else
  766. {
  767. if ( (INSTALLSTATE_UNKNOWN == _InstallState) || (INSTALLSTATE_ABSENT == _InstallState) )
  768. {
  769. //
  770. // This is the case where a published app was uninstalled via some
  771. // non-mgmt mechanism like msiexec command line or the app's own
  772. // configuration via ARP. We respect this type of uninstall.
  773. //
  774. SetAction(
  775. ACTION_ORPHAN,
  776. APP_ATTRIBUTE_REMOVALCAUSE_USER,
  777. NULL);
  778. DebugMsg((DM_VERBOSE, IDS_ORPHAN_ACTION4, _pwszDeploymentName, _pwszGPOName));
  779. }
  780. else
  781. {
  782. DebugMsg((DM_VERBOSE, IDS_NONE_ACTION1, _pwszDeploymentName, _pwszGPOName));
  783. }
  784. }
  785. }
  786. }
  787. if ( ACTION_NONE == _Action )
  788. {
  789. //
  790. // Three types of apps will still be at ACTION_NONE here :
  791. // + Published apps we already have on the machine
  792. // + Disabled apps -> (ACTFLG_Assigned | ACTFLG_Published) is not set
  793. // + Apps which "disappear" from our policy set because of ACLs
  794. // on the app's deployment properties (not GPO ACLs, that would
  795. // cause a removal of the entire GPO)
  796. //
  797. // We want to do appropriate orphaning actions only for the last
  798. // case. The first two classes of apps are simply left alone. Note
  799. // that if an app is explicitly removed-orphan, we know this
  800. // because it still comes down from the Directory with the
  801. // ACTFLG_Orphan flag set.
  802. //
  803. // We detect the third case with a zero _ActFlag, which means the app
  804. // was not found in the Directory.
  805. //
  806. if ( (0 == _ActFlags) && (_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED)) )
  807. {
  808. if ( _State & APPSTATE_POLICYREMOVE_UNINSTALL )
  809. {
  810. SetAction(
  811. ACTION_UNINSTALL,
  812. APP_ATTRIBUTE_REMOVALCAUSE_SCOPELOSS,
  813. NULL);
  814. DebugMsg((DM_VERBOSE, IDS_UNINSTALL_ACTION2, _pwszDeploymentName, _pwszGPOName));
  815. }
  816. else
  817. {
  818. SetAction(
  819. ACTION_ORPHAN,
  820. APP_ATTRIBUTE_REMOVALCAUSE_SCOPELOSS,
  821. NULL);
  822. DebugMsg((DM_VERBOSE, IDS_ORPHAN_ACTION3, _pwszDeploymentName, _pwszGPOName));
  823. }
  824. _dwRemovalCause = APP_ATTRIBUTE_REMOVALCAUSE_SCOPELOSS;
  825. return;
  826. }
  827. }
  828. //
  829. // Check if we have to do a reinstall because of a patch on the install
  830. // image. Note, we only go to this state if the app is already
  831. // installed on this machine.
  832. //
  833. // Note, the Darwin msi database is only cached at install time, so
  834. // if the app is only advertised, we will always pull down the most recent
  835. // msi when the install is invoked.
  836. //
  837. // Also, the INSTALLSTATE_DEFAULT covers both the INSTALLSTATE_LOCAL and
  838. // INSTALLSTATE_SOURCE.
  839. //
  840. if ( (_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED)) &&
  841. (_State & APPSTATE_SCRIPT_EXISTED) &&
  842. (_DirectoryRevision > 0) )
  843. {
  844. CAppInfo * pScriptInfo;
  845. if ( _LocalRevision < _DirectoryRevision )
  846. {
  847. SetAction(
  848. ACTION_REINSTALL,
  849. APP_ATTRIBUTE_APPLYCAUSE_VALUE_REDEPLOY,
  850. NULL);
  851. DebugMsg((DM_VERBOSE, IDS_REINSTALL_ACTION1, _pwszDeploymentName, _pwszGPOName));
  852. }
  853. else
  854. {
  855. pScriptInfo = _pManApp->ScriptList().Find( _DeploymentId );
  856. if ( CompareFileTime( &pScriptInfo->_ScriptTime, &_ScriptTime ) < 0 )
  857. {
  858. SetAction(
  859. ACTION_REINSTALL,
  860. APP_ATTRIBUTE_APPLYCAUSE_VALUE_REDEPLOY,
  861. NULL);
  862. if ( DebugLevelOn(DM_VERBOSE) )
  863. {
  864. SYSTEMTIME LocalTime;
  865. SYSTEMTIME SysvolTime;
  866. WCHAR wszLocalTime[32];
  867. WCHAR wszSysvolTime[32];
  868. FileTimeToSystemTime( &pScriptInfo->_ScriptTime, &LocalTime );
  869. FileTimeToSystemTime( &_ScriptTime, &SysvolTime );
  870. (void) StringCchPrintf(
  871. wszLocalTime,
  872. sizeof(wszLocalTime)/sizeof(wszLocalTime[0]),
  873. L"%02d-%02d %02d:%02d:%02d:%03d",
  874. LocalTime.wMonth,
  875. LocalTime.wDay,
  876. LocalTime.wHour,
  877. LocalTime.wMinute,
  878. LocalTime.wSecond,
  879. LocalTime.wMilliseconds );
  880. (void) StringCchPrintf(
  881. wszSysvolTime,
  882. sizeof(wszSysvolTime)/sizeof(wszSysvolTime[0]),
  883. L"%02d-%02d %02d:%02d:%02d:%03d",
  884. SysvolTime.wMonth,
  885. SysvolTime.wDay,
  886. SysvolTime.wHour,
  887. SysvolTime.wMinute,
  888. SysvolTime.wSecond,
  889. SysvolTime.wMilliseconds );
  890. DebugMsg((DM_VERBOSE, IDS_REINSTALL_ACTION2, _pwszDeploymentName, _pwszGPOName, wszLocalTime, wszSysvolTime));
  891. }
  892. }
  893. }
  894. }
  895. }
  896. void
  897. CAppInfo::SetActionPass2()
  898. {
  899. //
  900. // In pass two we do product id filtering based on language and policy
  901. // precedence.
  902. //
  903. //
  904. // In reporting mode, we perform no processing, all apps that currently
  905. // apply (i.e. all apps in the gpo) will be logged
  906. //
  907. if ( _pManApp->GetRsopContext()->IsReportingModeEnabled() )
  908. {
  909. return;
  910. }
  911. if ( (ACTION_UNINSTALL == _Action) || (ACTION_ORPHAN == _Action) )
  912. return;
  913. //
  914. // When creating the list of apps to show in ARP we want to include
  915. // the highest precedence assigned app (if one exists) and all
  916. // published apps from higher precedence policies then the one that
  917. // the (optional) assigned app has come from. Thus if there are no
  918. // assigned apps with the product code, we would show the published
  919. // apps from all policies.
  920. //
  921. // This is done simply by not allowing published apps to filter out
  922. // any lower precedence apps.
  923. //
  924. if ( _pManApp->ARPList() && (_ActFlags & ACTFLG_Published) )
  925. return;
  926. //
  927. // Published apps which we already have on the machine will never be
  928. // set to apply again. However, we still want them to override lower
  929. // precedence products (even assigned) that have the same product id.
  930. // So the below check causes the logic to continue as long as 'this'
  931. // app has already been applied on this machine.
  932. //
  933. // Note that we check for the assigned state as well because it could
  934. // be getting changed to published in this run of policy.
  935. //
  936. if ( (ACTION_NONE == _Action) && ! (_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED)) )
  937. return;
  938. //
  939. // If multiple apps of the same product id are set to be assigned or
  940. // installed, only assign/install the one in the closest GPO. This is
  941. // usefull when the app is deployed with a different set of transforms
  942. // in the different GPOs. Darwin will only honor one set of transforms.
  943. //
  944. //
  945. // We do this pass in the NoChanges case to enforce the product code
  946. // filtering logic.
  947. //
  948. CAppInfo * pAppInfo;
  949. DWORD n;
  950. BOOL bPastThis;
  951. BOOL bAnalyzeForRsopOnly;
  952. bPastThis = FALSE;
  953. bAnalyzeForRsopOnly = FALSE;
  954. for ( _pManApp->AppList().Reset(), pAppInfo = (CAppInfo *) _pManApp->AppList().GetCurrentItem();
  955. pAppInfo;
  956. _pManApp->AppList().MoveNext(), pAppInfo = (CAppInfo *) _pManApp->AppList().GetCurrentItem() )
  957. {
  958. if ( pAppInfo == this )
  959. {
  960. bPastThis = TRUE;
  961. continue;
  962. }
  963. //
  964. // Once we're past 'this' we need to start checking if we should
  965. // stop processing. We don't want to supercede an app with the
  966. // same product id which is of higher precedence.
  967. //
  968. // When not constructing the ARP list of apps, we stop once
  969. // past 'this'. The most recently deployed app will win ties in
  970. // that case.
  971. //
  972. // When constructing the ARP list of apps, we keep on looking at other
  973. // apps until we encounter a new policy or an assigned app. That is
  974. // because we want to treat all published apps in a policy equally,
  975. // but an assigned app acts as a blocking point.
  976. //
  977. if ( bPastThis )
  978. {
  979. if ( lstrcmpi( pAppInfo->_pwszGPOId, _pwszGPOId ) != 0 )
  980. break;
  981. if ( ! _pManApp->ARPList() )
  982. break;
  983. else if ( pAppInfo->_ActFlags & ACTFLG_Assigned )
  984. bAnalyzeForRsopOnly = TRUE;
  985. }
  986. if ( (ACTION_ORPHAN == pAppInfo->_Action) || (ACTION_UNINSTALL == pAppInfo->_Action) )
  987. continue;
  988. if ( (ACTION_NONE == pAppInfo->_Action) &&
  989. ! (pAppInfo->_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED)) &&
  990. ! (pAppInfo->_ActFlags & (ACTFLG_Assigned | ACTFLG_Published)) )
  991. continue;
  992. if ( lstrcmpi( pAppInfo->_pwszProductId, _pwszProductId ) != 0 )
  993. continue;
  994. //
  995. // One important exception to product code filtering is when there are
  996. // upgrades. We don't do any filtering in that case. It doesn't matter
  997. // whether this is an "upgrade by" or "upgrade over" upgrade.
  998. //
  999. for ( n = 0; n < _Upgrades; n++ )
  1000. {
  1001. if ( _pUpgrades[n].pBaseApp == pAppInfo )
  1002. break;
  1003. }
  1004. if ( n < _Upgrades )
  1005. continue;
  1006. //
  1007. // Now we know we want to override the lower precedence app so we
  1008. // set it to orphan. We don't want to do an uninstall, if a
  1009. // tranform conflict requires this, that will be detected later.
  1010. // Note that if the lower precedence app is not already present on
  1011. // the machine then it's action will be changed to ACTION_NONE in
  1012. // Pass4. But we still set it to ACTION_ORPHAN here so that none of
  1013. // it's upgrade settings will be applied in it's Pass3.
  1014. //
  1015. // Within a single GPO, language match takes precedence over last
  1016. // modified time.
  1017. //
  1018. if ( (pAppInfo->_LanguageWeight > _LanguageWeight) && (0 == lstrcmpi( pAppInfo->_pwszGPOId, _pwszGPOId )) )
  1019. {
  1020. if ( ! bAnalyzeForRsopOnly )
  1021. {
  1022. SetAction(
  1023. ACTION_ORPHAN,
  1024. APP_ATTRIBUTE_REMOVALCAUSE_SCOPELOSS,
  1025. pAppInfo);
  1026. DebugMsg((DM_VERBOSE, IDS_UNDO3_ACTION, _pwszDeploymentName, _pwszGPOName, pAppInfo->_pwszDeploymentName, pAppInfo->_pwszGPOName));
  1027. }
  1028. (void) pAppInfo->UpdatePrecedence( this, APP_ATTRIBUTE_REASON_VALUE_LANGUAGE );
  1029. bAnalyzeForRsopOnly = TRUE;
  1030. }
  1031. else
  1032. {
  1033. if ( ! bAnalyzeForRsopOnly )
  1034. {
  1035. pAppInfo->SetAction(
  1036. ACTION_ORPHAN,
  1037. APP_ATTRIBUTE_REMOVALCAUSE_PRODUCT,
  1038. this);
  1039. DebugMsg((DM_VERBOSE, IDS_UNDO6_ACTION, pAppInfo->_pwszDeploymentName, pAppInfo->_pwszGPOName, _pwszDeploymentName, _pwszGPOName));
  1040. }
  1041. (void) UpdatePrecedence( pAppInfo, APP_ATTRIBUTE_REASON_VALUE_PRODUCT );
  1042. }
  1043. }
  1044. _pManApp->AppList().ResetEnd();
  1045. }
  1046. void
  1047. CAppInfo::SetActionPass3()
  1048. {
  1049. static const UCHAR PolicyForceBaseNone[BASE_STATE_CHOICES][UPGRADE_STATE_CHOICES] =
  1050. {
  1051. { NO, NO, NO, NO },
  1052. { SPECIAL1, SPECIAL1, NO, NO },
  1053. { NO, NO, NO, NO },
  1054. { NO, NO, NO, NO }
  1055. };
  1056. static const UCHAR PolicyForceUpgradeNone[BASE_STATE_CHOICES][UPGRADE_STATE_CHOICES] =
  1057. {
  1058. { NO, NO, NO, NO },
  1059. { SPECIAL2, SPECIAL2, NO, NO },
  1060. { YES, SPECIAL2, NO, NO },
  1061. { YES, SPECIAL2, NO, NO } };
  1062. static const UCHAR PolicyApplyUpgrade[BASE_STATE_CHOICES][UPGRADE_STATE_CHOICES] =
  1063. {
  1064. { NO, NO, NO, NO },
  1065. { NO, NO, YES, YES },
  1066. { NO, SPECIAL1, YES, YES },
  1067. { NO, SPECIAL1, YES, YES }
  1068. };
  1069. static const UCHAR ARPForceBaseNone[BASE_STATE_CHOICES][UPGRADE_STATE_CHOICES] =
  1070. {
  1071. { SPECIAL1, SPECIAL1, YES, YES },
  1072. { NO, NO, YES, YES },
  1073. { NO, NO, YES, YES },
  1074. { NO, NO, YES, YES }
  1075. };
  1076. //
  1077. // In pass three, we may modify this app's or other app's action based upon
  1078. // upgrade relationships between the set of apps in a policy run.
  1079. //
  1080. //
  1081. // In reporting mode, we perform no processing, all apps that currently
  1082. // apply (i.e. all apps in the gpo) will be logged
  1083. //
  1084. if ( _pManApp->GetRsopContext()->IsReportingModeEnabled() )
  1085. {
  1086. return;
  1087. }
  1088. if ( _pManApp->NoChanges() )
  1089. return;
  1090. if ( ! _Upgrades )
  1091. return;
  1092. BOOL bAnalyzeForRsopOnly;
  1093. bAnalyzeForRsopOnly = FALSE;
  1094. if ( (ACTION_UNINSTALL == _Action) || (ACTION_ORPHAN == _Action) )
  1095. {
  1096. //
  1097. // Even if this app is not applied, we want to be sure that
  1098. // it doesn't have some upgrades
  1099. //
  1100. if ( _pManApp->GetRsopContext()->IsRsopEnabled() )
  1101. {
  1102. bAnalyzeForRsopOnly = TRUE;
  1103. }
  1104. else
  1105. {
  1106. return;
  1107. }
  1108. }
  1109. if ( ! (_ActFlags & (ACTFLG_Assigned | ACTFLG_Published)) )
  1110. return;
  1111. for ( DWORD n = 0; n < _Upgrades; n++ )
  1112. {
  1113. CAppInfo * pBaseApp;
  1114. DWORD BaseIndex;
  1115. DWORD UpgradeIndex;
  1116. BOOL bBasePresent;
  1117. BOOL bBaseToApply;
  1118. BOOL bUpgradePresent;
  1119. BOOL bUpgradeForced;
  1120. BOOL bUpgradeToApply;
  1121. BOOL bApplyUpgrade;
  1122. if ( ! (_pUpgrades[n].Flags & UPGRADE_OVER) )
  1123. continue;
  1124. pBaseApp = _pUpgrades[n].pBaseApp;
  1125. if ( ! pBaseApp )
  1126. continue;
  1127. //
  1128. // Notes about the state settings :
  1129. //
  1130. // BasePresent should be set to FALSE if the app is set to be unmanaged and the
  1131. // upgrade is not forced. This is to ensure the if the upgrade app is assigned
  1132. // it will be applied. Likewise, if the upgrade is forced then we want to treat
  1133. // the base app as present if it was currently managed. That is to ensure that
  1134. // the upgrade will apply even if the base app is already set to be removed.
  1135. //
  1136. //
  1137. // Four conditions under which an upgrade is forced :
  1138. // 1. During an install from ARP or fileext/clsid activation.
  1139. // 2. If the app is configured to force it's upgrades.
  1140. // 3. If the upgrade link was reversed because of policy precedence (see InitializePass0)
  1141. // 4. Whenever an app is restored after a profile sync problem (see CManagedAppProcessor::GetLostApps)
  1142. //
  1143. bUpgradeForced = _DemandInstall ||
  1144. (_ActFlags & ACTFLG_ForceUpgrade) ||
  1145. (_pUpgrades[n].Flags & UPGRADE_FORCE) ||
  1146. (_State & APPSTATE_RESTORED);
  1147. bBasePresent = ( pBaseApp->_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED) );
  1148. if ( ! _pManApp->GetRsopContext()->IsPlanningModeEnabled() )
  1149. {
  1150. if ( ! bUpgradeForced && ((ACTION_ORPHAN == pBaseApp->_Action) || (ACTION_UNINSTALL == pBaseApp->_Action)) )
  1151. bBasePresent = FALSE;
  1152. }
  1153. else if ( CRsopAppContext::POLICY_REFRESH == _pManApp->GetRsopContext()->GetContext() )
  1154. {
  1155. if ( ! ( ( _ActFlags & ACTFLG_Assigned ) && ! ( pBaseApp->_ActFlags & ACTFLG_Assigned ) ) )
  1156. {
  1157. bBasePresent = TRUE;
  1158. }
  1159. else
  1160. {
  1161. bBasePresent = FALSE;
  1162. }
  1163. }
  1164. if ( _pManApp->ARPList() )
  1165. bBaseToApply = pBaseApp->_State & APPSTATE_ASSIGNED;
  1166. else
  1167. bBaseToApply = (ACTION_APPLY == pBaseApp->_Action) || (ACTION_INSTALL == pBaseApp->_Action);
  1168. bUpgradePresent = _State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED);
  1169. if ( _pManApp->ARPList() )
  1170. bUpgradeToApply = _State & APPSTATE_ASSIGNED;
  1171. else
  1172. bUpgradeToApply = (ACTION_APPLY == _Action) || (ACTION_INSTALL == _Action);
  1173. if ( _pManApp->GetRsopContext()->IsPlanningModeEnabled() &&
  1174. ( CRsopAppContext::ARPLIST == _pManApp->GetRsopContext()->GetContext() ) )
  1175. {
  1176. if ( ( _ActFlags & ACTFLG_Assigned ) && ! ( pBaseApp->_ActFlags & ACTFLG_Assigned ) )
  1177. {
  1178. bUpgradeToApply = TRUE;
  1179. bUpgradePresent = TRUE;
  1180. }
  1181. }
  1182. DebugMsg((DM_VERBOSE, IDS_UPGRADE_INFO, _pwszDeploymentName, _pwszGPOName, pBaseApp->_pwszDeploymentName, pBaseApp->_pwszGPOName, bBasePresent, bBaseToApply, bUpgradePresent, bUpgradeToApply, bUpgradeForced));
  1183. if ( bBasePresent )
  1184. BaseIndex = bBaseToApply ? BASE_STATE_PRESENT_APPLY : BASE_STATE_PRESENT_NOTAPPLY;
  1185. else
  1186. BaseIndex = bBaseToApply ? BASE_STATE_ABSENT_APPLY : BASE_STATE_ABSENT_NOTAPPLY;
  1187. if ( bUpgradeForced )
  1188. UpgradeIndex = bUpgradeToApply ? UPGRADE_STATE_FORCED_APPLY : UPGRADE_STATE_FORCED_NOTAPPLY;
  1189. else
  1190. UpgradeIndex = bUpgradeToApply ? UPGRADE_STATE_NOTFORCED_APPLY : UPGRADE_STATE_NOTFORCED_NOTAPPLY;
  1191. //
  1192. // In the case where we are constructing the list to show in ARP, the
  1193. // only decision is whether to hide the base app.
  1194. //
  1195. if ( _pManApp->ARPList() )
  1196. {
  1197. if ( (YES == ARPForceBaseNone[BaseIndex][UpgradeIndex]) ||
  1198. ((SPECIAL1 == ARPForceBaseNone[BaseIndex][UpgradeIndex]) && bUpgradePresent) )
  1199. {
  1200. if ( ! bAnalyzeForRsopOnly )
  1201. {
  1202. DebugMsg((DM_VERBOSE, IDS_UNDO4_ACTION, pBaseApp->_pwszDeploymentName, pBaseApp->_pwszGPOName, _pwszDeploymentName, _pwszGPOName));
  1203. pBaseApp->SetAction(
  1204. ACTION_NONE,
  1205. APP_ATTRIBUTE_REMOVALCAUSE_NONE,
  1206. this);
  1207. }
  1208. (void) UpdatePrecedence( pBaseApp, APP_ATTRIBUTE_REASON_VALUE_UPGRADE );
  1209. }
  1210. continue;
  1211. }
  1212. //
  1213. // The rest of this code executes when we are running policy in winlogon
  1214. // or when doing a demand install.
  1215. //
  1216. if ( (YES == PolicyForceBaseNone[BaseIndex][UpgradeIndex]) ||
  1217. ((SPECIAL1 == PolicyForceBaseNone[BaseIndex][UpgradeIndex]) && bUpgradePresent) )
  1218. {
  1219. if ( ! bAnalyzeForRsopOnly )
  1220. {
  1221. DebugMsg((DM_VERBOSE, IDS_UNDO1_ACTION, pBaseApp->_pwszDeploymentName, pBaseApp->_pwszGPOName, _pwszDeploymentName, _pwszGPOName));
  1222. pBaseApp->SetAction(
  1223. ACTION_NONE,
  1224. APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE,
  1225. this);
  1226. }
  1227. }
  1228. if ( (YES == PolicyForceUpgradeNone[BaseIndex][UpgradeIndex]) ||
  1229. ((SPECIAL2 == PolicyForceUpgradeNone[BaseIndex][UpgradeIndex]) && ! bUpgradePresent) )
  1230. {
  1231. if ( ! bAnalyzeForRsopOnly )
  1232. {
  1233. DebugMsg((DM_VERBOSE, IDS_UNDO2_ACTION, _pwszDeploymentName, _pwszGPOName, pBaseApp->_pwszDeploymentName, pBaseApp->_pwszGPOName));
  1234. SetAction(
  1235. ACTION_NONE,
  1236. APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE,
  1237. pBaseApp);
  1238. }
  1239. (void) pBaseApp->UpdatePrecedence( this, APP_ATTRIBUTE_REASON_VALUE_NONFORCEDUPGRADE );
  1240. }
  1241. bApplyUpgrade = (YES == PolicyApplyUpgrade[BaseIndex][UpgradeIndex]) ||
  1242. ((SPECIAL1 == PolicyApplyUpgrade[BaseIndex][UpgradeIndex]) && bUpgradePresent);
  1243. if ( ! bApplyUpgrade )
  1244. {
  1245. if ( _pManApp->GetRsopContext()->IsPlanningModeEnabled() &&
  1246. ( CRsopAppContext::POLICY_REFRESH == _pManApp->GetRsopContext()->GetContext() ) &&
  1247. ( ( ACTION_APPLY == _Action ) || ( ACTION_INSTALL == _Action ) ) )
  1248. {
  1249. UpdatePrecedence( pBaseApp, APP_ATTRIBUTE_REASON_VALUE_UPGRADE );
  1250. }
  1251. continue;
  1252. }
  1253. //
  1254. // At this point we know that this upgrade relationship is set to be
  1255. // applied.
  1256. //
  1257. (void) UpdatePrecedence( pBaseApp, APP_ATTRIBUTE_REASON_VALUE_UPGRADE );
  1258. if ( _pManApp->GetRsopContext()->IsRsopEnabled() )
  1259. {
  1260. if ( bBasePresent )
  1261. {
  1262. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_UPGRADE;
  1263. }
  1264. }
  1265. //
  1266. // If we are only here to ensure that we get all the upgrades for RSoP,
  1267. // we should leave now since we know that the upgrade is enforced
  1268. //
  1269. if ( bAnalyzeForRsopOnly )
  1270. {
  1271. return;
  1272. }
  1273. //
  1274. // Make sure a full advertise is done for the new app during user policy
  1275. // processing.
  1276. // We don't want this for machine policy, user assign full install option
  1277. // nor ARP since the install action will follow in that case.
  1278. //
  1279. if ( _pManApp->IsUserPolicy() && ! (_ActFlags & ACTFLG_InstallUserAssign) && ! _DemandInstall )
  1280. _State |= APPSTATE_FULL_ADVERTISE;
  1281. //
  1282. // This is for the case when the new upgrade app is published.
  1283. //
  1284. if ( ACTION_NONE == _Action )
  1285. {
  1286. SetAction(
  1287. ACTION_APPLY,
  1288. APP_ATTRIBUTE_APPLYCAUSE_VALUE_UPGRADE,
  1289. NULL);
  1290. DebugMsg((DM_VERBOSE, IDS_ASSIGN4_ACTION, _pwszDeploymentName, _pwszGPOName));
  1291. }
  1292. if ( ! bBasePresent )
  1293. {
  1294. DebugMsg((DM_VERBOSE, IDS_UNDO4_ACTION, pBaseApp->_pwszDeploymentName, pBaseApp->_pwszGPOName, _pwszDeploymentName, _pwszGPOName));
  1295. pBaseApp->_Action = ACTION_NONE;
  1296. continue;
  1297. }
  1298. if ( ! _pManApp->GetRsopContext()->IsPlanningModeEnabled() )
  1299. {
  1300. //
  1301. // Before we start setting the upgrade apps' states, we need to make
  1302. // sure that we can get the new app's script from the sysvol. Because
  1303. // of replication issues, it's possible the script may not be available
  1304. // on the DC we bind to. We don't want to undo the upgraded apps until
  1305. // we know we'll be able to apply the new one.
  1306. //
  1307. _Status = CopyScriptIfNeeded();
  1308. if ( _Status != ERROR_SUCCESS )
  1309. {
  1310. //
  1311. // This may seem strange, but logging all three of these events provides
  1312. // the proper context of the error. This is how a failed upgrade would
  1313. // normally be logged, but in this case the error occurs so early we
  1314. // abort before the normal set of processing is performed that would log
  1315. // the other events. We want to stop early to prevent doing unnecessary
  1316. // uninstalls.
  1317. //
  1318. gpEvents->Upgrade( this, pBaseApp, _pUpgrades[n].Flags & UPGRADE_UNINSTALL );
  1319. gpEvents->Assign( _Status, this );
  1320. gpEvents->UpgradeAbort( _Status, this, pBaseApp, FALSE );
  1321. SetAction(
  1322. ACTION_NONE,
  1323. _dwApplyCause,
  1324. NULL);
  1325. pBaseApp->_bRollback = TRUE;
  1326. return;
  1327. }
  1328. }
  1329. _pUpgrades[n].Flags |= UPGRADE_APPLIED;
  1330. if ( ! _pManApp->GetRsopContext()->IsPlanningModeEnabled() )
  1331. {
  1332. if ( _pUpgrades[n].Flags & UPGRADE_UNINSTALL )
  1333. {
  1334. pBaseApp->SetAction(
  1335. ACTION_UNINSTALL,
  1336. APP_ATTRIBUTE_REMOVALCAUSE_UPGRADE,
  1337. this);
  1338. gpEvents->Upgrade( this, pBaseApp, TRUE );
  1339. }
  1340. else // _pUpgrades[n].Flags & UPGRADE_NOUNINSTALL
  1341. {
  1342. pBaseApp->SetAction(
  1343. ACTION_ORPHAN,
  1344. APP_ATTRIBUTE_REMOVALCAUSE_UPGRADE,
  1345. this);
  1346. gpEvents->Upgrade( this, pBaseApp, FALSE );
  1347. }
  1348. }
  1349. }
  1350. }
  1351. void
  1352. CAppInfo::SetActionPass4()
  1353. {
  1354. //
  1355. // In pass four we look for various cases of simultaneous advertise and
  1356. // unadvertise of the same product or other action states that need
  1357. // slight changes based on all of the inter-deployment processing we've
  1358. // finished.
  1359. //
  1360. //
  1361. // In reporting mode, we perform no processing, all apps that currently
  1362. // apply (i.e. all apps in the gpo) will be logged
  1363. //
  1364. if ( _pManApp->GetRsopContext()->IsReportingModeEnabled() )
  1365. {
  1366. return;
  1367. }
  1368. //
  1369. // If this product is to be assigned, check if the same product is being
  1370. // uninstalled now as well. If so, we switch this app to be applied async,
  1371. // so that it will get assigned again after the uninstall action.
  1372. //
  1373. CAppInfo * pAppInfo;
  1374. //
  1375. // If an app is set to orphan, but we don't even have it in the registry,
  1376. // then we can just fall back to do nothing.
  1377. // This can happen for upgrades of assigned apps that were previously
  1378. // applied.
  1379. //
  1380. if ( ACTION_ORPHAN == _Action )
  1381. {
  1382. if ( ! (_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED | APPSTATE_SCRIPT_EXISTED)) )
  1383. {
  1384. SetAction(
  1385. ACTION_NONE,
  1386. APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE,
  1387. NULL);
  1388. DebugMsg((DM_VERBOSE, IDS_NONE_ACTION2, _pwszDeploymentName, _pwszGPOName));
  1389. }
  1390. }
  1391. for ( _pManApp->AppList().Reset(), pAppInfo = (CAppInfo *) _pManApp->AppList().GetCurrentItem();
  1392. pAppInfo;
  1393. _pManApp->AppList().MoveNext(), pAppInfo = (CAppInfo *) _pManApp->AppList().GetCurrentItem() )
  1394. {
  1395. if ( pAppInfo == this )
  1396. break;
  1397. if ( lstrcmpi( pAppInfo->_pwszProductId, _pwszProductId ) != 0 )
  1398. continue;
  1399. //
  1400. // When the lower precedent app is set to be uninstalled, we switch it
  1401. // to orphan if the higher precedent app is already on the machine.
  1402. // This holds even if the higher precedent app is set to be orphaned
  1403. // or uninstalled.
  1404. //
  1405. if ( ACTION_UNINSTALL == pAppInfo->_Action )
  1406. {
  1407. if ( _State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED) )
  1408. {
  1409. DebugMsg((DM_VERBOSE, IDS_UNDO5_ACTION, pAppInfo->_pwszDeploymentName, pAppInfo->_pwszGPOName, _pwszDeploymentName, _pwszGPOName));
  1410. pAppInfo->SetAction(
  1411. ACTION_ORPHAN,
  1412. APP_ATTRIBUTE_REMOVALCAUSE_PRODUCT,
  1413. this);
  1414. }
  1415. }
  1416. }
  1417. _pManApp->AppList().ResetEnd();
  1418. }
  1419. void
  1420. CAppInfo::SetAction(
  1421. APPACTION AppAction,
  1422. DWORD Reason,
  1423. CAppInfo* pAppCause
  1424. )
  1425. {
  1426. _Action = AppAction;
  1427. if ( ( _Action == ACTION_APPLY ) ||
  1428. ( _Action == ACTION_INSTALL ) ||
  1429. ( _Action == ACTION_REINSTALL) )
  1430. {
  1431. _dwApplyCause = Reason;
  1432. }
  1433. else if ( ( _Action == ACTION_ORPHAN ) ||
  1434. ( _Action == ACTION_UNINSTALL ) )
  1435. {
  1436. _dwRemovalCause = Reason;
  1437. if ( pAppCause )
  1438. {
  1439. HRESULT hr;
  1440. hr = SetRemovingDeploymentId( &(pAppCause->_DeploymentId) );
  1441. if ( FAILED( hr ) )
  1442. {
  1443. _pManApp->GetRsopContext()->DisableRsop( hr );
  1444. }
  1445. }
  1446. }
  1447. else
  1448. {
  1449. _dwRemovalCause = APP_ATTRIBUTE_REMOVALCAUSE_NONE;
  1450. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE;
  1451. }
  1452. }
  1453. DWORD
  1454. CAppInfo::ProcessApplyActions()
  1455. {
  1456. DWORD n;
  1457. DWORD ScriptFlags;
  1458. if ( _Status != ERROR_SUCCESS )
  1459. return _Status;
  1460. switch ( _Action )
  1461. {
  1462. case ACTION_NONE :
  1463. //
  1464. // If policy has changed, then we want to rewrite our state even for apps
  1465. // which we have but which are not set to apply. This is to update any
  1466. // settings like UI level or orphan/uninstall at policy removal.
  1467. //
  1468. if ( ! _pManApp->NoChanges() && (_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED)) )
  1469. (void) Assign( 0, FALSE, TRUE );
  1470. break;
  1471. case ACTION_APPLY :
  1472. //
  1473. // Note that apply actions can be processed during an async refresh, as long as they
  1474. // do not lead to an install
  1475. //
  1476. case ACTION_INSTALL :
  1477. case ACTION_REINSTALL :
  1478. BOOL bUpgradeComplete;
  1479. bUpgradeComplete = FALSE;
  1480. if ( ! _DemandInstall )
  1481. {
  1482. //
  1483. // Before applying an app which is an upgrade of something
  1484. // already on the machine, we make sure that all necessary actions
  1485. // on the old apps completed successfully. If there were any errors in
  1486. // the uninstalls, then the upgrade app is not applied.
  1487. // Upgrade processed through ARP actions are transacted differently
  1488. // since they involve an install of the new app, so this does not
  1489. // apply in that case.
  1490. //
  1491. for ( n = 0; n < _Upgrades; n++ )
  1492. {
  1493. if ( ! _pUpgrades[n].pBaseApp || ! (_pUpgrades[n].Flags & UPGRADE_OVER) )
  1494. continue;
  1495. // Abort and fail if any of the upgraded app removals failed.
  1496. if ( _pUpgrades[n].pBaseApp->_Status != ERROR_SUCCESS )
  1497. {
  1498. DWORD retStatus = RollbackUpgrades();
  1499. if ( retStatus == ERROR_SUCCESS )
  1500. {
  1501. retStatus = _pUpgrades[n].pBaseApp->_Status;
  1502. }
  1503. return retStatus;
  1504. }
  1505. // Remember if any of the base apps were actually present.
  1506. if ( _pUpgrades[n].pBaseApp->_State & (APPSTATE_PUBLISHED | APPSTATE_ASSIGNED) )
  1507. bUpgradeComplete = TRUE;
  1508. }
  1509. }
  1510. ScriptFlags = 0;
  1511. //
  1512. // Reinstalls require recopying the script file because the msi
  1513. // data may have been modified in a way which changes the script
  1514. // data.
  1515. // Also check for a first time advertise where we need to update
  1516. // the registry stored script time.
  1517. //
  1518. if ( (ACTION_REINSTALL == _Action) ||
  1519. ((_DirectoryRevision > 0) && (0 == _ScriptTime.dwLowDateTime) && (0 == _ScriptTime.dwHighDateTime)) )
  1520. {
  1521. WIN32_FIND_DATA FindData;
  1522. HANDLE hFind;
  1523. hFind = FindFirstFile( _pwszGPTScriptPath, &FindData );
  1524. if ( INVALID_HANDLE_VALUE == hFind )
  1525. {
  1526. _Status = GetLastError();
  1527. gpEvents->Reinstall( _Status, this );
  1528. return _Status;
  1529. }
  1530. FindClose( hFind );
  1531. _ScriptTime = FindData.ftLastWriteTime;
  1532. if ( ACTION_REINSTALL == _Action )
  1533. {
  1534. // This will force the script to be recopied.
  1535. _State &= ~APPSTATE_SCRIPT_PRESENT;
  1536. //
  1537. // Force a full readvertise for assigned apps. This catches handles cases where the app
  1538. // is only in an advertised state.
  1539. //
  1540. if ( _ActFlags & ACTFLG_Assigned )
  1541. ScriptFlags = SCRIPTFLAGS_REGDATA_CNFGINFO | SCRIPTFLAGS_CACHEINFO | SCRIPTFLAGS_SHORTCUTS | SCRIPTFLAGS_REGDATA_EXTENSIONINFO;
  1542. }
  1543. }
  1544. //
  1545. // Determine whether this app will require uninstall of an
  1546. // existing unmanaged version of the same application -- note that
  1547. // this call must be made while impersonating
  1548. //
  1549. _bNeedsUnmanagedRemove = RequiresUnmanagedRemoval();
  1550. if ( _Action != ACTION_REINSTALL )
  1551. _Status = Assign( ScriptFlags, TRUE, TRUE );
  1552. else
  1553. _Status = Assign( ScriptFlags, TRUE, FALSE );
  1554. if ( ERROR_INSTALL_TRANSFORM_FAILURE == _Status )
  1555. {
  1556. DebugMsg((DM_VERBOSE, IDS_INSTALL_TRANSFORM, _pwszDeploymentName, _pwszGPOName));
  1557. _State |= APPSTATE_TRANSFORM_CONFLICT;
  1558. _bTransformConflict = TRUE;
  1559. //
  1560. // Though we are not really doing an install, the uninstall is an operation
  1561. // we are performing in order to apply this new deployment of the app. We
  1562. // don't want to scare the user into thinking their app is being
  1563. // totally nuked. So in this case we actually put up the install message.
  1564. //
  1565. _pManApp->LogonMsgInstall( _pwszDeploymentName );
  1566. _Status = Uninstall();
  1567. if ( ERROR_SUCCESS == _Status )
  1568. {
  1569. _Status = Assign();
  1570. }
  1571. _pManApp->LogonMsgApplying();
  1572. }
  1573. else if ( ERROR_SUCCESS != _Status )
  1574. {
  1575. //
  1576. // Ensure that we record an event in this case
  1577. // so RSoP will associate an error with this application
  1578. //
  1579. if ( _Action == ACTION_REINSTALL )
  1580. {
  1581. gpEvents->Assign( _Status, this );
  1582. }
  1583. }
  1584. //
  1585. // If a script is not present, we should check for an unmanaged version of the app if it's going to be applied,
  1586. // since we will want to reinstall if this app is not configured to remove unmanaged installs
  1587. // of the same app.
  1588. //
  1589. // This can also happen if the application temporarily goes out of scope on this machine
  1590. // due to wql filtering or security group filtering, and then comes back into scope.
  1591. //
  1592. //
  1593. // Note that we do this now rather than in SetActions because we want to wait until
  1594. // all unapply actions have taken place before we make this decision
  1595. //
  1596. if ( ! _DemandInstall &&
  1597. ( ACTION_APPLY == _Action || ACTION_INSTALL == _Action ) &&
  1598. ( _State & APPSTATE_SCRIPT_NOT_EXISTED ) &&
  1599. ! _bNeedsUnmanagedRemove )
  1600. {
  1601. DWORD InstallState;
  1602. //
  1603. // We must query the install state since we normally only query
  1604. // the install state when the script exists
  1605. //
  1606. InstallState = gpfnMsiQueryProductState( _pwszProductId );
  1607. if ( ( INSTALLSTATE_DEFAULT == InstallState ) ||
  1608. ( INSTALLSTATE_LOCAL == InstallState ) )
  1609. {
  1610. SetAction(
  1611. ACTION_REINSTALL,
  1612. _dwApplyCause,
  1613. NULL);
  1614. DebugMsg((DM_VERBOSE, IDS_REINSTALL_ACTION3, _pwszDeploymentName, _pwszGPOName));
  1615. }
  1616. }
  1617. if ( ERROR_SUCCESS == _Status )
  1618. {
  1619. if ( ACTION_INSTALL == _Action )
  1620. {
  1621. _pManApp->LogonMsgInstall( _pwszDeploymentName );
  1622. _Status = Install();
  1623. _pManApp->LogonMsgApplying();
  1624. }
  1625. else if ( ACTION_REINSTALL == _Action )
  1626. {
  1627. //
  1628. // Note that in the redeploy case, the full reinstall is needed only if the app
  1629. // has already been installed once on this machine.
  1630. // We want to check for any unmanaged install instance, so don't use
  1631. // _InstallState here.
  1632. //
  1633. if ( INSTALLSTATE_DEFAULT == (*gpfnMsiQueryProductState)( _pwszProductId ) )
  1634. {
  1635. _pManApp->LogonMsgInstall( _pwszDeploymentName );
  1636. _Status = Reinstall();
  1637. _pManApp->LogonMsgApplying();
  1638. }
  1639. //
  1640. // Make sure to do this even if we didn't attempt a reinstall so that
  1641. // any new properites of the app get written to our local key.
  1642. //
  1643. if ( ERROR_SUCCESS == _Status )
  1644. _Status = Assign( 0, FALSE, TRUE );
  1645. }
  1646. }
  1647. if ( (ACTION_INSTALL == _Action) &&
  1648. (_Status != ERROR_SUCCESS) &&
  1649. (_State & APPSTATE_SCRIPT_NOT_EXISTED) )
  1650. {
  1651. //
  1652. // Try to rollback the failed install
  1653. //
  1654. Unassign( SCRIPTFLAGS_REGDATA_CNFGINFO | SCRIPTFLAGS_CACHEINFO, TRUE );
  1655. }
  1656. if ( bUpgradeComplete )
  1657. {
  1658. if ( _Status != ERROR_SUCCESS )
  1659. {
  1660. // Ignoring result from RollbackUpgrades since it does not modify _Status, which
  1661. // will be returned by this function and is not equal to ERROR_SUCCESS to begin with.
  1662. (void) RollbackUpgrades();
  1663. break;
  1664. }
  1665. for ( n = 0; n < _Upgrades; n++ )
  1666. {
  1667. if ( ! _pUpgrades[n].pBaseApp || ! (_pUpgrades[n].Flags & UPGRADE_OVER) )
  1668. continue;
  1669. if ( _pUpgrades[n].pBaseApp->_State & (APPSTATE_PUBLISHED | APPSTATE_ASSIGNED) )
  1670. gpEvents->UpgradeComplete( this, _pUpgrades[n].pBaseApp );
  1671. }
  1672. }
  1673. break;
  1674. case ACTION_UNINSTALL :
  1675. case ACTION_ORPHAN :
  1676. break;
  1677. }
  1678. return _Status;
  1679. }
  1680. DWORD
  1681. CAppInfo::ProcessUnapplyActions()
  1682. {
  1683. if ( _Status != ERROR_SUCCESS )
  1684. return _Status;
  1685. switch ( _Action )
  1686. {
  1687. case ACTION_NONE :
  1688. case ACTION_APPLY :
  1689. case ACTION_INSTALL :
  1690. case ACTION_REINSTALL :
  1691. break;
  1692. case ACTION_UNINSTALL :
  1693. //
  1694. // During async refreshes, we will not process any unapply actions as that
  1695. // would be disruptive to the user. This also prevents rip n replace upgrades,
  1696. // since an unapply action is required for the base app and this will set the error
  1697. // for the base app so that the upgrade app is not assigned.
  1698. //
  1699. if ( _pManApp->Async() )
  1700. {
  1701. DebugMsg((DM_VERBOSE, IDS_ABORT_OPERATION));
  1702. _Status = ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED;
  1703. break;
  1704. }
  1705. if ( _State & APPSTATE_SCRIPT_NOT_EXISTED )
  1706. {
  1707. INSTALLSTATE InstallState;
  1708. //
  1709. // This is a bizarre scenario possible with a roaming profile.
  1710. // It's possible we may be getting the uninstall action for the
  1711. // first time while logging onto a machine where an assignment of
  1712. // the app has never been done.
  1713. // In that case we make our best effort to remove advertise data that
  1714. // may be in the profile. We don't want to do any uninstall action
  1715. // here since we never performed an install action. Note we don't
  1716. // use SCRIPTFLAG_REGDATA_APPINFO because class registrations don't
  1717. // roam. If we can't get the script to do the unadvertise, we continue
  1718. // and unmanage the app.
  1719. //
  1720. //
  1721. // Note that we only want to unadvertise if the app is in the
  1722. // advertised state or not present -- otherwise, we may trash
  1723. // an unmanaged version of the app, or a managed version of the application
  1724. // with the same product id. We check the install state below -- we must
  1725. // call the api to do this since our _InstallState member is only initialized
  1726. // when the script exists, and in this case we know it does not
  1727. //
  1728. InstallState = (*gpfnMsiQueryProductState)( _pwszProductId );
  1729. if ( ( INSTALLSTATE_ADVERTISED == InstallState ) ||
  1730. ( INSTALLSTATE_ABSENT == InstallState ) )
  1731. {
  1732. //
  1733. // Artifically bump up the ref count since an assignment was never done
  1734. // on this machine.
  1735. //
  1736. if ( _pManApp->IsUserPolicy() )
  1737. _AssignCount++;
  1738. if ( ERROR_SUCCESS == CopyScriptIfNeeded() )
  1739. _Status = Unassign( SCRIPTFLAGS_REGDATA_CNFGINFO | SCRIPTFLAGS_CACHEINFO | SCRIPTFLAGS_SHORTCUTS, FALSE );
  1740. }
  1741. }
  1742. else
  1743. {
  1744. _pManApp->LogonMsgUninstall( _pwszDeploymentName );
  1745. _Status = Uninstall( FALSE );
  1746. _pManApp->LogonMsgApplying();
  1747. //
  1748. // If an app is only advertised, then an uninstall will fail with
  1749. // ERROR_INSTALL_SOURCE_ABSENT if the original package source (msi)
  1750. // can not be accessed. This is because the msi is not cached until
  1751. // install time.
  1752. // Uninstall will also fail if the package has been disallowed through
  1753. // software restriction policies.
  1754. // In these cases, we just need to undo the rest of the advertise that
  1755. // we did originally.
  1756. //
  1757. if ( (INSTALLSTATE_ADVERTISED == _InstallState) &&
  1758. ((ERROR_INSTALL_SOURCE_ABSENT == _Status) ||
  1759. (ERROR_INSTALL_PACKAGE_REJECTED == _Status) ||
  1760. (ERROR_INSTALL_TRANSFORM_REJECTED == _Status) ||
  1761. (ERROR_INSTALL_TRANSFORM_FAILURE == _Status)) )
  1762. {
  1763. _Status = Unassign( SCRIPTFLAGS_REGDATA_CNFGINFO | SCRIPTFLAGS_CACHEINFO | SCRIPTFLAGS_SHORTCUTS | SCRIPTFLAGS_REGDATA_EXTENSIONINFO, FALSE );
  1764. }
  1765. if ( ERROR_SUCCESS != _Status )
  1766. {
  1767. gpEvents->Uninstall( _Status, this );
  1768. }
  1769. }
  1770. //
  1771. // On success we can finally remove our own internal state info
  1772. // about this apps.
  1773. //
  1774. if ( ERROR_SUCCESS == _Status )
  1775. _Status = Unassign();
  1776. break;
  1777. case ACTION_ORPHAN :
  1778. //
  1779. // Artifically bump up the ref count since an assignment was never done
  1780. // on this machine.
  1781. //
  1782. if ( (_State & APPSTATE_SCRIPT_NOT_EXISTED) && _pManApp->IsUserPolicy() )
  1783. _AssignCount++;
  1784. _Status = Unassign();
  1785. break;
  1786. }
  1787. return _Status;
  1788. }
  1789. DWORD
  1790. CAppInfo::ProcessTransformConflicts()
  1791. {
  1792. //
  1793. // For RSoP, we need to say which apps were uninstalled due
  1794. // to transform conflicts
  1795. //
  1796. //
  1797. // Since the uninstall was performed as part of installing an app
  1798. // in PRocessApplyActions (upon receiving ERROR_INSTALL_TRANSFORM_FAILURE
  1799. // from MsiAdvertiseScript), any installed apps would have had the same
  1800. // product id and therefore would have been marked to uninstall in a
  1801. // previous pass
  1802. //
  1803. //
  1804. // So first we check to see if this app encountered a transform
  1805. // conflict when it was installed
  1806. //
  1807. if ( _bTransformConflict )
  1808. {
  1809. //
  1810. // Now look for any application with the same product id marked
  1811. // as being removed due to product conflict:
  1812. //
  1813. CAppInfo* pAppInfo;
  1814. for ( _pManApp->AppList().Reset(), pAppInfo = (CAppInfo *) _pManApp->AppList().GetCurrentItem();
  1815. pAppInfo;
  1816. _pManApp->AppList().MoveNext(), pAppInfo = (CAppInfo *) _pManApp->AppList().GetCurrentItem() )
  1817. {
  1818. //
  1819. // Check to see if the current app was removed due to product conflict
  1820. //
  1821. if ( APP_ATTRIBUTE_REMOVALCAUSE_PRODUCT != pAppInfo->_dwRemovalCause )
  1822. continue;
  1823. //
  1824. // See if the current app's product id matches
  1825. //
  1826. if ( lstrcmpi( pAppInfo->_pwszProductId, _pwszProductId ) != 0 )
  1827. continue;
  1828. //
  1829. // Since this app had a product conflict with the current app,
  1830. // it had to have been uninstalled as part of installing this app,
  1831. // so we note this
  1832. //
  1833. pAppInfo->_dwRemovalCause = APP_ATTRIBUTE_REMOVALCAUSE_TRANSFORM;
  1834. }
  1835. _pManApp->AppList().ResetEnd();
  1836. }
  1837. return ERROR_SUCCESS;
  1838. }
  1839. DWORD
  1840. CAppInfo::CopyToManagedApplication(
  1841. MANAGED_APP * pManagedApp
  1842. )
  1843. {
  1844. DWORD cbApplication;
  1845. LONG Error;
  1846. Error = ERROR_SUCCESS;
  1847. //
  1848. // Copy guid data
  1849. //
  1850. StringToGuid(_pwszGPOId, &(pManagedApp->GpoId));
  1851. StringToGuid(_pwszProductId, &(pManagedApp->ProductId));
  1852. //
  1853. // Copy simple data
  1854. //
  1855. pManagedApp->dwVersionHi = _VersionHi;
  1856. pManagedApp->dwVersionLo = _VersionLo;
  1857. pManagedApp->dwRevision = _LocalRevision;
  1858. pManagedApp->Language = _LangId;
  1859. pManagedApp->pszOwner = NULL;
  1860. pManagedApp->pszCompany = NULL;
  1861. pManagedApp->pszComments = NULL;
  1862. pManagedApp->pszContact = NULL;
  1863. //
  1864. // Copy information about the application type -- do
  1865. // a translation from com pathtype constants to Win32
  1866. // constants.
  1867. //
  1868. switch ( _PathType )
  1869. {
  1870. case DrwFilePath:
  1871. pManagedApp->dwPathType = MANAGED_APPTYPE_WINDOWSINSTALLER;
  1872. break;
  1873. case SetupNamePath:
  1874. pManagedApp->dwPathType = MANAGED_APPTYPE_SETUPEXE;
  1875. break;
  1876. default:
  1877. pManagedApp->dwPathType = MANAGED_APPTYPE_UNSUPPORTED;
  1878. }
  1879. pManagedApp->bInstalled = ((_State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED)) != 0);
  1880. //
  1881. // Copy string data
  1882. //
  1883. if (_pwszDeploymentName)
  1884. {
  1885. pManagedApp->pszPackageName = MidlStringDuplicate(_pwszDeploymentName);
  1886. if (!(pManagedApp->pszPackageName))
  1887. {
  1888. Error = ERROR_NOT_ENOUGH_MEMORY;
  1889. goto cleanup;
  1890. }
  1891. }
  1892. if (_pwszGPOName)
  1893. {
  1894. pManagedApp->pszPolicyName = MidlStringDuplicate(_pwszGPOName);
  1895. if (!(pManagedApp->pszPolicyName))
  1896. {
  1897. Error = ERROR_NOT_ENOUGH_MEMORY;
  1898. goto cleanup;
  1899. }
  1900. }
  1901. if (_pwszPublisher)
  1902. {
  1903. pManagedApp->pszPublisher = MidlStringDuplicate(_pwszPublisher);
  1904. if (!(pManagedApp->pszPublisher))
  1905. {
  1906. Error = ERROR_NOT_ENOUGH_MEMORY;
  1907. goto cleanup;
  1908. }
  1909. }
  1910. if (_pwszSupportURL)
  1911. {
  1912. pManagedApp->pszSupportUrl = MidlStringDuplicate(_pwszSupportURL);
  1913. if (!(pManagedApp->pszSupportUrl))
  1914. {
  1915. Error = ERROR_NOT_ENOUGH_MEMORY;
  1916. goto cleanup;
  1917. }
  1918. }
  1919. cleanup:
  1920. if (ERROR_SUCCESS != Error)
  1921. {
  1922. ClearManagedApp( pManagedApp );
  1923. }
  1924. return Error;
  1925. }
  1926. BOOL
  1927. CAppInfo::HasCategory(
  1928. WCHAR * pwszCategory
  1929. )
  1930. {
  1931. for ( DWORD n = 0; n < _cCategories; n++ )
  1932. {
  1933. if ( 0 == lstrcmp( _rgwszCategories[n], pwszCategory ) )
  1934. return TRUE;
  1935. }
  1936. return FALSE;
  1937. }
  1938. DWORD
  1939. CAppInfo::Assign(
  1940. DWORD ScriptFlags, // = 0
  1941. BOOL bDoAdvertise, // = TRUE
  1942. BOOL bAddAppData // = TRUE
  1943. )
  1944. {
  1945. HKEY hkApp;
  1946. WCHAR wszDeploymentId[40];
  1947. DWORD AppState;
  1948. DWORD Status;
  1949. BOOL bAdvertised;
  1950. BOOL bUnmanageUninstall;
  1951. //
  1952. // For async refreshes, We do not want to perform any assignments that are destined to
  1953. // lead to installs since that would disrupt the user. However, pure advertisements
  1954. // are ok -- they cause minimal disruption and no loss of user functionality
  1955. //
  1956. if ( _pManApp->Async() )
  1957. {
  1958. if ( ( ACTION_INSTALL == _Action ) ||
  1959. ( ACTION_REINSTALL == _Action ) )
  1960. {
  1961. DebugMsg((DM_VERBOSE, IDS_ABORT_OPERATION));
  1962. _Status = ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED;
  1963. Status = _Status;
  1964. goto ReportStatus;
  1965. }
  1966. }
  1967. Status = ERROR_SUCCESS;
  1968. bAdvertised = FALSE;
  1969. bUnmanageUninstall = FALSE;
  1970. GuidToString( _DeploymentId, wszDeploymentId );
  1971. if ( ! bDoAdvertise )
  1972. goto SaveAppData;
  1973. DebugMsg((DM_VERBOSE, IDS_ASSIGN, _pwszDeploymentName, _pwszGPOName));
  1974. Status = CopyScriptIfNeeded();
  1975. if ( (Status != ERROR_SUCCESS) && bDoAdvertise && bAddAppData )
  1976. {
  1977. gpEvents->Assign( Status, this );
  1978. return Status;
  1979. }
  1980. //
  1981. // Do this before determining script flags because an uninstall will cause
  1982. // the app state to change.
  1983. //
  1984. Status = EnforceAssignmentSecurity( &bUnmanageUninstall );
  1985. //
  1986. // Note that we check the error status for the call above below -- we
  1987. // do not overwrite the status if it is an error. Better code arrangement
  1988. // is called for here, but we are making the smallest change since an
  1989. // issue with this was found at the end of xpsp1
  1990. //
  1991. if ( 0 == ScriptFlags )
  1992. {
  1993. //
  1994. // Apps which are installed on demand (ARP, shell/com activation) only
  1995. // have the Darwin product registry keys advertised.
  1996. // This is all we need to make the MsiConfigureProduct call in the
  1997. // client work and ensure that if the install must be rolled back, we
  1998. // get back to the true previous state of the machine.
  1999. //
  2000. // The icons/transforms have to be included in any first time advertise
  2001. // because of some bizarre design in Darwin. If we don't advertise
  2002. // it then the app's shorcuts will not have icons even after the install.
  2003. // For subsequent advertises we don't include the icons/transforms because
  2004. // this is a very expensive part of advertisement because it extracts and
  2005. // re-creates icons from the script file. [Removed 12/23/98, we'll see
  2006. // if Darwin handles this correctly now].
  2007. //
  2008. // During policy runs we advertise shortcuts for previously advertised
  2009. // assigned apps.
  2010. //
  2011. // For published apps which we're applying for the first time on a machine
  2012. // we just advertise the config data. Note that the only time a published
  2013. // app is advertised as part of a policy run is for the roaming profile
  2014. // scenario where the app has never been applied to the machine we're now on.
  2015. // We don't want to advertise shorcuts nor class data in this case because
  2016. // only a subset of the product's features may have been installed on the
  2017. // original machine. We want to preserve this feature state.
  2018. //
  2019. // The very first time an assigned app is assigned to a machine we will also
  2020. // advertise the shell class data. But since this is quite heavy
  2021. // weight, we only do it the first time. If it is ever lost somehow,
  2022. // a miss on this info will result in a DS query and install anyway.
  2023. //
  2024. ScriptFlags = SCRIPTFLAGS_REGDATA_CNFGINFO;
  2025. if ( (_State & APPSTATE_SCRIPT_NOT_EXISTED) || ! AppPresent(_InstallState) )
  2026. {
  2027. ScriptFlags |= SCRIPTFLAGS_CACHEINFO;
  2028. //
  2029. // Now we decide whether or not to validate the transform list
  2030. //
  2031. // MsiAdvertiseScript incorrectly detects transform conflicts between a user
  2032. // and machine installed version of the same application, so we
  2033. // only validate transforms for user policy if the application is already
  2034. // in a non absent state per-user. A transform conflict cannot
  2035. // be possible in that case despite what MsiAdvertiseScript claims.
  2036. //
  2037. // We check for the application's presence below -- note that we can't use
  2038. // the _InstallState member since it is not guaranteed to be set when
  2039. // we reach this point.
  2040. //
  2041. // Note : all this code was also added for a win2k-sp3, and xpsp1 fix.
  2042. //
  2043. BOOL bValidateTransforms = TRUE;
  2044. if ( _pManApp->IsUserPolicy() )
  2045. {
  2046. INSTALLSTATE InstallState = (*gpfnMsiQueryProductState)( _pwszProductId );
  2047. WCHAR wszBuffer[8];
  2048. DWORD Size = sizeof(wszBuffer) / sizeof(WCHAR);
  2049. if ( AppPresent(InstallState) )
  2050. {
  2051. //
  2052. // Be sure to use a new error status here so we don't
  2053. // overwrite the existing status which should be checked later
  2054. //
  2055. DWORD ProductInfoStatus;
  2056. ProductInfoStatus = (*gpfnMsiGetProductInfo)(
  2057. _pwszProductId,
  2058. INSTALLPROPERTY_ASSIGNMENTTYPE,
  2059. wszBuffer,
  2060. &Size );
  2061. //
  2062. // Only if we don't already have a failure status should we overwrite
  2063. // the existing status -- otherwise, we will miss the failure in the
  2064. // call to EnforceAssignmentSecurity, which can happen when we need
  2065. // to uninstall an unmanaged app but we're in async refresh. This issue
  2066. // was found at the end of xpsp1 and was caused when this new code was
  2067. // added to properly detect transform conflicts in xpsp1. We are making
  2068. // the smallest change here to restore the failure path to what it was
  2069. // before the transform fix for xpsp1 was made.
  2070. //
  2071. if ( ERROR_SUCCESS == Status )
  2072. {
  2073. Status = ProductInfoStatus;
  2074. }
  2075. // '1' means installed per-machine
  2076. if ( (ERROR_SUCCESS == ProductInfoStatus) && (L'1' == wszBuffer[0]) )
  2077. bValidateTransforms = FALSE; }
  2078. }
  2079. //
  2080. // The application is present, so we must tell Msi to guard against transform
  2081. // conflicts between the existing application and the one we are trying to install
  2082. //
  2083. if ( ! (_State & APPSTATE_TRANSFORM_CONFLICT) && bValidateTransforms )
  2084. ScriptFlags |= SCRIPTFLAGS_VALIDATE_TRANSFORMS_LIST;
  2085. }
  2086. //
  2087. // When an unmanaged instance of the product is uninstall we need to ensure
  2088. // that shortcuts are always added back for the managed product.
  2089. //
  2090. if ( bUnmanageUninstall )
  2091. ScriptFlags |= SCRIPTFLAGS_SHORTCUTS;
  2092. if ( ( _State & APPSTATE_FULL_ADVERTISE ) || _bRestored )
  2093. {
  2094. //
  2095. // This part here means we are in a policy run in winlogon, not
  2096. // in the service doing a demand install. We are advertising
  2097. // an assigned app, a published app which is an upgrade,
  2098. // or a published app which was removed on another logon (possibly
  2099. // another machine) because its gpo went out of scope but has
  2100. // now come back into scope.
  2101. //
  2102. ScriptFlags |= SCRIPTFLAGS_SHORTCUTS;
  2103. //
  2104. // The first time we apply an assigned app on a machine, we do a
  2105. // full advertise. Otherwise, we don't advertise shell class
  2106. // registry data and icon/transform data.
  2107. //
  2108. if ( (_State & APPSTATE_SCRIPT_NOT_EXISTED) || ! AppPresent(_InstallState) )
  2109. ScriptFlags |= SCRIPTFLAGS_REGDATA_EXTENSIONINFO;
  2110. }
  2111. }
  2112. if ( ! _pManApp->IsUserPolicy() )
  2113. ScriptFlags |= SCRIPTFLAGS_MACHINEASSIGN;
  2114. if ( ERROR_SUCCESS == Status )
  2115. {
  2116. DebugMsg((DM_VERBOSE, IDS_ADVERTISE, _pwszDeploymentName, _pwszLocalScriptPath, ScriptFlags));
  2117. Status = CallMsiAdvertiseScript(
  2118. _pwszLocalScriptPath,
  2119. ScriptFlags,
  2120. NULL,
  2121. FALSE );
  2122. }
  2123. if ( ERROR_SUCCESS == Status )
  2124. {
  2125. bAdvertised = TRUE;
  2126. if ( _State & APPSTATE_SCRIPT_NOT_EXISTED )
  2127. _AssignCount++;
  2128. }
  2129. else
  2130. {
  2131. DebugMsg((DM_WARNING, IDS_ADVERTISE_FAIL, _pwszDeploymentName, _pwszLocalScriptPath, Status));
  2132. }
  2133. //
  2134. // Abort early in this case without deleting any management data.
  2135. // The app will be reapplied asynchronously in this case.
  2136. //
  2137. if ( (ACTION_APPLY == _Action) &&
  2138. (ERROR_INSTALL_ALREADY_RUNNING == Status) )
  2139. return Status;
  2140. //
  2141. // If we have a transform conflict with this app, then abort the assign
  2142. // now without removing the app. Callers of this routine will fix up
  2143. // the app state and retry if appropriate.
  2144. //
  2145. if ( ERROR_INSTALL_TRANSFORM_FAILURE == Status )
  2146. return Status;
  2147. SaveAppData:
  2148. //
  2149. // Always set this, even when bAddAppData is FALSE. This controls the
  2150. // UI level used for descriptor based installs from shell & com. The
  2151. // last writer (highest precedence app for a product id) wins.
  2152. //
  2153. if ( ERROR_SUCCESS == Status )
  2154. {
  2155. Status = RegSetValueEx(
  2156. _pManApp->AppmgmtKey(),
  2157. _pwszProductId,
  2158. 0,
  2159. REG_DWORD,
  2160. (LPBYTE) &_InstallUILevel,
  2161. sizeof(DWORD) );
  2162. }
  2163. //
  2164. // We only write/update our registry state if we've gotten info back down
  2165. // from the Directory.
  2166. //
  2167. if ( (ERROR_SUCCESS == Status) && bAddAppData && (_ActFlags != 0) )
  2168. {
  2169. _pManApp->Revert();
  2170. hkApp = 0;
  2171. Status = RegCreateKeyEx(
  2172. _pManApp->AppmgmtKey(),
  2173. wszDeploymentId,
  2174. 0,
  2175. NULL,
  2176. REG_OPTION_NON_VOLATILE,
  2177. KEY_READ | KEY_WRITE,
  2178. NULL,
  2179. &hkApp,
  2180. NULL );
  2181. if ( ERROR_SUCCESS == Status )
  2182. {
  2183. Status = RegSetValueEx(
  2184. hkApp,
  2185. DEPLOYMENTNAMEVALUE,
  2186. 0,
  2187. REG_SZ,
  2188. (LPBYTE) _pwszDeploymentName,
  2189. lstrlen( _pwszDeploymentName ) * sizeof(WCHAR) + sizeof(WCHAR) );
  2190. }
  2191. if ( ERROR_SUCCESS == Status )
  2192. {
  2193. Status = RegSetValueEx(
  2194. hkApp,
  2195. GPONAMEVALUE,
  2196. 0,
  2197. REG_SZ,
  2198. (LPBYTE) _pwszGPOName,
  2199. lstrlen( _pwszGPOName ) * sizeof(WCHAR) + sizeof(WCHAR) );
  2200. }
  2201. if ( ERROR_SUCCESS == Status )
  2202. {
  2203. Status = RegSetValueEx(
  2204. hkApp,
  2205. GPOIDVALUE,
  2206. 0,
  2207. REG_SZ,
  2208. (LPBYTE) _pwszGPOId,
  2209. lstrlen( _pwszGPOId ) * sizeof(WCHAR) + sizeof(WCHAR) );
  2210. }
  2211. if ( ERROR_SUCCESS == Status )
  2212. {
  2213. Status = RegSetValueEx(
  2214. hkApp,
  2215. PRODUCTIDVALUE,
  2216. 0,
  2217. REG_SZ,
  2218. (LPBYTE) _pwszProductId,
  2219. lstrlen( _pwszProductId ) * sizeof(WCHAR) + sizeof(WCHAR) );
  2220. }
  2221. if ( _pwszSupportURL && (ERROR_SUCCESS == Status) )
  2222. {
  2223. Status = RegSetValueEx(
  2224. hkApp,
  2225. SUPPORTURL,
  2226. 0,
  2227. REG_SZ,
  2228. (LPBYTE) _pwszSupportURL,
  2229. lstrlen( _pwszSupportURL ) * sizeof(WCHAR) + sizeof(WCHAR) );
  2230. }
  2231. if ( (ERROR_SUCCESS == Status) && (_Overrides > 0) )
  2232. {
  2233. WCHAR * pwszSupercededIds;
  2234. WCHAR * pwszString;
  2235. pwszSupercededIds = new WCHAR[(_Overrides * (GUIDSTRLEN + 1)) + 1];
  2236. if ( pwszSupercededIds )
  2237. {
  2238. pwszString = pwszSupercededIds;
  2239. for ( DWORD n = 0; n < _Overrides; n++ )
  2240. {
  2241. GuidToString( _pOverrides[n], pwszString );
  2242. pwszString += GUIDSTRLEN + 1;
  2243. }
  2244. *pwszString = 0;
  2245. Status = RegSetValueEx(
  2246. hkApp,
  2247. SUPERCEDEDIDS,
  2248. 0,
  2249. REG_MULTI_SZ,
  2250. (LPBYTE) pwszSupercededIds,
  2251. (_Overrides * (GUIDSTRLEN + 1) + 1) * sizeof(WCHAR) );
  2252. delete [] pwszSupercededIds;
  2253. }
  2254. else
  2255. {
  2256. Status = ERROR_OUTOFMEMORY;
  2257. }
  2258. }
  2259. if ( ERROR_SUCCESS == Status )
  2260. {
  2261. Status = RegSetValueEx(
  2262. hkApp,
  2263. ASSIGNCOUNTVALUE,
  2264. 0,
  2265. REG_DWORD,
  2266. (LPBYTE) &_AssignCount,
  2267. sizeof(DWORD) );
  2268. }
  2269. if ( ERROR_SUCCESS == Status )
  2270. {
  2271. Status = RegSetValueEx(
  2272. hkApp,
  2273. REVISIONVALUE,
  2274. 0,
  2275. REG_DWORD,
  2276. (LPBYTE) &_DirectoryRevision,
  2277. sizeof(DWORD) );
  2278. if ( (ERROR_SUCCESS == Status) && (_DirectoryRevision > 0) )
  2279. {
  2280. Status = RegSetValueEx(
  2281. hkApp,
  2282. SCRIPTTIMEVALUE,
  2283. 0,
  2284. REG_BINARY,
  2285. (LPBYTE) &_ScriptTime,
  2286. sizeof(_ScriptTime) );
  2287. }
  2288. }
  2289. if ( ERROR_SUCCESS == Status )
  2290. {
  2291. Status = RegSetValueEx(
  2292. hkApp,
  2293. INSTALLUI,
  2294. 0,
  2295. REG_DWORD,
  2296. (LPBYTE) &_InstallUILevel,
  2297. sizeof(DWORD) );
  2298. }
  2299. if ( ERROR_SUCCESS == Status )
  2300. {
  2301. if ( _ActFlags )
  2302. {
  2303. AppState = 0;
  2304. //
  2305. // If an app becomes disabled then it gets neither the assigned
  2306. // nor the published state bit.
  2307. //
  2308. if ( _ActFlags & ACTFLG_Assigned )
  2309. AppState |= APPSTATE_ASSIGNED;
  2310. else if ( _ActFlags & ACTFLG_Published )
  2311. AppState |= APPSTATE_PUBLISHED;
  2312. AppState |= (_ActFlags & ACTFLG_UninstallOnPolicyRemoval) ? APPSTATE_POLICYREMOVE_UNINSTALL : APPSTATE_POLICYREMOVE_ORPHAN;
  2313. if ( _bNeedsUnmanagedRemove )
  2314. AppState |= APPSTATE_UNINSTALL_UNMANAGED;
  2315. if ( _ActFlags & ACTFLG_InstallUserAssign )
  2316. AppState |= APPSTATE_INSTALL;
  2317. }
  2318. else
  2319. {
  2320. AppState = _State;
  2321. }
  2322. AppState &= APPSTATE_PERSIST_MASK;
  2323. Status = RegSetValueEx(
  2324. hkApp,
  2325. APPSTATEVALUE,
  2326. 0,
  2327. REG_DWORD,
  2328. (LPBYTE) &AppState,
  2329. sizeof(DWORD) );
  2330. }
  2331. if ( hkApp )
  2332. RegCloseKey( hkApp );
  2333. DWORD impStatus = _pManApp->Impersonate();
  2334. if ( (impStatus != ERROR_SUCCESS) && (Status == ERROR_SUCCESS) )
  2335. {
  2336. Status = impStatus;
  2337. }
  2338. }
  2339. ReportStatus:
  2340. if ( bDoAdvertise && bAddAppData )
  2341. gpEvents->Assign( Status, this );
  2342. //
  2343. // If we hit an error then the destructor of this object will make sure we delete the script file so a full
  2344. // advertise will be tried next time.
  2345. //
  2346. return Status;
  2347. }
  2348. DWORD
  2349. CAppInfo::Install()
  2350. {
  2351. DWORD Status;
  2352. //
  2353. // During async refreshes, we will not install an application as that
  2354. // would be disruptive to the user
  2355. //
  2356. if ( ! _pManApp->Async() )
  2357. {
  2358. //
  2359. // Installs can happen for machine assign apps or for user apps when there
  2360. // are transform conflicts.
  2361. //
  2362. // Always set UI to NONE.
  2363. //
  2364. (*gpfnMsiSetInternalUI)( INSTALLUILEVEL_NONE, NULL );
  2365. DebugMsg((DM_VERBOSE, IDS_INSTALL, _pwszDeploymentName, _pwszGPOName));
  2366. Status = CallMsiConfigureProduct(
  2367. _pwszProductId,
  2368. INSTALLLEVEL_DEFAULT,
  2369. INSTALLSTATE_DEFAULT,
  2370. NULL );
  2371. }
  2372. else
  2373. {
  2374. DebugMsg((DM_VERBOSE, IDS_ABORT_OPERATION));
  2375. _Status = ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED;
  2376. Status = _Status;
  2377. }
  2378. gpEvents->Install( Status, this );
  2379. return Status;
  2380. }
  2381. DWORD
  2382. CAppInfo::Reinstall()
  2383. {
  2384. DWORD Status;
  2385. //
  2386. // For async refreshes, We do not want to reinstall an application
  2387. // since that would disrupt the user
  2388. //
  2389. if ( ! _pManApp->Async() )
  2390. {
  2391. //
  2392. // Reinstalls can happen when a redeploy action is specified in the SI UI.
  2393. // This is normally done when a binary patch is applied to an application.
  2394. //
  2395. // Always set UI to NONE.
  2396. //
  2397. (*gpfnMsiSetInternalUI)( INSTALLUILEVEL_NONE, NULL );
  2398. DebugMsg((DM_VERBOSE, IDS_REINSTALL, _pwszDeploymentName));
  2399. Status = CallMsiReinstallProduct( _pwszProductId );
  2400. }
  2401. else
  2402. {
  2403. DebugMsg((DM_VERBOSE, IDS_ABORT_OPERATION));
  2404. _Status = ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED;
  2405. Status = _Status;
  2406. }
  2407. gpEvents->Reinstall( Status, this );
  2408. return Status;
  2409. }
  2410. DWORD
  2411. CAppInfo::Unassign(
  2412. DWORD ScriptFlags, // = 0
  2413. BOOL bRemoveAppData // = TRUE
  2414. )
  2415. {
  2416. HKEY hkApp;
  2417. WCHAR wszDeploymentId[40];
  2418. DWORD AppState;
  2419. DWORD Status;
  2420. ASSERT( ! _pManApp->GetRsopContext()->IsPlanningModeEnabled() );
  2421. //
  2422. // For async refreshes, We do not want to unassign an application
  2423. // since that would disrupt the user
  2424. //
  2425. if ( _pManApp->Async() )
  2426. {
  2427. DebugMsg((DM_VERBOSE, IDS_ABORT_OPERATION));
  2428. _Status = ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED;
  2429. if ( bRemoveAppData )
  2430. gpEvents->Unassign( _Status, this );
  2431. return _Status;
  2432. }
  2433. GuidToString( _DeploymentId, wszDeploymentId);
  2434. if ( bRemoveAppData )
  2435. DebugMsg((DM_VERBOSE, IDS_UNMANAGE, _pwszDeploymentName));
  2436. Status = STATUS_SUCCESS;
  2437. if ( ScriptFlags != 0 )
  2438. {
  2439. if ( ! _pManApp->IsUserPolicy() )
  2440. ScriptFlags |= SCRIPTFLAGS_MACHINEASSIGN;
  2441. DebugMsg((DM_VERBOSE, IDS_UNADVERTISE, _pwszDeploymentName, _pwszLocalScriptPath));
  2442. Status = CallMsiAdvertiseScript(
  2443. _pwszLocalScriptPath,
  2444. ScriptFlags,
  2445. NULL,
  2446. TRUE );
  2447. // It's possible for the product to be uninstalled without us knowing.
  2448. if ( ERROR_UNKNOWN_PRODUCT == Status )
  2449. Status = ERROR_SUCCESS;
  2450. if ( Status != ERROR_SUCCESS )
  2451. DebugMsg((DM_WARNING, IDS_UNADVERTISE_FAIL, _pwszDeploymentName, _pwszLocalScriptPath, Status));
  2452. }
  2453. if ( (ERROR_SUCCESS == Status) && bRemoveAppData )
  2454. {
  2455. _pManApp->Revert();
  2456. DeleteFile( _pwszLocalScriptPath );
  2457. _State &= ~APPSTATE_SCRIPT_PRESENT;
  2458. //
  2459. // Do not delete the productid->installui hint value when a product is removed
  2460. // because of productid or transform conflicts. In both of these cases it means
  2461. // an app with the same productid is still currently being managed.
  2462. // This is important because the unmanage calls are done last when handling ARP
  2463. // requests and this will inadvertently delete the productid->installui hint value
  2464. // for a product which is still being managed.
  2465. //
  2466. if ( (_dwRemovalCause != APP_ATTRIBUTE_REMOVALCAUSE_PRODUCT) &&
  2467. (_dwRemovalCause != APP_ATTRIBUTE_REMOVALCAUSE_TRANSFORM) )
  2468. RegDeleteValue( _pManApp->AppmgmtKey(), _pwszProductId );
  2469. _AssignCount--;
  2470. if ( _AssignCount > 0 )
  2471. {
  2472. BOOL bUpdateState;
  2473. bUpdateState = TRUE;
  2474. if ( ACTION_ORPHAN == _Action )
  2475. {
  2476. DebugMsg((DM_VERBOSE, IDS_UNMANAGE_ORPHAN, _pwszDeploymentName));
  2477. AppState = APPSTATE_ORPHANED;
  2478. }
  2479. else if ( ( ACTION_UNINSTALL == _Action ) || ( ACTION_NONE == _Action ) )
  2480. {
  2481. DebugMsg((DM_VERBOSE, IDS_UNMANAGE_UNINSTALL, _pwszDeploymentName));
  2482. AppState = APPSTATE_UNINSTALLED;
  2483. }
  2484. else
  2485. {
  2486. bUpdateState = FALSE;
  2487. }
  2488. Status = RegOpenKeyEx(
  2489. _pManApp->AppmgmtKey(),
  2490. wszDeploymentId,
  2491. 0,
  2492. KEY_ALL_ACCESS,
  2493. &hkApp );
  2494. if ( ERROR_SUCCESS == Status )
  2495. {
  2496. DWORD RemovedState;
  2497. RemovedState = _State & APPSTATE_PERSIST_MASK;
  2498. if ( _pManApp->IsRemovingPolicies() )
  2499. {
  2500. Status = RegSetValueEx(
  2501. hkApp,
  2502. REMOVEDGPOSTATE,
  2503. 0,
  2504. REG_DWORD,
  2505. (LPBYTE) &RemovedState,
  2506. sizeof(DWORD) );
  2507. }
  2508. if ( bUpdateState &&
  2509. ( ERROR_SUCCESS == Status ) )
  2510. {
  2511. Status = RegSetValueEx(
  2512. hkApp,
  2513. APPSTATEVALUE,
  2514. 0,
  2515. REG_DWORD,
  2516. (LPBYTE) &AppState,
  2517. sizeof(DWORD) );
  2518. }
  2519. if ( ERROR_SUCCESS == Status )
  2520. {
  2521. Status = RegSetValueEx(
  2522. hkApp,
  2523. ASSIGNCOUNTVALUE,
  2524. 0,
  2525. REG_DWORD,
  2526. (LPBYTE) &_AssignCount,
  2527. sizeof(DWORD) );
  2528. }
  2529. RegCloseKey( hkApp );
  2530. }
  2531. if ( Status != ERROR_SUCCESS )
  2532. {
  2533. Status = ERROR_SUCCESS;
  2534. RegDeleteKey( _pManApp->AppmgmtKey(), wszDeploymentId );
  2535. }
  2536. }
  2537. else
  2538. {
  2539. RegDeleteKey( _pManApp->AppmgmtKey(), wszDeploymentId );
  2540. }
  2541. DWORD impStatus = _pManApp->Impersonate();
  2542. if ( (impStatus != ERROR_SUCCESS) && (Status == ERROR_SUCCESS) )
  2543. {
  2544. Status = impStatus;
  2545. }
  2546. }
  2547. if ( bRemoveAppData )
  2548. gpEvents->Unassign( Status, this );
  2549. return Status;
  2550. }
  2551. DWORD
  2552. CAppInfo::Uninstall(
  2553. BOOL bLogFailure // = TRUE
  2554. )
  2555. {
  2556. DWORD Status;
  2557. //
  2558. // For async refreshes, We do not want to uninstall an application
  2559. // since that would disrupt the user
  2560. //
  2561. if ( ! _pManApp->Async() )
  2562. {
  2563. // Uninstalls happen in our background thread. Always set UI to NONE.
  2564. (*gpfnMsiSetInternalUI)( INSTALLUILEVEL_NONE, NULL );
  2565. DebugMsg((DM_VERBOSE, IDS_UNINSTALL, _pwszDeploymentName, _pwszGPOName));
  2566. Status = CallMsiConfigureProduct(
  2567. _pwszProductId,
  2568. INSTALLLEVEL_MAXIMUM,
  2569. INSTALLSTATE_ABSENT,
  2570. NULL );
  2571. // It's possible for the product to be uninstalled without us knowing.
  2572. if ( ERROR_UNKNOWN_PRODUCT == Status )
  2573. Status = ERROR_SUCCESS;
  2574. }
  2575. else
  2576. {
  2577. DebugMsg((DM_VERBOSE, IDS_ABORT_OPERATION));
  2578. _Status = ERROR_SYNC_FOREGROUND_REFRESH_REQUIRED;
  2579. Status = _Status;
  2580. }
  2581. if ( bLogFailure )
  2582. {
  2583. gpEvents->Uninstall( Status, this );
  2584. }
  2585. return Status;
  2586. }
  2587. HRESULT
  2588. CAppInfo::Write( CPolicyRecord* pRecord )
  2589. {
  2590. HRESULT hr;
  2591. LONG EntryType;
  2592. WCHAR wszDeploymentId[ MAX_SZGUID_LEN ];
  2593. EntryType = GetPublicRsopEntryType();
  2594. hr = pRecord->SetValue(
  2595. APP_ATTRIBUTE_ENTRYTYPE,
  2596. EntryType);
  2597. if (FAILED(hr))
  2598. {
  2599. goto cleanup;
  2600. }
  2601. hr = pRecord->SetValue(
  2602. RSOP_ATTRIBUTE_NAME,
  2603. _pwszDeploymentName);
  2604. REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_NAME, hr )
  2605. if (FAILED(hr))
  2606. {
  2607. goto cleanup;
  2608. }
  2609. GuidToString( _DeploymentId, wszDeploymentId);
  2610. hr = pRecord->SetValue(
  2611. APP_ATTRIBUTE_APPID,
  2612. wszDeploymentId);
  2613. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_APPID, hr );
  2614. if (FAILED(hr))
  2615. {
  2616. goto cleanup;
  2617. }
  2618. hr = pRecord->SetValue(
  2619. APP_ATTRIBUTE_ENTRYTYPE,
  2620. EntryType);
  2621. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ENTRYTYPE, hr )
  2622. if (FAILED(hr))
  2623. {
  2624. goto cleanup;
  2625. }
  2626. //
  2627. // For the remaining attributes, we will ignore failures -- at this
  2628. // point, they have the application name, which is useful in
  2629. // and of itself.
  2630. //
  2631. //
  2632. // These properties are only written for new records -- if we are creating
  2633. // an instance from an existing record, will not write these properties since
  2634. // the current instance already has them set correctly and the reason that we're
  2635. // re-using this instance is that we do not have this information
  2636. //
  2637. if ( pRecord->AlreadyExists() )
  2638. {
  2639. return hr;
  2640. }
  2641. {
  2642. SYSTEMTIME CurrentTime;
  2643. //
  2644. // This does not fail
  2645. //
  2646. GetSystemTime( &CurrentTime );
  2647. hr = pRecord->SetValue(
  2648. RSOP_ATTRIBUTE_CREATIONTIME,
  2649. &CurrentTime);
  2650. REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_CREATIONTIME, hr );
  2651. }
  2652. hr = pRecord->SetValue(
  2653. RSOP_ATTRIBUTE_GPOID,
  2654. _pwszGPODSPath);
  2655. REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_GPOID, hr )
  2656. hr = pRecord->SetValue(
  2657. RSOP_ATTRIBUTE_SOMID,
  2658. _pwszSOMId);
  2659. REPORT_ATTRIBUTE_SET_STATUS( RSOP_ATTRIBUTE_SOMID, hr )
  2660. hr = pRecord->SetValue(
  2661. APP_ATTRIBUTE_ENTRYTYPE,
  2662. EntryType);
  2663. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ENTRYTYPE, hr )
  2664. hr = pRecord->SetValue(
  2665. APP_ATTRIBUTE_SECURITY_DESCRIPTOR,
  2666. _rgSecurityDescriptor,
  2667. _cbSecurityDescriptor);
  2668. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_SECURITY_DESCRIPTOR, hr )
  2669. hr = pRecord->SetValue(
  2670. APP_ATTRIBUTE_VERSIONLO,
  2671. (LONG)_VersionLo);
  2672. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_VERSIONLO, hr )
  2673. hr = pRecord->SetValue(
  2674. APP_ATTRIBUTE_VERSIONHI,
  2675. (LONG)_VersionHi);
  2676. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_VERSIONHI, hr )
  2677. hr = pRecord->SetValue(
  2678. APP_ATTRIBUTE_PRODUCT_ID,
  2679. _pwszProductId);
  2680. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_PRODUCT_ID, hr )
  2681. hr = pRecord->SetValue(
  2682. APP_ATTRIBUTE_SCRIPTFILE,
  2683. _pwszGPTScriptPath);
  2684. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_SCRIPTFILE, hr )
  2685. hr = pRecord->SetValue(
  2686. APP_ATTRIBUTE_LANGUAGEID,
  2687. (LONG) _LangId);
  2688. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_LANGUAGEID, hr )
  2689. hr = pRecord->SetValue(
  2690. APP_ATTRIBUTE_DEPLOY_TYPE,
  2691. (_ActFlags & ACTFLG_Assigned ?
  2692. APP_ATTRIBUTE_DEPLOY_VALUE_ASSIGNED :
  2693. APP_ATTRIBUTE_DEPLOY_VALUE_PUBLISHED));
  2694. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_DEPLOY_TYPE, hr )
  2695. {
  2696. LONG AssignmentType;
  2697. if ( _ActFlags & ACTFLG_Published )
  2698. {
  2699. AssignmentType = APP_ATTRIBUTE_ASSIGNMENTTYPE_VALUE_NOTASSIGNED;
  2700. }
  2701. else if ( _ActFlags & ACTFLG_InstallUserAssign )
  2702. {
  2703. AssignmentType = APP_ATTRIBUTE_ASSIGNMENTTYPE_VALUE_INSTALL;
  2704. }
  2705. else
  2706. {
  2707. AssignmentType = APP_ATTRIBUTE_ASSIGNMENTTYPE_VALUE_STANDARD;
  2708. }
  2709. hr = pRecord->SetValue(
  2710. APP_ATTRIBUTE_ASSIGNMENT_TYPE,
  2711. AssignmentType);
  2712. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ASSIGNMENT_TYPE, hr )
  2713. }
  2714. hr = pRecord->SetValue(
  2715. APP_ATTRIBUTE_INSTALLATIONUI,
  2716. ((INSTALLUILEVEL_FULL == _InstallUILevel) ?
  2717. APP_ATTRIBUTE_INSTALLATIONUI_VALUE_MAXIMUM :
  2718. APP_ATTRIBUTE_INSTALLATIONUI_VALUE_BASIC));
  2719. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_INSTALLATIONUI, hr )
  2720. hr = pRecord->SetValue(
  2721. APP_ATTRIBUTE_ONDEMAND,
  2722. (BOOL)(_ActFlags & ACTFLG_OnDemandInstall));
  2723. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ONDEMAND, hr )
  2724. hr = pRecord->SetValue(
  2725. APP_ATTRIBUTE_LOSSOFSCOPEACTION,
  2726. (BOOL)(_ActFlags & ACTFLG_OrphanOnPolicyRemoval) ?
  2727. APP_ATTRIBUTE_SCOPELOSS_ORPHAN :
  2728. APP_ATTRIBUTE_SCOPELOSS_UNINSTALL);
  2729. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_LOSSOFSCOPEACTION, hr )
  2730. hr = pRecord->SetValue(
  2731. APP_ATTRIBUTE_IGNORELANGUAGE,
  2732. (BOOL)(_ActFlags & ACTFLG_IgnoreLanguage));
  2733. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_IGNORELANGUAGE, hr )
  2734. hr = pRecord->SetValue(
  2735. APP_ATTRIBUTE_PACKAGELOCATION,
  2736. _pwszPackageLocation);
  2737. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_PACKAGELOCATION, hr );
  2738. hr = pRecord->SetValue(
  2739. APP_ATTRIBUTE_CATEGORYLIST,
  2740. _rgwszCategories,
  2741. _cCategories);
  2742. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_CATEGORYLIST, hr );
  2743. hr = pRecord->SetValue(
  2744. APP_ATTRIBUTE_TRANSFORMLIST,
  2745. _rgwszTransforms,
  2746. _cTransforms);
  2747. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_TRANSFORMLIST, hr );
  2748. hr = pRecord->SetValue(
  2749. APP_ATTRIBUTE_ARCHITECTURES,
  2750. _rgArchitectures,
  2751. _cArchitectures);
  2752. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ARCHITECTURES, hr );
  2753. hr = pRecord->SetValue(
  2754. APP_ATTRIBUTE_PUBLISHER,
  2755. _pwszPublisher ? _pwszPublisher : L"" );
  2756. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_PUBLISHER, hr );
  2757. hr = pRecord->SetValue(
  2758. APP_ATTRIBUTE_REDEPLOYCOUNT,
  2759. (LONG) _DirectoryRevision);
  2760. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_REDEPLOYCOUNT, hr );
  2761. hr = pRecord->SetValue(
  2762. APP_ATTRIBUTE_UPGRADE_SETTINGS_MANDATORY,
  2763. (BOOL) ( _ActFlags & ACTFLG_ForceUpgrade ) );
  2764. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_UPGRADE_SETTINGS_MANDATORY, hr );
  2765. hr = pRecord->SetValue(
  2766. APP_ATTRIBUTE_UNINSTALL_UNMANAGED,
  2767. (BOOL) ( _bNeedsUnmanagedRemove ) );
  2768. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_UNINSTALL_UNMANAGED, hr );
  2769. hr = pRecord->SetValue(
  2770. APP_ATTRIBUTE_DISPLAYINARP,
  2771. (BOOL) ( _ActFlags & ACTFLG_UserInstall ) );
  2772. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_DISPLAYINARP, hr );
  2773. hr = pRecord->SetValue(
  2774. APP_ATTRIBUTE_SUPPORTURL,
  2775. _pwszSupportURL);
  2776. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_SUPPORTURL, hr );
  2777. if ( APP_ATTRIBUTE_ENTRYTYPE_VALUE_REMOVED_PACKAGE == EntryType )
  2778. {
  2779. hr = WriteRemovalProperties( pRecord );
  2780. }
  2781. {
  2782. BOOL bX86OnWin64;
  2783. bX86OnWin64 = FALSE;
  2784. //
  2785. // If this is an x86 package, see if this applies to 64-bit clients
  2786. //
  2787. if ( PROCESSOR_ARCHITECTURE_INTEL == _PrimaryArchitecture )
  2788. {
  2789. //
  2790. // If it has been excluded by the admin, it does not apply
  2791. //
  2792. if ( ! ( ACTFLG_ExcludeX86OnWin64 & _ActFlags ) )
  2793. {
  2794. bX86OnWin64 = TRUE;
  2795. }
  2796. //
  2797. // The flag above is reversed if this is a ZAP app -- flip
  2798. // the logic to support the reverse preference.
  2799. //
  2800. if ( SetupNamePath == _PathType )
  2801. {
  2802. bX86OnWin64 = ! bX86OnWin64;
  2803. }
  2804. }
  2805. hr = pRecord->SetValue(
  2806. APP_ATTRIBUTE_X86OnWin64,
  2807. bX86OnWin64);
  2808. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_X86OnWin64, hr);
  2809. }
  2810. {
  2811. SYSTEMTIME SystemTime;
  2812. BOOL bStatus;
  2813. bStatus = FileTimeToSystemTime(
  2814. (FILETIME*) &_USN,
  2815. &SystemTime);
  2816. if ( bStatus )
  2817. {
  2818. hr = pRecord->SetValue(
  2819. APP_ATTRIBUTE_MODIFYTIME,
  2820. &SystemTime);
  2821. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_MODIFYTIME, hr);
  2822. }
  2823. else
  2824. {
  2825. hr = HRESULT_FROM_WIN32( GetLastError() );
  2826. }
  2827. }
  2828. {
  2829. LONG PackageType;
  2830. switch ( _PathType )
  2831. {
  2832. case DrwFilePath:
  2833. PackageType = APP_ATTRIBUTE_PACKAGETYPE_VALUE_WIN_INSTALLER;
  2834. break;
  2835. case SetupNamePath:
  2836. PackageType = APP_ATTRIBUTE_PACKAGETYPE_VALUE_ZAP;
  2837. break;
  2838. default:
  2839. ASSERT ( L"Invalid packagetype" && FALSE );
  2840. break;
  2841. }
  2842. hr = pRecord->SetValue(
  2843. APP_ATTRIBUTE_PACKAGETYPE,
  2844. (LONG) PackageType);
  2845. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_PACKAGETYPE, hr )
  2846. }
  2847. if ( ! _pManApp->ARPList() )
  2848. {
  2849. DWORD dwInstallType;
  2850. WCHAR* wszDemandSpec;
  2851. WCHAR* wszProperty;
  2852. dwInstallType = _pManApp->GetRsopContext()->GetDemandSpec( &wszDemandSpec );
  2853. wszProperty = NULL;
  2854. switch (dwInstallType)
  2855. {
  2856. case CRsopAppContext::DEMAND_INSTALL_FILEEXT:
  2857. wszProperty = APP_ATTRIBUTE_ONDEMAND_FILEEXT;
  2858. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_FILEEXT;
  2859. break;
  2860. case CRsopAppContext::DEMAND_INSTALL_CLSID:
  2861. wszProperty = APP_ATTRIBUTE_ONDEMAND_CLSID;
  2862. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_CLSID;
  2863. break;
  2864. case CRsopAppContext::DEMAND_INSTALL_PROGID:
  2865. wszProperty = APP_ATTRIBUTE_ONDEMAND_PROGID;
  2866. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_PROGID;
  2867. break;
  2868. case CRsopAppContext::DEMAND_INSTALL_NAME:
  2869. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_USER;
  2870. wszProperty = NULL;
  2871. break;
  2872. case CRsopAppContext::DEMAND_INSTALL_NONE:
  2873. //
  2874. // We reach this case if we are in policy application
  2875. //
  2876. wszProperty = NULL;
  2877. if ( ( _dwApplyCause == APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE ) && ! IsSuperseded() )
  2878. {
  2879. if ( _ActFlags & ACTFLG_Assigned )
  2880. {
  2881. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_ASSIGNED;
  2882. }
  2883. else if ( _ActFlags & ACTFLG_Published )
  2884. {
  2885. if ( _State & APPSTATE_SCRIPT_NOT_EXISTED )
  2886. {
  2887. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_PROFILE;
  2888. }
  2889. else if ( _State & APPSTATE_ASSIGNED )
  2890. {
  2891. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_ASSIGNED;
  2892. }
  2893. else
  2894. {
  2895. _dwApplyCause = APP_ATTRIBUTE_APPLYCAUSE_VALUE_USER;
  2896. if ( ! _pManApp->GetRsopContext()->Transition() )
  2897. {
  2898. _dwApplyCause = _dwUserApplyCause;
  2899. wszProperty = _wszDemandProp;
  2900. wszDemandSpec = _wszDemandSpec;
  2901. }
  2902. }
  2903. }
  2904. }
  2905. break;
  2906. default:
  2907. ASSERT( L"Invalid RSoP Install Context" && FALSE );
  2908. break;
  2909. }
  2910. if ( wszProperty )
  2911. {
  2912. hr = pRecord->SetValue(
  2913. wszProperty,
  2914. wszDemandSpec);
  2915. REPORT_ATTRIBUTE_SET_STATUS( wszProperty, hr )
  2916. }
  2917. else if ( APP_ATTRIBUTE_ENTRYTYPE_VALUE_REMOVED_PACKAGE != EntryType )
  2918. {
  2919. //
  2920. // Ensure that
  2921. //
  2922. hr = pRecord->ClearValue(
  2923. APP_ATTRIBUTE_ONDEMAND_FILEEXT);
  2924. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ONDEMAND_FILEEXT, hr )
  2925. hr = pRecord->ClearValue(
  2926. APP_ATTRIBUTE_ONDEMAND_CLSID);
  2927. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ONDEMAND_CLSID, hr )
  2928. hr = pRecord->ClearValue(
  2929. APP_ATTRIBUTE_ONDEMAND_PROGID);
  2930. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ONDEMAND_PROGID, hr )
  2931. }
  2932. if ( APP_ATTRIBUTE_APPLYCAUSE_VALUE_NONE != _dwApplyCause )
  2933. {
  2934. hr = pRecord->SetValue(
  2935. APP_ATTRIBUTE_APPLY_CAUSE,
  2936. (LONG) _dwApplyCause);
  2937. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_APPLY_CAUSE, hr )
  2938. }
  2939. }
  2940. {
  2941. LONG MatchType;
  2942. switch(_LanguageWeight)
  2943. {
  2944. case PRI_LANG_ALWAYSMATCH:
  2945. MatchType = APP_ATTRIBUTE_LANGMATCH_VALUE_IGNORE;
  2946. break;
  2947. case PRI_LANG_SYSTEMLOCALE:
  2948. MatchType = APP_ATTRIBUTE_LANGMATCH_VALUE_SYSLOCALE;
  2949. break;
  2950. case PRI_LANG_ENGLISH:
  2951. MatchType = APP_ATTRIBUTE_LANGMATCH_VALUE_ENGLISH;
  2952. break;
  2953. case PRI_LANG_NEUTRAL:
  2954. MatchType = APP_ATTRIBUTE_LANGMATCH_VALUE_NEUTRAL;
  2955. break;
  2956. default:
  2957. MatchType = APP_ATTRIBUTE_LANGMATCH_VALUE_NOMATCH;
  2958. break;
  2959. }
  2960. hr = pRecord->SetValue(
  2961. APP_ATTRIBUTE_LANGMATCH,
  2962. MatchType);
  2963. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_LANGMATCH, hr )
  2964. }
  2965. hr = pRecord->SetValue(
  2966. APP_ATTRIBUTE_ELIGIBILITY,
  2967. GetEligibility() );
  2968. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_ELIGIBILITY, hr )
  2969. LogUpgrades( pRecord );
  2970. cleanup:
  2971. return hr;
  2972. }
  2973. HRESULT
  2974. CAppInfo::WriteRemovalProperties(
  2975. CPolicyRecord* pRemovalRecord )
  2976. {
  2977. HRESULT hr;
  2978. LONG RemovalType;
  2979. LONG RemovalCause;
  2980. RemovalCause = (LONG) _dwRemovalCause;
  2981. if ( CRsopAppContext::REMOVAL == _pManApp->GetRsopContext()->GetContext() )
  2982. {
  2983. RemovalType = APP_ATTRIBUTE_REMOVALTYPE_UNINSTALLED;
  2984. }
  2985. else if ( APP_ATTRIBUTE_REMOVALCAUSE_UPGRADE == RemovalCause )
  2986. {
  2987. if ( ACTION_UNINSTALL == Action() )
  2988. {
  2989. RemovalType = APP_ATTRIBUTE_REMOVALTYPE_UNINSTALLED;
  2990. }
  2991. else
  2992. {
  2993. RemovalType = APP_ATTRIBUTE_REMOVALTYPE_UPGRADED;
  2994. }
  2995. }
  2996. else if ( APP_ATTRIBUTE_REMOVALCAUSE_TRANSFORM == RemovalCause )
  2997. {
  2998. RemovalType = APP_ATTRIBUTE_REMOVALTYPE_UNINSTALLED;
  2999. }
  3000. else if ( ACTION_ORPHAN == Action() )
  3001. {
  3002. RemovalType = APP_ATTRIBUTE_REMOVALTYPE_ORPHAN;
  3003. }
  3004. else if ( ACTION_UNINSTALL == Action() )
  3005. {
  3006. RemovalType = APP_ATTRIBUTE_REMOVALTYPE_UNINSTALLED;
  3007. }
  3008. else
  3009. {
  3010. RemovalType = APP_ATTRIBUTE_REMOVALTYPE_NONE;
  3011. }
  3012. if ( APP_ATTRIBUTE_REMOVALTYPE_NONE == RemovalType )
  3013. {
  3014. return S_OK;
  3015. }
  3016. hr = pRemovalRecord->SetValue(
  3017. APP_ATTRIBUTE_REMOVAL_CAUSE,
  3018. RemovalCause);
  3019. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_REMOVAL_CAUSE, hr );
  3020. hr = pRemovalRecord->SetValue(
  3021. APP_ATTRIBUTE_REMOVAL_TYPE,
  3022. RemovalType);
  3023. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_REMOVAL_TYPE, hr );
  3024. hr = pRemovalRecord->ClearValue(
  3025. APP_ATTRIBUTE_PRECEDENCE_REASON);
  3026. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_PRECEDENCE_REASON, hr );
  3027. if ( _pwszRemovingDeploymentId )
  3028. {
  3029. hr = pRemovalRecord->SetValue(
  3030. APP_ATTRIBUTE_REMOVING_APP,
  3031. _pwszRemovingDeploymentId);
  3032. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_REMOVING_APP, hr )
  3033. }
  3034. return hr;
  3035. }
  3036. HRESULT
  3037. CAppInfo::ClearRemovalProperties( CPolicyRecord* pRecord )
  3038. {
  3039. HRESULT hr;
  3040. hr = pRecord->ClearValue( APP_ATTRIBUTE_REMOVAL_CAUSE );
  3041. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_REMOVAL_CAUSE, hr )
  3042. if ( SUCCEEDED( hr ) )
  3043. {
  3044. hr = pRecord->ClearValue( APP_ATTRIBUTE_REMOVAL_TYPE );
  3045. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_REMOVAL_TYPE, hr )
  3046. }
  3047. if ( SUCCEEDED( hr ) )
  3048. {
  3049. hr = pRecord->ClearValue( APP_ATTRIBUTE_REMOVING_APP );
  3050. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_REMOVING_APP, hr )
  3051. }
  3052. return hr;
  3053. }
  3054. LONG
  3055. CAppInfo::GetRsopEntryType()
  3056. {
  3057. LONG EntryType;
  3058. if ( _pManApp->ARPList() )
  3059. {
  3060. EntryType = APP_ATTRIBUTE_ENTRYTYPE_VALUE_ARPLIST_ITEM;
  3061. }
  3062. else
  3063. {
  3064. if ( ( _Action == ACTION_APPLY ) ||
  3065. ( _Action == ACTION_INSTALL ) ||
  3066. ( _Action == ACTION_REINSTALL ) )
  3067. {
  3068. EntryType = APP_ATTRIBUTE_ENTRYTYPE_VALUE_INSTALLED_PACKAGE;
  3069. }
  3070. else if ( ( _Action == ACTION_ORPHAN ) ||
  3071. ( _Action == ACTION_UNINSTALL ) )
  3072. {
  3073. EntryType = APP_ATTRIBUTE_ENTRYTYPE_VALUE_REMOVED_PACKAGE;
  3074. }
  3075. else if ( ( _State & APPSTATE_ASSIGNED ) |
  3076. ( _State & APPSTATE_PUBLISHED ) )
  3077. {
  3078. EntryType = APP_ATTRIBUTE_ENTRYTYPE_VALUE_INSTALLED_PACKAGE;
  3079. }
  3080. else
  3081. {
  3082. EntryType = NO_RSOP_ENTRY;
  3083. }
  3084. }
  3085. return EntryType;
  3086. }
  3087. LONG
  3088. CAppInfo::GetPublicRsopEntryType()
  3089. {
  3090. LONG EntryType;
  3091. if ( IsSuperseded() )
  3092. {
  3093. if ( _pManApp->ARPList() )
  3094. {
  3095. EntryType = APP_ATTRIBUTE_ENTRYTYPE_VALUE_ARPLIST_ITEM;
  3096. }
  3097. else
  3098. {
  3099. EntryType = APP_ATTRIBUTE_ENTRYTYPE_VALUE_INSTALLED_PACKAGE;
  3100. }
  3101. }
  3102. else
  3103. {
  3104. EntryType = GetRsopEntryType();
  3105. }
  3106. return EntryType;
  3107. }
  3108. LONG
  3109. CAppInfo::GetEligibility()
  3110. {
  3111. LONG Eligibility;
  3112. Eligibility = 0;
  3113. if ( ! ( CRsopAppContext::ARPLIST == _pManApp->GetRsopContext()->GetContext() ) )
  3114. {
  3115. if ( ! ( CRsopAppContext::POLICY_REFRESH == _pManApp->GetRsopContext()->GetContext() ) &&
  3116. ! IsSuperseded() )
  3117. {
  3118. Eligibility = APP_ATTRIBUTE_ELIGIBILITY_VALUE_APPLIED;
  3119. }
  3120. else if ( ( _ActFlags & ACTFLG_Assigned ) || ( _State & APPSTATE_ASSIGNED ) )
  3121. {
  3122. Eligibility = APP_ATTRIBUTE_ELIGIBILITY_VALUE_ASSIGNED;
  3123. }
  3124. else if ( _ActFlags & ACTFLG_HasUpgrades )
  3125. {
  3126. Eligibility = APP_ATTRIBUTE_ELIGIBILITY_VALUE_UPGRADES;
  3127. }
  3128. else if ( ( _dwApplyCause == APP_ATTRIBUTE_APPLYCAUSE_VALUE_PROFILE ) ||
  3129. _DemandInstall )
  3130. {
  3131. Eligibility = APP_ATTRIBUTE_ELIGIBILITY_VALUE_APPLIED;
  3132. }
  3133. else if ( _pManApp->GetRsopContext()->IsPlanningModeEnabled() )
  3134. {
  3135. Eligibility = APP_ATTRIBUTE_ELIGIBILITY_VALUE_PLANNING;
  3136. }
  3137. else
  3138. {
  3139. Eligibility = APP_ATTRIBUTE_ELIGIBILITY_VALUE_APPLIED;
  3140. }
  3141. }
  3142. return Eligibility;
  3143. }
  3144. HRESULT
  3145. CAppInfo::SetRemovingDeploymentId( GUID* pDeploymentId )
  3146. {
  3147. if ( ! _pwszRemovingDeploymentId )
  3148. {
  3149. _pwszRemovingDeploymentId = new WCHAR[ MAX_SZGUID_LEN ];
  3150. }
  3151. if ( ! _pwszRemovingDeploymentId )
  3152. {
  3153. return E_OUTOFMEMORY;
  3154. }
  3155. GuidToString( *pDeploymentId, _pwszRemovingDeploymentId);
  3156. return S_OK;
  3157. }
  3158. void
  3159. CAppInfo::SetRsopFailureStatus(
  3160. DWORD dwStatus,
  3161. DWORD dwEventId)
  3162. {
  3163. CAppStatus* pNewStatus;
  3164. //
  3165. // Allocate a new failure status for this application --
  3166. // it will be freed by the destructor of this class
  3167. //
  3168. pNewStatus = new CAppStatus;
  3169. if ( ! pNewStatus )
  3170. {
  3171. _pManApp->GetRsopContext()->DisableRsop( E_OUTOFMEMORY );
  3172. return;
  3173. }
  3174. //
  3175. // Set the status as specified by the caller
  3176. //
  3177. pNewStatus->SetRsopFailureStatus( dwStatus, dwEventId );
  3178. //
  3179. // Remember this new status --
  3180. // keep track of multiple errors in the order they were logged
  3181. //
  3182. _StatusList.InsertFIFO( pNewStatus );
  3183. //
  3184. // Always reset this so that if someone calls GetCurrentItem,
  3185. // they will get the first thing in the list -- if this is
  3186. // never called, the list returns NULL
  3187. //
  3188. _StatusList.Reset();
  3189. }
  3190. void
  3191. CAppInfo::ForceFailureStatus()
  3192. {
  3193. //
  3194. // If we haven't already failed, set an arbitrary
  3195. // error code -- this is used in cases where the app
  3196. // itself did not fail to apply, but some other app
  3197. // failed (as in the upgrade case), but we need to
  3198. // set this as a failure so that the application will
  3199. // clean up its state
  3200. //
  3201. if ( ERROR_SUCCESS == _Status )
  3202. {
  3203. _Status = ERROR_NOT_ENOUGH_MEMORY;
  3204. }
  3205. }
  3206. LONG
  3207. CAppInfo::UpdatePrecedence(
  3208. CAppInfo* pLosingApp,
  3209. DWORD dwConflict
  3210. )
  3211. {
  3212. LONG Status;
  3213. Status = ERROR_SUCCESS;
  3214. if ( ! _bSupersedesAssigned )
  3215. {
  3216. if ( pLosingApp->_bSupersedesAssigned )
  3217. {
  3218. _bSupersedesAssigned = pLosingApp->_bSupersedesAssigned;
  3219. }
  3220. else
  3221. {
  3222. _bSupersedesAssigned = ( ACTFLG_Assigned & pLosingApp->_ActFlags );
  3223. }
  3224. }
  3225. //
  3226. // If Rsop logging is enabled, we need to update
  3227. // the precedence of this application according
  3228. // to the conflict
  3229. //
  3230. if ( _pManApp->GetRsopContext()->IsRsopEnabled() )
  3231. {
  3232. Status = _SupersededApps.AddConflict( pLosingApp, this, dwConflict );
  3233. //
  3234. // Supersede the losing app -- that is, mark it as
  3235. // superseded so that later on when writing the rsop
  3236. // log we do not log it as a winning application
  3237. //
  3238. if ( ERROR_SUCCESS == Status )
  3239. {
  3240. pLosingApp->Supersede();
  3241. DebugMsg((
  3242. DM_VERBOSE,
  3243. IDS_RSOP_SUPERSEDED,
  3244. pLosingApp->_pwszDeploymentName,
  3245. pLosingApp->_pwszGPOName,
  3246. _pwszDeploymentName,
  3247. _pwszGPOName,
  3248. dwConflict));
  3249. }
  3250. else
  3251. {
  3252. HRESULT hr;
  3253. hr = HRESULT_FROM_WIN32( Status );
  3254. _pManApp->GetRsopContext()->DisableRsop( hr );
  3255. }
  3256. }
  3257. return Status;
  3258. }
  3259. void
  3260. CAppInfo::LogUpgrades( CPolicyRecord* pRecord )
  3261. {
  3262. if (!_Upgrades)
  3263. {
  3264. return;
  3265. }
  3266. WCHAR** rgwszUpgradeable;
  3267. WCHAR** rgwszReplaceable;
  3268. rgwszUpgradeable = NULL;
  3269. rgwszReplaceable = NULL;
  3270. rgwszUpgradeable = new WCHAR*[_Upgrades];
  3271. if ( ! rgwszUpgradeable )
  3272. {
  3273. goto ExitAndCleanup_LogUpgrades;
  3274. }
  3275. rgwszReplaceable = new WCHAR*[_Upgrades];
  3276. if ( ! rgwszUpgradeable )
  3277. {
  3278. goto ExitAndCleanup_LogUpgrades;
  3279. }
  3280. RtlZeroMemory(rgwszUpgradeable, _Upgrades * sizeof(*rgwszUpgradeable));
  3281. RtlZeroMemory(rgwszReplaceable, _Upgrades * sizeof(*rgwszReplaceable));
  3282. DWORD cUpgradeable;
  3283. DWORD cReplaceable;
  3284. cUpgradeable = 0;
  3285. cReplaceable = 0;
  3286. //
  3287. // We will iterate through each upgrade so that we can log it
  3288. //
  3289. DWORD iUpgrade;
  3290. for (iUpgrade = 0; iUpgrade < _Upgrades; iUpgrade++)
  3291. {
  3292. WCHAR** ppwszUpgradeId;
  3293. //
  3294. // We only track the applications that we upgrade, not those
  3295. // that we are upgraded by. Note that we do not check for the
  3296. // converse flag, UPGRADE_OVER, since it can get cleared when
  3297. // an upgrade relationship is reversed -- we still need to
  3298. // log that as an upgrade for this app
  3299. //
  3300. if ( _pUpgrades[iUpgrade].Flags & UPGRADE_BY )
  3301. {
  3302. continue;
  3303. }
  3304. //
  3305. // If this upgrade is the result of a reversed upgrade due to
  3306. // a policy precedence violation, we should not log it as part
  3307. // of this application's upgrades
  3308. //
  3309. if ( _pUpgrades[iUpgrade].Flags & UPGRADE_REVERSED )
  3310. {
  3311. continue;
  3312. }
  3313. if ( _pUpgrades[iUpgrade].Flags & UPGRADE_UNINSTALL )
  3314. {
  3315. ppwszUpgradeId = &(rgwszReplaceable[cReplaceable]);
  3316. cReplaceable++;
  3317. }
  3318. else
  3319. {
  3320. ppwszUpgradeId = &(rgwszUpgradeable[cUpgradeable]);
  3321. cUpgradeable++;
  3322. }
  3323. //
  3324. // The RSoP schema requires the guids be in string form,
  3325. // so we need to convert this guid to a string -- note that
  3326. // this call allocates memory which must be freed later
  3327. //
  3328. GuidToString(
  3329. _pUpgrades[iUpgrade].DeploymentId,
  3330. ppwszUpgradeId);
  3331. if ( ! *ppwszUpgradeId )
  3332. {
  3333. break;
  3334. }
  3335. }
  3336. if (iUpgrade == _Upgrades)
  3337. {
  3338. HRESULT hr;
  3339. hr = pRecord->SetValue(
  3340. APP_ATTRIBUTE_UPGRADEABLE_APPLICATIONS,
  3341. rgwszUpgradeable,
  3342. cUpgradeable);
  3343. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_UPGRADEABLE_APPLICATIONS, hr )
  3344. hr = pRecord->SetValue(
  3345. APP_ATTRIBUTE_REPLACEABLE_APPLICATIONS,
  3346. rgwszReplaceable,
  3347. cReplaceable);
  3348. REPORT_ATTRIBUTE_SET_STATUS( APP_ATTRIBUTE_REPLACEABLE_APPLICATIONS, hr )
  3349. }
  3350. //
  3351. // Free the memory allocated in the GuidToString call for each upgrade guid
  3352. //
  3353. for (iUpgrade = 0; iUpgrade < cUpgradeable; iUpgrade++)
  3354. {
  3355. delete [] rgwszUpgradeable[iUpgrade];
  3356. }
  3357. for (iUpgrade = 0; iUpgrade < cReplaceable; iUpgrade++)
  3358. {
  3359. delete [] rgwszReplaceable[iUpgrade];
  3360. }
  3361. ExitAndCleanup_LogUpgrades:
  3362. delete [] rgwszUpgradeable;
  3363. delete [] rgwszReplaceable;
  3364. }
  3365. BOOL
  3366. CAppInfo::IsLocal()
  3367. {
  3368. return NULL == _pwszGPODSPath;
  3369. }
  3370. BOOL
  3371. CAppInfo::IsGpoInScope()
  3372. {
  3373. BOOL bGpoInScope;
  3374. bGpoInScope = FALSE;
  3375. if ( _pwszGPOId )
  3376. {
  3377. CGPOInfoList& GpoInfoList = _pManApp->GPOList();
  3378. bGpoInScope = ( NULL != GpoInfoList.Find( _pwszGPOId ) );
  3379. }
  3380. return bGpoInScope;
  3381. }
  3382. LONG
  3383. CAppInfo::InitializeRSOPTransformsList(
  3384. PACKAGEDISPINFO* pPackageInfo
  3385. )
  3386. {
  3387. if ( ! pPackageInfo->cTransforms )
  3388. {
  3389. return ERROR_SUCCESS;
  3390. }
  3391. //
  3392. // The first element of the transforms list is
  3393. // actually the original package itself, so we don't count it
  3394. //
  3395. _cTransforms = pPackageInfo->cTransforms - 1;
  3396. //
  3397. // If we have transforms, get space for them
  3398. //
  3399. if ( 0 != _cTransforms )
  3400. {
  3401. //
  3402. // The elements in the transform list are
  3403. // the actual transforms, so we'll copy them to our own list -- first
  3404. // allocate enough space for pointers to each path
  3405. //
  3406. _rgwszTransforms = new WCHAR* [ _cTransforms ];
  3407. if ( ! _rgwszTransforms )
  3408. {
  3409. return ERROR_NOT_ENOUGH_MEMORY;
  3410. }
  3411. RtlZeroMemory( _rgwszTransforms, sizeof(*_rgwszTransforms) * _cTransforms );
  3412. }
  3413. //
  3414. // Now place the transforms into the array
  3415. //
  3416. //
  3417. // Each transform is of the form <index>:<path>. The <index> is
  3418. // an integer that is unique for each transform in this package and
  3419. // less than or equal to the number of transforms. The 0th transform
  3420. // is actually not a transform, but the source package itself, and this
  3421. // is special cased
  3422. //
  3423. //
  3424. // Copy each transform path to an element in the array of strings. We
  3425. // decide which element in the array based on the <index> indicated
  3426. // in the transform string, shifted down 1 to skip the 0th (the source package).
  3427. // For example, the transform with <index> 1 goes to array element 0,
  3428. // the transform with <index> 4 goes to 3, etc. That way, no matter what
  3429. // order the transforms are in (e.g. 3,2,0,4,1), because we are mapping
  3430. // based on index, we end up with an ordered array (e.g. 1,2,3,4).
  3431. //
  3432. DWORD iTransform;
  3433. BOOL bFoundSource;
  3434. bFoundSource = FALSE;
  3435. for ( iTransform = 0; iTransform < pPackageInfo->cTransforms; iTransform++ )
  3436. {
  3437. WCHAR* wszTransform;
  3438. DWORD dwTransformIndex;
  3439. //
  3440. // First, we need the transform index -- look for the separator
  3441. // so we can find it
  3442. //
  3443. wszTransform = wcschr( pPackageInfo->prgTransforms[ iTransform ], L':' );
  3444. //
  3445. // Check for bogus data
  3446. //
  3447. if ( ! wszTransform )
  3448. {
  3449. return ERROR_INVALID_PARAMETER;
  3450. }
  3451. //
  3452. // Truncate the string right after the index
  3453. //
  3454. *wszTransform = L'\0';
  3455. //
  3456. // The actual transform path starts one past the separator
  3457. //
  3458. wszTransform++;
  3459. //
  3460. // Now convert the index to integer
  3461. //
  3462. UNICODE_STRING TransformIndex;
  3463. NTSTATUS NtStatus;
  3464. RtlInitUnicodeString( &TransformIndex, pPackageInfo->prgTransforms[ iTransform ] );
  3465. NtStatus = RtlUnicodeStringToInteger( &TransformIndex, 10, &dwTransformIndex );
  3466. //
  3467. // This should only fail if the index string is corrupt ( i.e. the number is not in base 10 )
  3468. //
  3469. if ( ! NT_SUCCESS( NtStatus ) )
  3470. {
  3471. return RtlNtStatusToDosError( NtStatus );
  3472. }
  3473. //
  3474. // The number is correct syntactically, now ensure that semantically it is correct --
  3475. // the index cannot exceed the number of transforms.
  3476. //
  3477. if ( dwTransformIndex > _cTransforms )
  3478. {
  3479. return ERROR_INVALID_PARAMETER;
  3480. }
  3481. //
  3482. // Check for the source package -- it is transform index 0
  3483. //
  3484. if ( 0 == dwTransformIndex )
  3485. {
  3486. //
  3487. // Make sure the source is not listed twice
  3488. //
  3489. if ( bFoundSource )
  3490. {
  3491. return ERROR_INVALID_PARAMETER;
  3492. }
  3493. bFoundSource = TRUE;
  3494. //
  3495. // Copy the source package path, minus the prefix,
  3496. // to the member reserved for this purpose -- it currently
  3497. // points to the separator, so we need to go 1 past it
  3498. //
  3499. _pwszPackageLocation = StringDuplicate( wszTransform );
  3500. if ( ! _pwszPackageLocation )
  3501. {
  3502. return ERROR_NOT_ENOUGH_MEMORY;
  3503. }
  3504. continue;
  3505. }
  3506. //
  3507. // Shift it down since this index's value includes the source package's
  3508. // occupation of zero, and we want to exclude it
  3509. //
  3510. dwTransformIndex--;
  3511. //
  3512. // Make sure we don't already have a transform at this index -- if we do, this
  3513. // is an ill-formed transform list
  3514. //
  3515. if ( _rgwszTransforms [ dwTransformIndex ] )
  3516. {
  3517. return ERROR_INVALID_PARAMETER;
  3518. }
  3519. _rgwszTransforms[ dwTransformIndex ] = StringDuplicate( wszTransform );
  3520. if ( ! _rgwszTransforms[ dwTransformIndex ] )
  3521. {
  3522. return ERROR_NOT_ENOUGH_MEMORY;
  3523. }
  3524. }
  3525. //
  3526. // If we did not find a source, this is not a valid transform list
  3527. //
  3528. if ( ! bFoundSource )
  3529. {
  3530. return ERROR_INVALID_PARAMETER;
  3531. }
  3532. return S_OK;
  3533. }
  3534. LONG
  3535. CAppInfo::InitializeRSOPArchitectureInfo( PACKAGEDISPINFO* pPackageInfo )
  3536. {
  3537. DWORD iArchitecture;
  3538. _rgArchitectures = new LONG [ pPackageInfo->cArchitectures ];
  3539. if ( ! _rgArchitectures )
  3540. {
  3541. return ERROR_OUTOFMEMORY;
  3542. }
  3543. _cArchitectures = pPackageInfo->cArchitectures;
  3544. for (
  3545. iArchitecture = 0;
  3546. iArchitecture < _cArchitectures;
  3547. iArchitecture ++ )
  3548. {
  3549. //
  3550. // We need to extract the Win32 processor architecture --
  3551. // the element in the PACKAGEDISPINFO is actually a combination
  3552. // of several other attributes -- the processor architecture is
  3553. // in highest 8 bits, so we'll shift everything right to get it.
  3554. //
  3555. _rgArchitectures[ iArchitecture ] =
  3556. pPackageInfo->prgArchitectures[ iArchitecture ] >> 24;
  3557. //
  3558. // In planning mode, we determine architecture by seeing if it lists 64-bit --
  3559. // if so, we mark it as 64 bit. If it doesn't list 64-bit, it will be marked 32-bit
  3560. // if it lists 32-bit. If it doesn't list either of those, it will be
  3561. // marked as unknown.
  3562. //
  3563. if ((PROCESSOR_ARCHITECTURE_IA64 != _PrimaryArchitecture) &&
  3564. (PROCESSOR_ARCHITECTURE_AMD64 != _PrimaryArchitecture))
  3565. {
  3566. if ((PROCESSOR_ARCHITECTURE_INTEL == _rgArchitectures[ iArchitecture ]) ||
  3567. (PROCESSOR_ARCHITECTURE_AMD64 == _rgArchitectures[ iArchitecture ]) ||
  3568. (PROCESSOR_ARCHITECTURE_IA64 == _rgArchitectures[ iArchitecture ]))
  3569. {
  3570. _PrimaryArchitecture = _rgArchitectures[ iArchitecture ];
  3571. }
  3572. }
  3573. }
  3574. if ( _pManApp->GetRsopContext()->IsDiagnosticModeEnabled() )
  3575. {
  3576. _PrimaryArchitecture = pPackageInfo->MatchedArchitecture >> 24;
  3577. }
  3578. return ERROR_SUCCESS;
  3579. }
  3580. LONG
  3581. CAppInfo::InitializeCategoriesList(
  3582. PACKAGEDISPINFO* pPackageInfo
  3583. )
  3584. {
  3585. if ( ! pPackageInfo->cCategories )
  3586. {
  3587. return ERROR_SUCCESS;
  3588. }
  3589. //
  3590. // Reserve enough space so that we can have a pointer
  3591. // to each category guid string
  3592. //
  3593. _cCategories = pPackageInfo->cCategories;
  3594. _rgwszCategories = new WCHAR* [ pPackageInfo->cCategories ];
  3595. if ( ! _rgwszCategories )
  3596. {
  3597. return ERROR_NOT_ENOUGH_MEMORY;
  3598. }
  3599. RtlZeroMemory( _rgwszCategories, sizeof( *_rgwszCategories ) * _cCategories );
  3600. //
  3601. // Now reserve enough space for each copy of the category
  3602. // guid strings
  3603. //
  3604. DWORD iCategory;
  3605. for ( iCategory = 0; iCategory < _cCategories; iCategory++ )
  3606. {
  3607. _rgwszCategories[ iCategory ] = StringDuplicate( pPackageInfo->prgCategories[ iCategory ] );
  3608. if ( ! _rgwszCategories[ iCategory ] )
  3609. {
  3610. return ERROR_NOT_ENOUGH_MEMORY;
  3611. }
  3612. }
  3613. return S_OK;
  3614. }
  3615. WCHAR* CAppInfo::GetRsopAppCriteria()
  3616. {
  3617. //
  3618. // We will want to specify an instance that has the conflict id unique
  3619. // to this package and its conflicts, and has an "installed" entry type.
  3620. //
  3621. //
  3622. // First, we calculate the length -- this is actually a constant based
  3623. // on the maximum sizes of the 2 criteria mentioned above: the conflict id
  3624. // is a guid string, and thus has a fixed maximum. The entry type is a
  3625. // 32 bit quantities, which of course has a maximum string length
  3626. // in decimal notation
  3627. //
  3628. DWORD cCriteriaLen;
  3629. cCriteriaLen =
  3630. MAXLEN_RSOPREMOVAL_QUERY_CRITERIA +
  3631. MAXLEN_RSOPENTRYTYPE_DECIMAL_REPRESENTATION +
  3632. MAXLEN_RSOPPACKAGEID_GUID_REPRESENTATION;
  3633. WCHAR* wszCriteria = new WCHAR [ cCriteriaLen ];
  3634. if ( wszCriteria )
  3635. {
  3636. WCHAR wszDeploymentId [ MAX_SZGUID_LEN ];
  3637. HRESULT hr;
  3638. GuidToString( _DeploymentId, wszDeploymentId);
  3639. hr = StringCchPrintf(
  3640. wszCriteria,
  3641. cCriteriaLen,
  3642. RSOP_REMOVAL_QUERY_CRITERIA,
  3643. APP_ATTRIBUTE_ENTRYTYPE_VALUE_INSTALLED_PACKAGE,
  3644. wszDeploymentId);
  3645. if (FAILED(hr))
  3646. {
  3647. delete [] wszCriteria;
  3648. return NULL;
  3649. }
  3650. }
  3651. return wszCriteria;
  3652. }
  3653. DWORD
  3654. CAppInfo::CopyScriptIfNeeded()
  3655. {
  3656. WCHAR * pwszTempScript;
  3657. DWORD Length;
  3658. DWORD Status;
  3659. if ( _State & APPSTATE_SCRIPT_PRESENT )
  3660. return ERROR_SUCCESS;
  3661. Status = ERROR_SUCCESS;
  3662. //
  3663. // It is remotely possible that we could hit this. For instance, during
  3664. // an ARP readvertise of an uninstalled assigned app. When using roaming
  3665. // profiles & with policy failing to run at the last logon, we might not
  3666. // have the local script, so we get this far, but this member will not be
  3667. // set when run in the service.
  3668. //
  3669. if ( ! _pwszGPTScriptPath )
  3670. return ERROR_BAD_PATHNAME;
  3671. //
  3672. // When doing user policy we have to do two copies to get the script in the
  3673. // right place. First we copy to a temp file while impersonating. This is
  3674. // so our sysvol access is done as the user. Then we copy from the temp file
  3675. // to the ACLed script dir under %systemroot% while reverted as LocalSystem.
  3676. //
  3677. if ( _pManApp->IsUserPolicy() )
  3678. {
  3679. pwszTempScript = 0;
  3680. Length = GetTempPath( 0, NULL );
  3681. if ( Length > 0 )
  3682. {
  3683. pwszTempScript = new WCHAR[Length + 1 + GUIDSTRLEN + 1];
  3684. if ( pwszTempScript )
  3685. {
  3686. if ( 0 == GetTempPath( Length, pwszTempScript ) )
  3687. Status = GetLastError();
  3688. }
  3689. else
  3690. {
  3691. Status = ERROR_OUTOFMEMORY;
  3692. }
  3693. }
  3694. else
  3695. Status = GetLastError();
  3696. if ( ERROR_SUCCESS == Status )
  3697. {
  3698. if ( pwszTempScript[lstrlen(pwszTempScript)-1] != L'\\' )
  3699. {
  3700. HRESULT hr;
  3701. hr = StringCchCat( pwszTempScript, Length + 1 + GUIDSTRLEN + 1, L"\\" );
  3702. if (FAILED(hr))
  3703. {
  3704. Status = HRESULT_CODE(hr);
  3705. }
  3706. }
  3707. if (ERROR_SUCCESS == Status)
  3708. {
  3709. GuidToString( _DeploymentId, &pwszTempScript[lstrlen(pwszTempScript)]);
  3710. //
  3711. // CopyFile does not use the thread impersonation token for access checks,
  3712. // so we are ok copying into the system temp dir.
  3713. //
  3714. if ( ! CopyFile(_pwszGPTScriptPath, pwszTempScript, FALSE) )
  3715. {
  3716. Status = GetLastError();
  3717. DebugMsg((DM_WARNING, IDS_SCRIPT_COPY_FAIL, _pwszDeploymentName, _pwszGPOName, _pwszGPTScriptPath, pwszTempScript, Status));
  3718. }
  3719. }
  3720. }
  3721. if ( ERROR_SUCCESS == Status )
  3722. {
  3723. _pManApp->Revert();
  3724. if ( ! CopyFile(pwszTempScript, _pwszLocalScriptPath, FALSE) )
  3725. {
  3726. Status = GetLastError();
  3727. DebugMsg((DM_WARNING, IDS_SCRIPT_COPY_FAIL, _pwszDeploymentName, _pwszGPOName, pwszTempScript, _pwszLocalScriptPath, Status));
  3728. }
  3729. DeleteFile( pwszTempScript );
  3730. DWORD impStatus = _pManApp->Impersonate();
  3731. if ( (impStatus != ERROR_SUCCESS) && (Status == ERROR_SUCCESS) )
  3732. {
  3733. Status = impStatus;
  3734. }
  3735. }
  3736. delete [] pwszTempScript;
  3737. }
  3738. else
  3739. {
  3740. if ( ! CopyFile(_pwszGPTScriptPath, _pwszLocalScriptPath, FALSE) )
  3741. {
  3742. Status = GetLastError();
  3743. DebugMsg((DM_WARNING, IDS_SCRIPT_COPY_FAIL, _pwszDeploymentName, _pwszGPOName, _pwszGPTScriptPath, _pwszLocalScriptPath, Status));
  3744. }
  3745. }
  3746. if ( ERROR_SUCCESS == Status )
  3747. _State |= APPSTATE_SCRIPT_PRESENT;
  3748. return Status;
  3749. }
  3750. void
  3751. CAppInfo::CheckScriptExistence()
  3752. {
  3753. if ( _State & (APPSTATE_SCRIPT_EXISTED | APPSTATE_SCRIPT_NOT_EXISTED) )
  3754. return;
  3755. if ( _pManApp->ScriptList().Find( _DeploymentId ) != NULL )
  3756. _State |= APPSTATE_SCRIPT_EXISTED | APPSTATE_SCRIPT_PRESENT;
  3757. else
  3758. _State |= APPSTATE_SCRIPT_NOT_EXISTED;
  3759. }
  3760. DWORD
  3761. CAppInfo::EnforceAssignmentSecurity(
  3762. BOOL * pbDidUninstall
  3763. )
  3764. {
  3765. INSTALLSTATE InstallState;
  3766. WCHAR wszBuffer[8];
  3767. DWORD Size;
  3768. DWORD Status;
  3769. BOOL bPerMachine;
  3770. BOOL bUninstall;
  3771. *pbDidUninstall = FALSE;
  3772. if ( ! _bNeedsUnmanagedRemove )
  3773. return ERROR_SUCCESS;
  3774. DebugMsg((DM_VERBOSE, IDS_ENFORCE_SECURE_ON, _pwszDeploymentName, _pwszGPOName));
  3775. InstallState = (*gpfnMsiQueryProductState)( _pwszProductId );
  3776. //
  3777. // If the app is not installed for the user/machine then we are done.
  3778. // Note that if only advertised, our subsequent advertise will update
  3779. // the source path, so we return in that case.
  3780. //
  3781. if ( ! AppPresent( InstallState) || (INSTALLSTATE_ADVERTISED == InstallState) )
  3782. return ERROR_SUCCESS;
  3783. Size = sizeof(wszBuffer) / sizeof(WCHAR);
  3784. Status = (*gpfnMsiGetProductInfo)(
  3785. _pwszProductId,
  3786. INSTALLPROPERTY_ASSIGNMENTTYPE,
  3787. wszBuffer,
  3788. &Size );
  3789. if ( Status != ERROR_SUCCESS )
  3790. {
  3791. DebugMsg((DM_WARNING, IDS_ENFORCE_SECURE_FAIL, _pwszDeploymentName, Status));
  3792. return Status;
  3793. }
  3794. bPerMachine = (L'1' == wszBuffer[0]);
  3795. //
  3796. // For user policy we only care about user installed apps and for machine
  3797. // policy we only care about machine installed apps.
  3798. //
  3799. if ( (_pManApp->IsUserPolicy() && bPerMachine) ||
  3800. (! _pManApp->IsUserPolicy() && ! bPerMachine) )
  3801. return ERROR_SUCCESS;
  3802. //
  3803. // If the app is present for the user and we've previously
  3804. // assigned it, we are safe if the product is marked for elevated
  3805. // install.
  3806. //
  3807. // If we've previously installed a machine assigned app then it's ok,
  3808. // because by definition all machine installed apps are elevated
  3809. // (because they require admin priviledge to install), so we
  3810. // don't need this extra check for them.
  3811. //
  3812. if ( _State & APPSTATE_SCRIPT_EXISTED )
  3813. {
  3814. BOOL bElevated;
  3815. if ( _pManApp->IsUserPolicy() )
  3816. {
  3817. Status = (*gpfnMsiIsProductElevated)( _pwszProductId, &bElevated );
  3818. if ( Status != ERROR_SUCCESS )
  3819. {
  3820. DebugMsg((DM_WARNING, IDS_ENFORCE_SECURE_FAIL, _pwszDeploymentName, Status));
  3821. return Status;
  3822. }
  3823. }
  3824. else
  3825. {
  3826. bElevated = TRUE;
  3827. }
  3828. if ( bElevated )
  3829. return ERROR_SUCCESS;
  3830. }
  3831. gpEvents->RemoveUnmanaged( this );
  3832. _pManApp->LogonMsgInstall( _pwszDeploymentName );
  3833. Status = Uninstall();
  3834. _pManApp->LogonMsgApplying();
  3835. if ( ERROR_SUCCESS == Status )
  3836. {
  3837. _InstallState = INSTALLSTATE_ABSENT;
  3838. *pbDidUninstall = TRUE;
  3839. }
  3840. else
  3841. {
  3842. DebugMsg((DM_WARNING, IDS_ENFORCE_SECURE_FAIL, _pwszDeploymentName, Status));
  3843. }
  3844. return Status;
  3845. }
  3846. BOOL
  3847. CAppInfo::RequiresUnmanagedRemoval()
  3848. {
  3849. BOOL bRequiresUnmanagedRemoval = FALSE;
  3850. if ( _pManApp->ARPList() )
  3851. {
  3852. return FALSE;
  3853. }
  3854. //
  3855. // We remove unmanaged installs as a security precaution to
  3856. // prevent elevation of privileges --
  3857. // this means that we do not need to do it for machine assigned apps
  3858. // or per-user apps for admins, since since system and admins
  3859. // already have the highest privileges
  3860. //
  3861. // Note that we could do this for all apps (whether or not they
  3862. // are machine assigned or user assigned / published to an admin),
  3863. // but the unmanaged removal is a less enjoyable user experience,
  3864. // so we only want to do this in the case where it is required --
  3865. // the per-user, non-admin case where the unmanaged application
  3866. // is not already elevated
  3867. //
  3868. //
  3869. // Verify that this is a per-user app
  3870. //
  3871. if ( _pManApp->IsUserPolicy() )
  3872. {
  3873. //
  3874. // For planning mode, we'll need to choose a "default" behavior
  3875. // so that we can simulate what might happen if this application
  3876. // were to be applied to a machine
  3877. //
  3878. if ( _pManApp->GetRsopContext()->IsPlanningModeEnabled() )
  3879. {
  3880. //
  3881. // We will err on the side of safety and say that this
  3882. // simulated application may require removal of unmanaged
  3883. // installs
  3884. //
  3885. bRequiresUnmanagedRemoval = TRUE;
  3886. }
  3887. else
  3888. {
  3889. //
  3890. // If this user is not an admin, we may require
  3891. // the removal of an unmanaged install of this app
  3892. // if one exists
  3893. //
  3894. if ( ! IsMemberOfAdminGroup( _pManApp->UserToken() ) )
  3895. {
  3896. BOOL bIsProductElevated = FALSE;
  3897. DWORD StatusElevated;
  3898. //
  3899. // The last check -- is this app present as an elevated install? If not,
  3900. // we should require its uninstall. Elevated apps were placed here by some
  3901. // admin user, so we do not consider these a threat to the system.
  3902. //
  3903. // Note that this call requires that the caller is impersonating
  3904. //
  3905. StatusElevated = gpfnMsiIsProductElevated( _pwszProductId, &bIsProductElevated );
  3906. //
  3907. // If this unmanaged install is not elevated, or if we were unable to determine whether
  3908. // or not it was elevated, we will require that the application is removed if it
  3909. // exists on the machine
  3910. //
  3911. if ( ( ERROR_SUCCESS != StatusElevated ) ||
  3912. ! bIsProductElevated )
  3913. {
  3914. bRequiresUnmanagedRemoval = TRUE;
  3915. }
  3916. }
  3917. }
  3918. }
  3919. return bRequiresUnmanagedRemoval;
  3920. }
  3921. DWORD
  3922. CAppInfo::RollbackUpgrades()
  3923. {
  3924. DWORD Status;
  3925. for ( DWORD n = 0; n < _Upgrades; n++ )
  3926. {
  3927. Status = ERROR_SUCCESS;
  3928. if ( ! _pUpgrades[n].pBaseApp || ! (_pUpgrades[n].Flags & UPGRADE_OVER) )
  3929. continue;
  3930. // Skip it if the app didn't exist here to begin with.
  3931. if ( ! (_pUpgrades[n].pBaseApp->_State & (APPSTATE_PUBLISHED | APPSTATE_ASSIGNED)) )
  3932. continue;
  3933. if ( _Status != ERROR_SUCCESS )
  3934. Status = _Status;
  3935. else
  3936. Status = _pUpgrades[n].pBaseApp->_Status;
  3937. gpEvents->UpgradeAbort( Status, this, _pUpgrades[n].pBaseApp, ERROR_SUCCESS == _Status );
  3938. // Re-apply any app which was successfully removed.
  3939. if ( ERROR_SUCCESS == _pUpgrades[n].pBaseApp->_Status )
  3940. {
  3941. DWORD ScriptFlags = SCRIPTFLAGS_REGDATA_CNFGINFO | SCRIPTFLAGS_CACHEINFO | SCRIPTFLAGS_SHORTCUTS;
  3942. DWORD AssignStatus;
  3943. if ( _pUpgrades[n].pBaseApp->_State & APPSTATE_ASSIGNED )
  3944. ScriptFlags |= SCRIPTFLAGS_REGDATA_EXTENSIONINFO;
  3945. AssignStatus = _pUpgrades[n].pBaseApp->Assign( ScriptFlags, TRUE, TRUE );
  3946. //
  3947. // Here we are checking for any assigned apps which are configured for
  3948. // default install. If such an app was previously in an install state
  3949. // before the upgrade attempt, then we put it back into this state by
  3950. // doing a default install again.
  3951. //
  3952. if ( (ERROR_SUCCESS == AssignStatus) &&
  3953. (! _pManApp->IsUserPolicy() || (_pUpgrades[n].pBaseApp->_State & APPSTATE_INSTALL)) &&
  3954. (AppPresent(_pUpgrades[n].pBaseApp->_InstallState) && (_pUpgrades[n].pBaseApp->_InstallState != INSTALLSTATE_ADVERTISED)) )
  3955. {
  3956. (void) _pUpgrades[n].pBaseApp->Install();
  3957. }
  3958. if ( ERROR_SUCCESS == AssignStatus )
  3959. {
  3960. _pUpgrades[n].pBaseApp->_bRollback = TRUE;
  3961. }
  3962. }
  3963. }
  3964. // Each upgrade rollback has its own status set ...
  3965. Status = ERROR_SUCCESS;
  3966. if ( (_State & APPSTATE_SCRIPT_NOT_EXISTED) && (_State & APPSTATE_SCRIPT_PRESENT) && _pwszLocalScriptPath )
  3967. {
  3968. //
  3969. // Remove the local script for the upgrade app since this app is not currently applied --
  3970. // we need to revert since the user does not have rights in this directory.
  3971. //
  3972. _pManApp->Revert();
  3973. DeleteFile( _pwszLocalScriptPath );
  3974. Status = _pManApp->Impersonate();
  3975. }
  3976. return Status;
  3977. }
  3978. BOOL
  3979. CAppInfo::CopyToApplicationInfo(
  3980. APPLICATION_INFO * pApplicationInfo
  3981. )
  3982. {
  3983. GuidToString( _DeploymentId, &pApplicationInfo->pwszDeploymentId );
  3984. pApplicationInfo->pwszDeploymentName = StringDuplicate( _pwszDeploymentName );
  3985. pApplicationInfo->pwszGPOName = StringDuplicate( _pwszGPOName );
  3986. pApplicationInfo->pwszProductCode = StringDuplicate( _pwszProductId );
  3987. pApplicationInfo->pwszDescriptor = 0;
  3988. pApplicationInfo->pwszSetupCommand = 0;
  3989. pApplicationInfo->Flags = 0;
  3990. if ( INSTALLUILEVEL_FULL == _InstallUILevel )
  3991. pApplicationInfo->Flags = APPINFOFLAG_FULLUI;
  3992. else
  3993. pApplicationInfo->Flags = APPINFOFLAG_BASICUI;
  3994. if ( _State & (APPSTATE_ASSIGNED | APPSTATE_PUBLISHED) )
  3995. pApplicationInfo->Flags |= APPINFOFLAG_ALREADYMANAGED;
  3996. if ( ACTION_UNINSTALL == _Action )
  3997. pApplicationInfo->Flags |= APPINFOFLAG_UNINSTALL;
  3998. else if ( ACTION_ORPHAN == _Action )
  3999. pApplicationInfo->Flags |= APPINFOFLAG_ORPHAN;
  4000. if ( ! pApplicationInfo->pwszDeploymentId ||
  4001. ! pApplicationInfo->pwszDeploymentName ||
  4002. ! pApplicationInfo->pwszGPOName ||
  4003. ! pApplicationInfo->pwszProductCode )
  4004. return FALSE;
  4005. return TRUE;
  4006. }
  4007. void
  4008. CAppInfo::AddToOverrideList(
  4009. GUID * pDeploymentId
  4010. )
  4011. {
  4012. GUID * pOldList;
  4013. if ( _pManApp->ARPList() )
  4014. return;
  4015. pOldList = _pOverrides;
  4016. _pOverrides = new GUID[_Overrides+1];
  4017. if ( ! _pOverrides )
  4018. {
  4019. _pOverrides = pOldList;
  4020. return;
  4021. }
  4022. if ( _Overrides > 0 )
  4023. {
  4024. memcpy( _pOverrides, pOldList, _Overrides * sizeof(GUID) );
  4025. delete pOldList;
  4026. }
  4027. memcpy( &_pOverrides[_Overrides++], pDeploymentId, sizeof(GUID) );
  4028. }
  4029. DWORD
  4030. CallMsiConfigureProduct(
  4031. WCHAR * pwszProduct,
  4032. int InstallLevel,
  4033. INSTALLSTATE InstallState,
  4034. WCHAR * pwszCommandLine
  4035. )
  4036. {
  4037. DWORD Status;
  4038. Status = (*gpfnMsiConfigureProductEx)( pwszProduct, InstallLevel, InstallState, pwszCommandLine );
  4039. REMAP_DARWIN_STATUS( Status );
  4040. return Status;
  4041. }
  4042. DWORD
  4043. CallMsiReinstallProduct(
  4044. WCHAR * pwszProduct
  4045. )
  4046. {
  4047. DWORD Status;
  4048. Status = (*gpfnMsiReinstallProduct)(
  4049. pwszProduct,
  4050. REINSTALLMODE_FILEOLDERVERSION | REINSTALLMODE_PACKAGE | REINSTALLMODE_MACHINEDATA | REINSTALLMODE_USERDATA | REINSTALLMODE_SHORTCUT );
  4051. REMAP_DARWIN_STATUS( Status );
  4052. return Status;
  4053. }
  4054. DWORD
  4055. CallMsiAdvertiseScript(
  4056. WCHAR * pwszScriptFile,
  4057. DWORD Flags,
  4058. PHKEY phkClasses,
  4059. BOOL bRemoveItems
  4060. )
  4061. {
  4062. return (*gpfnMsiAdvertiseScript)( pwszScriptFile, Flags, phkClasses, bRemoveItems );
  4063. }