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.

3718 lines
113 KiB

  1. //+------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: admin.cxx
  7. //
  8. // Contents:Class Factory and IUnknown methods for CClassContainer
  9. //
  10. // Author: DebiM
  11. //
  12. //-------------------------------------------------------------------------
  13. #include "cstore.hxx"
  14. //
  15. // Constructor for Class Container Class factory
  16. //
  17. unsigned long gulcInstances = 0;
  18. HRESULT GetConsistentPackageFlags(
  19. HANDLE hADs,
  20. DWORD* pdwPackageFlags,
  21. UINT* pdwUpgrades,
  22. UINT* pdwInstallUiLevel,
  23. CLASSPATHTYPE* pdwPathType,
  24. DWORD* pdwNewPackageFlags,
  25. WCHAR* wszSearchFlags)
  26. {
  27. HRESULT hr;
  28. LPOLESTR PackageAttrName;
  29. ADS_ATTR_INFO* pAttrsGot;
  30. DWORD cgot;
  31. DWORD posn;
  32. DWORD dwOldPackageFlags;
  33. DWORD dwNewPackageFlags;
  34. //
  35. // Init locals
  36. //
  37. dwOldPackageFlags = 0;
  38. PackageAttrName = PACKAGEFLAGS;
  39. pAttrsGot = NULL;
  40. hr = S_OK;
  41. if (hADs)
  42. {
  43. //
  44. // We need to find the old package flags -- we do this so we can preserve
  45. // certain properties.
  46. //
  47. hr = ADSIGetObjectAttributes(hADs, &PackageAttrName, 1, &pAttrsGot, &cgot);
  48. if (SUCCEEDED(hr))
  49. {
  50. posn = GetPropertyFromAttr(pAttrsGot, cgot, PACKAGEFLAGS);
  51. if (posn < cgot)
  52. UnpackDWFrom(pAttrsGot[posn], (DWORD *)&dwOldPackageFlags);
  53. else
  54. hr=CS_E_OBJECT_NOTFOUND;
  55. }
  56. }
  57. if (SUCCEEDED(hr))
  58. {
  59. //
  60. // Decide whether to start with existing flags or caller supplied flags based
  61. // on whether the caller passed in desired flags
  62. //
  63. dwNewPackageFlags = pdwPackageFlags ? *pdwPackageFlags : dwOldPackageFlags;
  64. //
  65. // Make sure to preserve upgrades,
  66. // installui, and pathtype transparently
  67. //
  68. dwNewPackageFlags |= dwOldPackageFlags &
  69. (ACTFLG_POSTBETA3 |
  70. ACTFLG_HasUpgrades |
  71. ACTFLG_FullInstallUI |
  72. PATHTYPEMASK);
  73. //
  74. // Now set the upgrade bit according to whether there are upgrades
  75. //
  76. if (pdwUpgrades)
  77. {
  78. dwNewPackageFlags = *pdwUpgrades ?
  79. dwNewPackageFlags | ACTFLG_HasUpgrades :
  80. dwNewPackageFlags & ~(ACTFLG_HasUpgrades);
  81. }
  82. //
  83. // Set the install UI level
  84. //
  85. if (pdwInstallUiLevel)
  86. {
  87. dwNewPackageFlags &= ~(ACTFLG_FullInstallUI);
  88. dwNewPackageFlags |= (*pdwInstallUiLevel != INSTALLUILEVEL_FULL) ?
  89. ACTFLG_FullInstallUI : 0;
  90. }
  91. //
  92. // Now or in the pathtype by shifting it to the far left -- first clear those
  93. // bits out
  94. //
  95. if (pdwPathType)
  96. {
  97. dwNewPackageFlags &= ~PATHTYPEMASK;
  98. dwNewPackageFlags |= *pdwPathType << PATHTYPESHIFT;
  99. }
  100. *pdwNewPackageFlags = dwNewPackageFlags;
  101. if (wszSearchFlags)
  102. {
  103. memset(wszSearchFlags, 0, MAX_SEARCH_FLAGS * sizeof(*wszSearchFlags));
  104. //
  105. // Previously, we determined the search flags based
  106. // on whether the package was an NT 5.0 beta 3 deployment --
  107. // this backward compatibility with beta 3 will not
  108. // be supported in subsequent versions of Windows
  109. //
  110. *wszSearchFlags = SEARCHFLAG_REMOVED;
  111. if (dwNewPackageFlags & ACTFLG_Published)
  112. {
  113. *wszSearchFlags = SEARCHFLAG_PUBLISHED;
  114. wszSearchFlags++;
  115. }
  116. if (dwNewPackageFlags & ACTFLG_Assigned)
  117. {
  118. *wszSearchFlags = SEARCHFLAG_ASSIGNED;
  119. }
  120. }
  121. }
  122. if (pAttrsGot)
  123. {
  124. FreeADsMem(pAttrsGot);
  125. }
  126. return hr;
  127. }
  128. CClassContainerCF::CClassContainerCF()
  129. {
  130. m_uRefs = 1;
  131. InterlockedIncrement((long *) &gulcInstances );
  132. }
  133. //
  134. // Destructor
  135. //
  136. CClassContainerCF::~CClassContainerCF()
  137. {
  138. InterlockedDecrement((long *) &gulcInstances );
  139. }
  140. HRESULT __stdcall CClassContainerCF::QueryInterface(REFIID riid, void * * ppvObject)
  141. {
  142. IUnknown *pUnkTemp = NULL;
  143. SCODE sc = S_OK;
  144. if( IsEqualIID( IID_IUnknown, riid ) )
  145. {
  146. pUnkTemp = (IUnknown *)(ITypeLib *)this;
  147. }
  148. else if( IsEqualIID( IID_IClassFactory, riid ) )
  149. {
  150. pUnkTemp = (IUnknown *)(IClassFactory *)this;
  151. } else
  152. {
  153. sc = (E_NOINTERFACE);
  154. }
  155. if((pUnkTemp != NULL) && (SUCCEEDED(sc)))
  156. {
  157. *ppvObject = (void * )pUnkTemp;
  158. pUnkTemp->AddRef();
  159. }
  160. return(sc);
  161. }
  162. ULONG __stdcall CClassContainerCF::AddRef()
  163. {
  164. InterlockedIncrement(( long * )&m_uRefs );
  165. return m_uRefs;
  166. }
  167. ULONG __stdcall CClassContainerCF::Release()
  168. {
  169. unsigned long uTmp = InterlockedDecrement((long *)&m_uRefs);
  170. unsigned long cRef = m_uRefs;
  171. if (uTmp == 0)
  172. {
  173. delete this;
  174. }
  175. return(cRef);
  176. }
  177. //+-------------------------------------------------------------------------
  178. //
  179. // Member: CClassContainerCF::CreateInstance
  180. //
  181. // Synopsis:
  182. // This is the default create instance on the class factory.
  183. //
  184. // Arguments: pUnkOuter - Should be NULL
  185. // riid - IID of interface wanted
  186. // ppvObject - Returns the pointer to the resulting IClassAdmin.
  187. //
  188. // Returns: S_OK
  189. // E_INVALIDARG
  190. // E_OUTOFMEMORY
  191. // MK_E_SYNTAX
  192. //
  193. //--------------------------------------------------------------------------
  194. //
  195. HRESULT __stdcall CClassContainerCF::CreateInstance(
  196. IUnknown * pUnkOuter,
  197. REFIID riid,
  198. void ** ppvObject)
  199. {
  200. CClassContainer * pIUnk = NULL;
  201. SCODE sc = S_OK;
  202. if( pUnkOuter == NULL )
  203. {
  204. if( (pIUnk = new CClassContainer()) != NULL)
  205. {
  206. sc = pIUnk->QueryInterface( riid , ppvObject );
  207. if(FAILED(sc))
  208. {
  209. sc = E_UNEXPECTED;
  210. }
  211. pIUnk->Release();
  212. }
  213. else
  214. sc = E_OUTOFMEMORY;
  215. }
  216. else
  217. {
  218. return E_INVALIDARG;
  219. }
  220. return (sc);
  221. }
  222. //+-------------------------------------------------------------------------
  223. //
  224. // Member: CClassContainerCF::CreateConnectedInstance
  225. //
  226. // Synopsis:
  227. // This method is called by the ParseDisplayName implementation
  228. // on the ClassFactory object.
  229. // When a display name is used to bind to a Class Store
  230. // an IClassAdmin is returned after binding to the container.
  231. // This method fails if the bind fails.
  232. //
  233. // Arguments: pszPath - DisplayName of Class Store Container
  234. // ppvObject - Returns the pointer to the resulting IClassAdmin.
  235. //
  236. // Returns: S_OK
  237. // E_INVALIDARG
  238. // E_OUTOFMEMORY
  239. // MK_E_SYNTAX
  240. //
  241. //--------------------------------------------------------------------------
  242. HRESULT __stdcall CClassContainerCF::CreateConnectedInstance(
  243. CServerContext* pServerContext,
  244. LPOLESTR pszPath,
  245. void ** ppvObject)
  246. {
  247. CClassContainer * pIUnk = NULL;
  248. SCODE sc = S_OK;
  249. HRESULT hr = S_OK;
  250. if ((pIUnk = new CClassContainer(pServerContext, pszPath, &sc)) != NULL)
  251. {
  252. if (SUCCEEDED(sc))
  253. {
  254. sc = pIUnk->QueryInterface( IID_IClassAdmin, ppvObject );
  255. if(FAILED(sc))
  256. {
  257. sc = E_UNEXPECTED;
  258. }
  259. }
  260. pIUnk->Release();
  261. }
  262. else
  263. sc = E_OUTOFMEMORY;
  264. return (sc);
  265. }
  266. HRESULT __stdcall CClassContainerCF::LockServer(BOOL fLock)
  267. {
  268. if(fLock)
  269. { InterlockedIncrement((long *) &gulcInstances ); }
  270. else
  271. { InterlockedDecrement((long *) &gulcInstances ); }
  272. return(S_OK);
  273. }
  274. //
  275. // IUnknown methods for CClassContainer
  276. //
  277. //
  278. HRESULT __stdcall CClassContainer::QueryInterface(REFIID riid, void * * ppvObject)
  279. {
  280. IUnknown *pUnkTemp = NULL;
  281. SCODE sc = S_OK;
  282. if( IsEqualIID( IID_IUnknown, riid ) )
  283. {
  284. pUnkTemp = (IUnknown *)(IClassAdmin *)this;
  285. }
  286. else if( IsEqualIID( IID_IClassAdmin, riid ) )
  287. {
  288. pUnkTemp = (IUnknown *)(IClassAdmin *)this;
  289. }
  290. else
  291. {
  292. sc = (E_NOINTERFACE);
  293. }
  294. if((pUnkTemp != NULL) && (SUCCEEDED(sc)))
  295. {
  296. *ppvObject = (void * )pUnkTemp;
  297. pUnkTemp->AddRef();
  298. }
  299. return(sc);
  300. }
  301. ULONG __stdcall CClassContainer::AddRef()
  302. {
  303. InterlockedIncrement(( long * )&m_uRefs );
  304. return m_uRefs;
  305. }
  306. ULONG __stdcall CClassContainer::Release()
  307. {
  308. unsigned long uTmp = InterlockedDecrement((long *)&m_uRefs);
  309. unsigned long cRef = m_uRefs;
  310. if (uTmp == 0)
  311. {
  312. delete this;
  313. }
  314. return(cRef);
  315. }
  316. // utility functions
  317. HRESULT UpdateStoreUsn(HANDLE hADs, LPOLESTR szUsn)
  318. {
  319. ADS_ATTR_INFO pAttr[1];
  320. DWORD cModified = 0;
  321. HRESULT hr = S_OK;
  322. PackStrToAttr(pAttr, STOREUSN, szUsn);
  323. hr = ADSISetObjectAttributes(hADs, pAttr, 1, &cModified);
  324. FreeAttr(pAttr[0]);
  325. return hr;
  326. }
  327. //----------------------------------------------------------
  328. // Implementation for CClassContainer
  329. //----------------------------------------------------------
  330. //
  331. CClassContainer::CClassContainer()
  332. {
  333. m_fOpen = FALSE;
  334. m_ADsContainer = NULL;
  335. m_ADsPackageContainer = NULL;
  336. m_szCategoryName = NULL;
  337. m_szPackageName = NULL;
  338. m_szPolicyName = NULL;
  339. memset (&m_PolicyId, 0, sizeof(GUID));
  340. m_uRefs = 1;
  341. }
  342. //---------------------------------------------------------------
  343. //
  344. // Function: Constructor
  345. //
  346. // Synopsis: Binds to the ClassStore given a class store path.
  347. //
  348. // Arguments:
  349. // [in]
  350. // szStoreName
  351. // Class Store Path without the leading ADCS:
  352. //
  353. // [out]
  354. // phr
  355. // Sucess code.
  356. //
  357. // Does an ADSI bind at the class store container and matches the
  358. // version numbers. if the version numbers match then it binds to the
  359. // class, package and category containers and keeps the bind handles.
  360. //----------------------------------------------------------------
  361. CClassContainer::CClassContainer(
  362. CServerContext* pServerContext,
  363. LPOLESTR szStoreName,
  364. HRESULT* phr)
  365. {
  366. DWORD dwStoreVersion = 0;
  367. LPOLESTR AttrNames[] = {STOREVERSION, POLICYDN};
  368. ADS_ATTR_INFO * pAttrsGot = NULL;
  369. DWORD cgot = 0, posn = 0;
  370. ADS_SEARCHPREF_INFO SearchPrefs[2];
  371. // set the search preference to one level search
  372. // and make the results come back in batches of size
  373. // 20 as default.
  374. SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  375. SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
  376. SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  377. SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  378. SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
  379. SearchPrefs[1].vValue.Integer = SEARCHPAGESIZE;
  380. // initialising.
  381. *phr = S_OK;
  382. m_fOpen = FALSE;
  383. m_ADsContainer = NULL;
  384. m_ADsPackageContainer = NULL;
  385. m_szCategoryName = NULL;
  386. m_szPackageName = NULL;
  387. m_szPolicyName = NULL;
  388. memset (&m_PolicyId, 0, sizeof(GUID));
  389. // Bind to a Class Store Container Object
  390. // Cache the interface pointer
  391. //
  392. *phr = StringCchCopy (m_szContainerName, _MAX_PATH, szStoreName);
  393. ERROR_ON_FAILURE(*phr);
  394. if ( pServerContext )
  395. {
  396. *phr = m_ServerContext.Initialize( pServerContext );
  397. }
  398. ERROR_ON_FAILURE(*phr);
  399. *phr = DSServerOpenDSObject( &m_ServerContext, m_szContainerName, GetDsFlags(),
  400. &m_ADsContainer);
  401. ERROR_ON_FAILURE(*phr);
  402. //
  403. // Check the Schema Version of this container
  404. //
  405. *phr = ADSIGetObjectAttributes(m_ADsContainer, AttrNames, 2, &pAttrsGot, &cgot);
  406. if ((SUCCEEDED(*phr)) && (cgot))
  407. {
  408. posn = GetPropertyFromAttr(pAttrsGot, cgot, STOREVERSION);
  409. dwStoreVersion = 0;
  410. if (posn < cgot)
  411. {
  412. UnpackDWFrom(pAttrsGot[posn], &dwStoreVersion);
  413. //
  414. // Compare the schema with the expected version
  415. //
  416. if (dwStoreVersion != SCHEMA_VERSION_NUMBER)
  417. {
  418. *phr = CS_E_INVALID_VERSION;
  419. }
  420. }
  421. if (SUCCEEDED(*phr))
  422. {
  423. LPOLESTR szPolicyPath = NULL, szPolicyName = NULL;
  424. posn = GetPropertyFromAttr(pAttrsGot, cgot, POLICYDN);
  425. if (posn < cgot)
  426. {
  427. LPOLESTR szParentPath = NULL, szPolicyGuid = NULL;
  428. UnpackStrFrom(pAttrsGot[posn], &szPolicyPath);
  429. //
  430. BuildADsParentPath(szPolicyPath, &szParentPath, &szPolicyGuid);
  431. if (szPolicyGuid && szParentPath)
  432. {
  433. if (wcslen(szPolicyGuid) == 41)
  434. {
  435. // valid GUID
  436. GUIDFromString(&szPolicyGuid[4], &m_PolicyId);
  437. }
  438. *phr = GetGPOName( &szPolicyName );
  439. }
  440. else
  441. {
  442. *phr = E_OUTOFMEMORY;
  443. }
  444. if (szParentPath)
  445. FreeADsMem(szParentPath);
  446. if (szPolicyGuid)
  447. FreeADsMem(szPolicyGuid);
  448. }
  449. m_szPolicyName = szPolicyName;
  450. }
  451. }
  452. if (pAttrsGot)
  453. FreeADsMem(pAttrsGot);
  454. ERROR_ON_FAILURE(*phr);
  455. //
  456. // Bind to the Package container Object
  457. // Cache the interface pointer
  458. //
  459. // get the package container name.
  460. BuildADsPathFromParent(m_szContainerName, PACKAGECONTAINERNAME, &m_szPackageName);
  461. m_ADsPackageContainer = NULL;
  462. // bind to the package container.
  463. *phr = DSServerOpenDSObject( &m_ServerContext, m_szPackageName, GetDsFlags(),
  464. &m_ADsPackageContainer);
  465. ERROR_ON_FAILURE(*phr);
  466. // set the search preference.
  467. *phr = ADSISetSearchPreference(m_ADsPackageContainer, SearchPrefs, 2);
  468. ERROR_ON_FAILURE(*phr);
  469. m_fOpen = TRUE;
  470. m_uRefs = 1;
  471. Error_Cleanup:
  472. *phr = RemapErrorCode(*phr, m_szContainerName);
  473. return;
  474. }
  475. CClassContainer::~CClassContainer(void)
  476. {
  477. if (m_fOpen)
  478. {
  479. m_fOpen = FALSE;
  480. }
  481. if (m_ADsPackageContainer)
  482. {
  483. ADSICloseDSObject(m_ADsPackageContainer);
  484. m_ADsPackageContainer = NULL;
  485. }
  486. if (m_szPackageName)
  487. FreeADsMem(m_szPackageName);
  488. if (m_szCategoryName)
  489. FreeADsMem(m_szCategoryName);
  490. if (m_ADsContainer)
  491. {
  492. ADSICloseDSObject(m_ADsContainer);
  493. m_ADsContainer = NULL;
  494. }
  495. }
  496. // currently unused.
  497. BOOL InvalidDSName(LPWSTR pName)
  498. {
  499. if (wcslen(pName) >= 56)
  500. return TRUE;
  501. while (*pName)
  502. {
  503. if ((*pName == L':') ||
  504. (*pName == L',') ||
  505. (*pName == L';') ||
  506. (*pName == L'/') ||
  507. (*pName == L'<') ||
  508. (*pName == L'>') ||
  509. (*pName == L'\\')||
  510. (*pName == L'+'))
  511. return TRUE;
  512. ++pName;
  513. }
  514. return FALSE;
  515. }
  516. HRESULT CClassContainer::GetGPOInfo(GUID *pGPOId, LPOLESTR *pszPolicyName)
  517. {
  518. HRESULT hr;
  519. if ((!pGPOId) || (IsBadWritePtr(pGPOId, sizeof(GUID))))
  520. return E_INVALIDARG;
  521. if ((!pszPolicyName) || (IsBadWritePtr(pszPolicyName, sizeof(LPOLESTR))))
  522. return E_OUTOFMEMORY;
  523. memcpy(pGPOId, &m_PolicyId, sizeof(GUID));
  524. if (m_szPolicyName)
  525. {
  526. *pszPolicyName = (LPOLESTR)CsMemAlloc(sizeof(WCHAR)*(1+wcslen(m_szPolicyName)));
  527. if (!(*pszPolicyName))
  528. return E_INVALIDARG;
  529. hr = StringCchCopy(*pszPolicyName, wcslen(m_szPolicyName) + 1, m_szPolicyName);
  530. if (FAILED(hr))
  531. {
  532. return hr;
  533. }
  534. }
  535. else
  536. {
  537. *pszPolicyName = (LPOLESTR)CsMemAlloc(sizeof(WCHAR)*2);
  538. if (!(*pszPolicyName))
  539. return E_OUTOFMEMORY;
  540. (*pszPolicyName)[0] = L'\0';
  541. }
  542. return S_OK;
  543. }
  544. //---------------------------------------------------------------
  545. //
  546. // Function: EnumPackages
  547. //
  548. // Synopsis: Returns an Enumerator for all the packages that satisfies
  549. // the query.
  550. //
  551. // UsedBy Add/Remove Programs
  552. //
  553. // Arguments:
  554. // [in]
  555. // pszFileExt
  556. // FileExt that has to be queried on. ignored if NULL.
  557. // pCategory
  558. // Category that has to be queried on. ignored if NULL.
  559. // dwAppFlags
  560. // One of the APPINFO_XXX. ignored if it is APPINFO_ALL.
  561. // pdwLocale
  562. // Locale that has to be queried on. Ignored if NULL.
  563. // pPlatform
  564. // Platform that has to be queried on. Ignored if NULL.
  565. //
  566. // [out]
  567. // ppIEnumPackage
  568. // Enumerator is returned.
  569. // Returns:
  570. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  571. //
  572. // Validates the inputs, Creates a EnumPackage object, makes up the
  573. // search string made up of file extension, category.
  574. //----------------------------------------------------------------
  575. HRESULT CClassContainer::EnumPackages(
  576. LPOLESTR pszFileExt,
  577. GUID *pCategory,
  578. DWORD dwAppFlags,
  579. DWORD *pdwLocale,
  580. CSPLATFORM *pPlatform,
  581. IEnumPackage **ppIEnumPackage
  582. )
  583. {
  584. const DWORD dwMaxStrLen = 1000;
  585. HRESULT hr = S_OK;
  586. CEnumPackage *pEnum = NULL;
  587. WCHAR szfilter[dwMaxStrLen], szQry[dwMaxStrLen];
  588. if (pszFileExt && IsBadStringPtr(pszFileExt, _MAX_PATH))
  589. return E_INVALIDARG;
  590. if (pCategory && IsBadReadPtr(pCategory, sizeof(GUID)))
  591. return E_INVALIDARG;
  592. if (IsBadWritePtr(ppIEnumPackage, sizeof(IEnumPackage *)))
  593. return E_INVALIDARG;
  594. *ppIEnumPackage = NULL;
  595. pEnum = new CEnumPackage(&m_ServerContext, m_PolicyId, m_szPolicyName, m_szContainerName, NULL);
  596. if(NULL == pEnum)
  597. return E_OUTOFMEMORY;
  598. //
  599. // Create a CommandText
  600. //
  601. hr = StringCchPrintf(szfilter, dwMaxStrLen, L"(& (objectClass=%s) ", CLASS_CS_PACKAGE);
  602. ERROR_ON_FAILURE(hr);
  603. if (pszFileExt)
  604. {
  605. hr = StringCchPrintf(szQry, dwMaxStrLen, L"(%s=%s*) ", PKGFILEEXTNLIST, pszFileExt);
  606. ERROR_ON_FAILURE(hr);
  607. hr = StringCchCat(szfilter, dwMaxStrLen, szQry);
  608. ERROR_ON_FAILURE(hr);
  609. }
  610. if (pCategory)
  611. {
  612. STRINGGUID szCat;
  613. StringFromGUID (*pCategory, szCat);
  614. hr = StringCchPrintf(szQry, dwMaxStrLen, L"(%s=%s) ", PKGCATEGORYLIST, szCat);
  615. ERROR_ON_FAILURE(hr);
  616. hr = StringCchCat(szfilter, dwMaxStrLen, szQry);
  617. ERROR_ON_FAILURE(hr);
  618. }
  619. hr = StringCchCat(szfilter, dwMaxStrLen, L")");
  620. ERROR_ON_FAILURE(hr);
  621. hr = pEnum->Initialize(m_szPackageName, szfilter,
  622. dwAppFlags, FALSE, pPlatform);
  623. ERROR_ON_FAILURE(hr);
  624. hr = pEnum->QueryInterface(IID_IEnumPackage, (void**)ppIEnumPackage);
  625. ERROR_ON_FAILURE(hr);
  626. return S_OK;
  627. Error_Cleanup:
  628. if (pEnum)
  629. delete pEnum;
  630. *ppIEnumPackage = NULL;
  631. return RemapErrorCode(hr, m_szContainerName);
  632. }
  633. HRESULT CClassContainer::GetDNFromPackageName(LPOLESTR pszPackageName, LPOLESTR *szDN)
  634. {
  635. HRESULT hr = S_OK;
  636. WCHAR* szfilter;
  637. WCHAR* szEscapedName;
  638. LPOLESTR AttrNames[] = {OBJECTCLASS, PACKAGEFLAGS, OBJECTDN};
  639. DWORD cAttr = 3;
  640. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  641. ADS_SEARCH_COLUMN column;
  642. DWORD dwFlags = 0;
  643. *szDN = NULL;
  644. szfilter = NULL;
  645. //
  646. // To get the DN, we perform a search. The search filter syntax requires that
  647. // the package name is properly escaped, so we retrieve such a filter below
  648. //
  649. hr = GetEscapedNameFilter( pszPackageName, &szfilter );
  650. if ( FAILED( hr ) )
  651. {
  652. RETURN_ON_FAILURE( hr );
  653. }
  654. hr = ADSIExecuteSearch(m_ADsPackageContainer, szfilter, AttrNames, cAttr, &hADsSearchHandle);
  655. CsMemFree( szfilter );
  656. RETURN_ON_FAILURE(hr);
  657. for (hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle);
  658. ((SUCCEEDED(hr)) && (hr != S_ADS_NOMORE_ROWS));
  659. hr = ADSIGetNextRow(m_ADsPackageContainer, hADsSearchHandle))
  660. {
  661. hr = DSGetAndValidateColumn(m_ADsPackageContainer, hADsSearchHandle, ADSTYPE_INTEGER, PACKAGEFLAGS, &column);
  662. if (SUCCEEDED(hr))
  663. {
  664. UnpackDWFrom(column, &dwFlags);
  665. ADSIFreeColumn(m_ADsPackageContainer, &column);
  666. }
  667. else
  668. continue;
  669. if ((dwFlags & ACTFLG_Orphan) || (dwFlags & ACTFLG_Uninstall))
  670. continue;
  671. hr = DSGetAndValidateColumn(m_ADsPackageContainer, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, OBJECTDN, &column);
  672. if (SUCCEEDED(hr))
  673. {
  674. UnpackStrAllocFrom(column, szDN);
  675. ADSIFreeColumn(m_ADsPackageContainer, &column);
  676. }
  677. else
  678. continue;
  679. break;
  680. }
  681. if (hADsSearchHandle)
  682. ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
  683. return hr;
  684. }
  685. // Gets the RDN of a package given the package Guid.
  686. HRESULT CClassContainer::BuildDNFromPackageGuid(GUID PackageGuid, LPOLESTR *szDN)
  687. {
  688. HRESULT hr = S_OK;
  689. LPOLESTR AttrName = {OBJECTDN};
  690. WCHAR szfilter[_MAX_PATH];
  691. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  692. ADS_SEARCH_COLUMN column;
  693. LPWSTR EncodedGuid = NULL;
  694. hr = ADsEncodeBinaryData((PBYTE)&PackageGuid, sizeof(GUID), &EncodedGuid);
  695. hr = StringCchPrintf(szfilter, _MAX_PATH, L"(%s=%s)", OBJECTGUID, EncodedGuid);
  696. RETURN_ON_FAILURE(hr);
  697. FreeADsMem(EncodedGuid);
  698. hr = ADSIExecuteSearch(m_ADsPackageContainer, szfilter, &AttrName, 1, &hADsSearchHandle);
  699. RETURN_ON_FAILURE(hr);
  700. hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle);
  701. if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
  702. {
  703. ERROR_ON_FAILURE(hr = CS_E_PACKAGE_NOTFOUND);
  704. }
  705. hr = DSGetAndValidateColumn(m_ADsPackageContainer, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, AttrName, &column);
  706. ERROR_ON_FAILURE(hr);
  707. if (SUCCEEDED(hr))
  708. {
  709. UnpackStrAllocFrom(column, szDN);
  710. }
  711. ADSIFreeColumn(m_ADsPackageContainer, &column);
  712. Error_Cleanup:
  713. if (hADsSearchHandle)
  714. ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
  715. return hr;
  716. }
  717. HRESULT CClassContainer::GetPackageGuid(WCHAR *szRDN, GUID *pPackageGuid)
  718. {
  719. HRESULT hr = S_OK;
  720. LPOLESTR AttrName = {OBJECTGUID};
  721. WCHAR szfilter[_MAX_PATH];
  722. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  723. ADS_SEARCH_COLUMN column;
  724. hr = ADSIExecuteSearch(m_ADsPackageContainer, szRDN, &AttrName, 1, &hADsSearchHandle);
  725. RETURN_ON_FAILURE(hr);
  726. hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle);
  727. if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
  728. {
  729. ERROR_ON_FAILURE(hr = CS_E_PACKAGE_NOTFOUND);
  730. }
  731. hr = DSGetAndValidateColumn(m_ADsPackageContainer, hADsSearchHandle, ADSTYPE_OCTET_STRING, AttrName, &column);
  732. ERROR_ON_FAILURE(hr);
  733. if (SUCCEEDED(hr))
  734. UnpackGUIDFrom(column, pPackageGuid);
  735. ADSIFreeColumn(m_ADsPackageContainer, &column);
  736. Error_Cleanup:
  737. if (hADsSearchHandle)
  738. ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
  739. return hr;
  740. }
  741. //---------------------------------------------------------------
  742. //
  743. // Function: GetPackageDetails
  744. //
  745. // Synopsis: Returns the PackageDetail corresponding to the PackageName.
  746. //
  747. // Arguments:
  748. // [in]
  749. // pszPackageId
  750. // Id of the Package.
  751. // [out]
  752. // pPackageDetail
  753. // PackageDetail info that is returned.
  754. // Returns:
  755. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  756. //
  757. // Binds to the Package object and calls GetPackageDetail with it.
  758. //----------------------------------------------------------------
  759. HRESULT CClassContainer::GetPackageDetails (
  760. LPOLESTR pszPackageName,
  761. PACKAGEDETAIL * pPackageDetail
  762. )
  763. {
  764. HRESULT hr = S_OK;
  765. HANDLE hADs = NULL;
  766. WCHAR * szFullName = NULL;
  767. ADS_ATTR_INFO * pAttr = NULL;
  768. DWORD cgot = 0;
  769. // this can be made into a search based API. Not required for the time being.
  770. // Should change it if perf is a big issue.
  771. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  772. return E_INVALIDARG;
  773. hr = GetDNFromPackageName(pszPackageName, &szFullName);
  774. ERROR_ON_FAILURE(hr);
  775. if (hr != S_OK)
  776. return CS_E_OBJECT_NOTFOUND;
  777. // binding to the package object.
  778. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(), &hADs);
  779. ERROR_ON_FAILURE(hr);
  780. // calling GetPackageDetail.
  781. hr = GetPackageDetail (hADs, NULL, pPackageDetail);
  782. ADSICloseDSObject(hADs);
  783. if (pAttr)
  784. FreeADsMem(pAttr);
  785. if (szFullName)
  786. CsMemFree(szFullName);
  787. Error_Cleanup:
  788. return RemapErrorCode(hr, m_szContainerName);
  789. }
  790. //---------------------------------------------------------------
  791. //
  792. // Function: GetPackageDetails
  793. //
  794. // Synopsis: Returns the PackageDetail corresponding to the PackageName.
  795. //
  796. // Arguments:
  797. // [in]
  798. // pszPackageId
  799. // Id of the Package.
  800. // [out]
  801. // pPackageDetail
  802. // PackageDetail info that is returned.
  803. // Returns:
  804. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  805. //
  806. // Binds to the Package object and calls GetPackageDetail with it.
  807. //----------------------------------------------------------------
  808. HRESULT CClassContainer::GetPackageDetailsFromGuid (
  809. GUID PkgGuid,
  810. PACKAGEDETAIL *pPackageDetail
  811. )
  812. {
  813. HRESULT hr = S_OK;
  814. HANDLE hADs = NULL;
  815. WCHAR * szFullName = NULL, szRDN[_MAX_PATH];
  816. ADS_ATTR_INFO * pAttr = NULL;
  817. DWORD cgot = 0;
  818. // this can be made into a search based API. Not required for the time being.
  819. // Should change it if perf is a big issue.
  820. if (IsNullGuid(PkgGuid))
  821. return E_INVALIDARG;
  822. BuildDNFromPackageGuid(PkgGuid, &szFullName);
  823. ERROR_ON_FAILURE(hr);
  824. if (hr != S_OK)
  825. return CS_E_OBJECT_NOTFOUND;
  826. // binding to the package object.
  827. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(), &hADs);
  828. ERROR_ON_FAILURE(hr);
  829. // calling GetPackageDetail.
  830. hr = GetPackageDetail (hADs, NULL, pPackageDetail);
  831. ADSICloseDSObject(hADs);
  832. if (pAttr)
  833. FreeADsMem(pAttr);
  834. if (szFullName)
  835. CsMemFree(szFullName);
  836. Error_Cleanup:
  837. return RemapErrorCode(hr, m_szContainerName);
  838. }
  839. #define FREEARR(ARR, SZ) { \
  840. DWORD curIndex; \
  841. for (curIndex = 0; curIndex < (SZ); curIndex++) \
  842. CsMemFree((ARR)[curIndex]); \
  843. CsMemFree(ARR); \
  844. ARR = NULL; \
  845. } \
  846. //---------------------------------------------------------------
  847. //
  848. // Function: ChangePackageUpgradeInfoIncremental
  849. //
  850. // Synopsis: Mark the package as upgraded by another package
  851. //
  852. // Arguments:
  853. // [in]
  854. // PackageGuid
  855. // Package Guid to identify the package.
  856. // szUpgradedByClassStore
  857. // Class Store where the package that upgrades exists
  858. // UpgradedByPackageGuid
  859. // The Guid of the package that upgrades
  860. // Add Add or remove the upgradedByrelation
  861. //
  862. // Returns:
  863. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  864. // Otherwise it packs all the required attributes in the ATTR_INFO
  865. // structure and sends it to the Directory.
  866. //----------------------------------------------------------------
  867. HRESULT CClassContainer::ChangePackageUpgradeInfoIncremental(
  868. GUID PackageGuid,
  869. UPGRADEINFO UpgradeInfo,
  870. DWORD OpFlags
  871. )
  872. {
  873. HRESULT hr = S_OK;
  874. HANDLE hADs = NULL;
  875. WCHAR *szFullName=NULL, szGuid[_MAX_PATH], szUsn[20];
  876. LPOLESTR pProp = NULL;
  877. ADS_ATTR_INFO pAttr[2];
  878. DWORD cAttr = 0, cModified = 0, i=0;
  879. UINT len=0;
  880. ULONG ulSize;
  881. hr = BuildDNFromPackageGuid(PackageGuid, &szFullName);
  882. ERROR_ON_FAILURE(hr);
  883. // Bind to the Package Object.
  884. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(), &hADs);
  885. ERROR_ON_FAILURE(hr);
  886. StringFromGUID(UpgradeInfo.PackageGuid, szGuid);
  887. len = wcslen(UpgradeInfo.szClassStore);
  888. ulSize = 36+PKG_UPG_DELIM1_LEN+len+PKG_UPG_DELIM2_LEN+2+2+1;
  889. pProp = (LPOLESTR)CsMemAlloc(sizeof(WCHAR) * ulSize);
  890. // Guid size+::+length++:+flagDigit+2
  891. hr = StringCchPrintf(pProp, ulSize, L"%s%s%s%s%02x", UpgradeInfo.szClassStore, PKG_UPG_DELIMITER1, szGuid, PKG_UPG_DELIMITER2, UpgradeInfo.Flag%16);
  892. ERROR_ON_FAILURE(hr);
  893. PackStrArrToAttrEx(pAttr+cAttr, UPGRADESPACKAGES, &pProp, 1, OpFlags?TRUE:FALSE);
  894. cAttr++;
  895. //
  896. // Update the TimeStamp
  897. //
  898. GetCurrentUsn(szUsn);
  899. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  900. cAttr++;
  901. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  902. if (hADs)
  903. ADSICloseDSObject(hADs);
  904. // ignore it if the property already exists.
  905. if (hr == HRESULT_FROM_WIN32(ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS))
  906. hr = S_OK;
  907. for (i = 0; i < cAttr; i++)
  908. FreeAttr(pAttr[i]);
  909. Error_Cleanup:
  910. if (szFullName)
  911. CsMemFree(szFullName);
  912. return RemapErrorCode(hr, m_szContainerName);
  913. }
  914. //---------------------------------------------------------------
  915. //
  916. // Function: ChangePackageProperties
  917. //
  918. // Synopsis: Change Various (most commonly changed) properties
  919. // for a given package.
  920. //
  921. // Arguments:
  922. // [in]
  923. // PackageId
  924. // Package Id to identify the package.
  925. // pszNewname
  926. // new Name for the Package. If it is being renamed
  927. // all other changes should be NULL.
  928. // pdwFlags
  929. // The Deployment Flags. Should be ACTFLG_XXX
  930. // Ignored if NULL.
  931. // pszUrl
  932. // Help Url for the Package. Ignored if NULL.
  933. // pszScriptPath
  934. // Script Path for the Package. Ignored if NULL.
  935. // pInstallUiLevel
  936. // The InstallationUiLevel. Ignored if NULL.
  937. // pdwRevision
  938. // REVISION. Ignored if NULL.
  939. //
  940. // Returns:
  941. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  942. // Otherwise it packs all the required attributes in the ATTR_INFO
  943. // structure and sends it to the Directory.
  944. //----------------------------------------------------------------
  945. HRESULT CClassContainer::ChangePackageProperties(
  946. LPOLESTR pszPackageName,
  947. LPOLESTR pszNewName,
  948. DWORD *pdwFlags,
  949. LPOLESTR pszUrl,
  950. LPOLESTR pszScriptPath,
  951. UINT *pInstallUiLevel,
  952. DWORD *pdwRevision
  953. )
  954. {
  955. HRESULT hr = S_OK;
  956. HANDLE hADs = NULL;
  957. WCHAR *szRDN=NULL, *szFullName=NULL;
  958. WCHAR szUsn[20];
  959. ADS_ATTR_INFO pAttr[9];
  960. DWORD cAttr = 0, cModified = 0, i=0;
  961. DWORD dwNewPackageFlags;
  962. WCHAR wszSearchFlags[MAX_SEARCH_FLAGS];
  963. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  964. return E_INVALIDARG;
  965. hr = GetDNFromPackageName(pszPackageName, &szFullName);
  966. ERROR_ON_FAILURE(hr);
  967. if (hr != S_OK)
  968. return CS_E_OBJECT_NOTFOUND;
  969. // if no properties have to be changed.
  970. if (!(pszScriptPath || pszUrl || pdwFlags || pInstallUiLevel || pdwRevision || pszNewName))
  971. return E_INVALIDARG;
  972. if (pszNewName)
  973. {
  974. // rename package
  975. WCHAR szNewRDN[_MAX_PATH];
  976. BOOL GenerateGuid = FALSE;
  977. GUID PackageGuidId;
  978. WCHAR pszPackageNewId[_MAX_PATH], *szJunk = NULL;
  979. if (IsBadStringPtr(pszNewName, _MAX_PATH))
  980. return E_INVALIDARG;
  981. if (pszScriptPath || pszUrl || pdwFlags || pInstallUiLevel || pdwRevision)
  982. return E_INVALIDARG;
  983. // see whether the new name is valid.
  984. // GenerateGuid = InvalidDSName(pszNewName);
  985. // see whether the newName already exists. Notice that if the same package name is
  986. // entered it will return error.
  987. hr = GetDNFromPackageName(pszNewName, &szJunk);
  988. if (szJunk)
  989. CsMemFree(szJunk);
  990. szJunk = NULL;
  991. ERROR_ON_FAILURE(hr);
  992. if (hr == S_OK)
  993. return CS_E_OBJECT_ALREADY_EXISTS;
  994. // Bind to the Package Object.
  995. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(),
  996. &hADs);
  997. if (szFullName)
  998. CsMemFree(szFullName);
  999. szFullName = NULL;
  1000. ERROR_ON_FAILURE(hr);
  1001. }
  1002. else
  1003. {
  1004. // Bind to the Package Object.
  1005. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(),
  1006. &hADs);
  1007. ERROR_ON_FAILURE(hr);
  1008. if (szFullName)
  1009. CsMemFree(szFullName);
  1010. szFullName = NULL;
  1011. }
  1012. // Just change some properties.
  1013. //
  1014. // Update the TimeStamp
  1015. //
  1016. GetCurrentUsn(szUsn);
  1017. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  1018. cAttr++;
  1019. if (SUCCEEDED(hr))
  1020. {
  1021. hr = GetConsistentPackageFlags(
  1022. hADs,
  1023. pdwFlags,
  1024. NULL,
  1025. pInstallUiLevel,
  1026. NULL,
  1027. &dwNewPackageFlags,
  1028. wszSearchFlags);
  1029. }
  1030. if (SUCCEEDED(hr))
  1031. {
  1032. //
  1033. // Set Package Flags
  1034. //
  1035. if (pdwFlags)
  1036. {
  1037. PackDWToAttr (pAttr+cAttr, PACKAGEFLAGS, dwNewPackageFlags);
  1038. cAttr++;
  1039. if (*wszSearchFlags)
  1040. {
  1041. PackStrToAttr(pAttr+cAttr, SEARCHFLAGS, wszSearchFlags);
  1042. cAttr++;
  1043. }
  1044. }
  1045. //
  1046. // Change Package Script
  1047. //
  1048. if (pszScriptPath)
  1049. {
  1050. PackStrToAttr(pAttr+cAttr, SCRIPTPATH, pszScriptPath);
  1051. cAttr++;
  1052. }
  1053. //
  1054. // Change Package Help URL
  1055. //
  1056. if (pszUrl)
  1057. {
  1058. if ( ! *pszUrl )
  1059. {
  1060. pszUrl = NULL;
  1061. }
  1062. PackStrToAttr(pAttr+cAttr, HELPURL, pszUrl);
  1063. cAttr++;
  1064. }
  1065. //
  1066. // Change Package UI Level.
  1067. //
  1068. if (pInstallUiLevel)
  1069. {
  1070. PackDWToAttr (pAttr+cAttr, UILEVEL, *pInstallUiLevel);
  1071. cAttr++;
  1072. }
  1073. //
  1074. // Change Revision.
  1075. //
  1076. if (pdwRevision)
  1077. {
  1078. PackDWToAttr (pAttr+cAttr, REVISION, *pdwRevision);
  1079. cAttr++;
  1080. }
  1081. if (pszNewName)
  1082. {
  1083. PackStrToAttr(pAttr+cAttr, PACKAGENAME, pszNewName);
  1084. cAttr++;
  1085. // also set display name so outside tools can have a
  1086. // friendly name
  1087. PackStrToAttr(pAttr+cAttr, PKGDISPLAYNAME, pszNewName);
  1088. cAttr++;
  1089. }
  1090. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1091. }
  1092. if (hADs)
  1093. ADSICloseDSObject(hADs);
  1094. for (i = 0; i < cAttr; i++)
  1095. FreeAttr(pAttr[i]);
  1096. if (SUCCEEDED(hr))
  1097. {
  1098. //
  1099. // Update Class Store Usn
  1100. //
  1101. UpdateStoreUsn(m_ADsContainer, szUsn);
  1102. }
  1103. Error_Cleanup:
  1104. if (szFullName)
  1105. CsMemFree(szFullName);
  1106. return RemapErrorCode(hr, m_szContainerName);
  1107. }
  1108. //---------------------------------------------------------------
  1109. // Function: ChangePackageCategories
  1110. //
  1111. // Synopsis: Change (Not Add) the Categories that a package
  1112. // belongs to.
  1113. //
  1114. // Arguments:
  1115. // [in]
  1116. // pszPackageName
  1117. // Package Name to identify the package.
  1118. // cCategories
  1119. // Number of Categories.
  1120. // rpCategory
  1121. // Array of categories.
  1122. //
  1123. // Returns:
  1124. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  1125. // Binds to the Package Object, Converts all the categories to strings
  1126. // Packs it and sends it to the DS.
  1127. //----------------------------------------------------------------
  1128. HRESULT CClassContainer::ChangePackageCategories(
  1129. LPOLESTR pszPackageName,
  1130. UINT cCategories,
  1131. GUID *rpCategory
  1132. )
  1133. {
  1134. //
  1135. // Does not change USN
  1136. //
  1137. HRESULT hr = S_OK;
  1138. HANDLE hADs = NULL;
  1139. WCHAR *szFullName = NULL;
  1140. LPOLESTR *pszGuid = NULL;
  1141. UINT count;
  1142. ADS_ATTR_INFO pAttr[1];
  1143. DWORD cAttr = 0, cModified = 0, i=0;
  1144. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  1145. return E_INVALIDARG;
  1146. if ((cCategories) && ((!rpCategory) ||
  1147. (IsBadReadPtr(rpCategory, sizeof(GUID) * cCategories))))
  1148. return E_INVALIDARG;
  1149. // Construct the Name of the Package Object.
  1150. GetDNFromPackageName(pszPackageName, &szFullName);
  1151. ERROR_ON_FAILURE(hr);
  1152. if (hr != S_OK)
  1153. return CS_E_OBJECT_NOTFOUND;
  1154. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(),
  1155. &hADs);
  1156. ERROR_ON_FAILURE(hr);
  1157. // fill in the categories
  1158. pszGuid = (LPOLESTR *)CsMemAlloc(cCategories * sizeof(LPOLESTR));
  1159. if (!pszGuid)
  1160. {
  1161. hr = E_OUTOFMEMORY;
  1162. ERROR_ON_FAILURE(hr);
  1163. }
  1164. // convert the GUIDs to Strings.
  1165. for (count = 0; (count < cCategories); count++)
  1166. {
  1167. pszGuid[count] = (LPOLESTR)CsMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
  1168. if (!(pszGuid[count]))
  1169. {
  1170. FREEARR(pszGuid, count);
  1171. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1172. }
  1173. StringFromGUID(rpCategory[count], pszGuid[count]);
  1174. }
  1175. // Pack it into Attribute Structure.
  1176. PackStrArrToAttr(pAttr+cAttr, PKGCATEGORYLIST, pszGuid, cCategories);
  1177. cAttr++;
  1178. // Set the Attribute
  1179. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1180. Error_Cleanup:
  1181. if (hADs)
  1182. ADSICloseDSObject(hADs);
  1183. if (pszGuid)
  1184. for (count = 0; (count < cCategories); count++)
  1185. CsMemFree(pszGuid[count]);
  1186. CsMemFree(pszGuid);
  1187. if (szFullName)
  1188. CsMemFree(szFullName);
  1189. for (i = 0; i < cAttr; i++)
  1190. FreeAttr(pAttr[i]);
  1191. return RemapErrorCode(hr, m_szContainerName);
  1192. }
  1193. //---------------------------------------------------------------
  1194. // Function: SetPriorityByFileExt
  1195. //
  1196. // Synopsis: Changes the priority of a Package corresp. to
  1197. // a file Extension.
  1198. //
  1199. // Arguments:
  1200. // [in]
  1201. // pszPackageName
  1202. // Package Name to identify the package.
  1203. // pszFileExt
  1204. // File Extension for which the priority has to be changed.
  1205. // Priority
  1206. // Priority for the Package.
  1207. //
  1208. // Returns:
  1209. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  1210. // Binds to the Package Object, Gets the file Extensions and changes
  1211. // the priority corresponding to the File Extension.
  1212. //----------------------------------------------------------------
  1213. HRESULT CClassContainer::SetPriorityByFileExt(
  1214. LPOLESTR pszPackageName,
  1215. LPOLESTR pszFileExt,
  1216. UINT Priority
  1217. )
  1218. {
  1219. HRESULT hr = S_OK;
  1220. HANDLE hADs = NULL;
  1221. WCHAR *szFullName=NULL;
  1222. LPOLESTR *prgFileExt = NULL;
  1223. WCHAR szUsn[20];
  1224. ADS_ATTR_INFO pAttr[4], *pAttrGot = NULL;
  1225. DWORD cAttr = 0, cAttrGot = 0, cModified = 0, cShellFileExt = 0, i=0;
  1226. LPOLESTR pAttrNames[] = {PKGFILEEXTNLIST};
  1227. // Construct the Package Name
  1228. GetDNFromPackageName(pszPackageName, &szFullName);
  1229. ERROR_ON_FAILURE(hr);
  1230. if (hr != S_OK)
  1231. return CS_E_OBJECT_NOTFOUND;
  1232. // Bind to the Package Object.
  1233. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(),
  1234. &hADs);
  1235. ERROR_ON_FAILURE(hr);
  1236. //
  1237. // Update the TimeStamp
  1238. //
  1239. GetCurrentUsn(szUsn);
  1240. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  1241. cAttr++;
  1242. // get the file extensions.
  1243. hr = ADSIGetObjectAttributes(hADs, pAttrNames, 1, &pAttrGot, &cAttrGot);
  1244. if ((SUCCEEDED(hr)) && (cAttrGot))
  1245. UnpackStrArrFrom(pAttrGot[0], &prgFileExt, &cShellFileExt);
  1246. // Look for the given file extension.
  1247. for (i=0; i < cShellFileExt; ++i)
  1248. {
  1249. if (wcsncmp(prgFileExt[i], pszFileExt, wcslen(pszFileExt)) == 0)
  1250. {
  1251. // if the file extension is found, change the corresponding priority.
  1252. if (wcslen(prgFileExt[i]) != (wcslen(pszFileExt)+3))
  1253. continue;
  1254. hr = StringCchPrintf(prgFileExt[i], wcslen(prgFileExt[i]) + 1, L"%s:%2d", pszFileExt, Priority%100);
  1255. ERROR_ON_FAILURE(hr);
  1256. break;
  1257. }
  1258. }
  1259. if (i == cShellFileExt)
  1260. {
  1261. ERROR_ON_FAILURE(hr = CS_E_OBJECT_NOTFOUND);
  1262. }
  1263. if (cShellFileExt)
  1264. {
  1265. PackStrArrToAttr(pAttr+cAttr, PKGFILEEXTNLIST, prgFileExt, cShellFileExt);
  1266. cAttr++;
  1267. }
  1268. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1269. if (SUCCEEDED(hr))
  1270. {
  1271. //
  1272. // Update Store Usn
  1273. //
  1274. UpdateStoreUsn(m_ADsContainer, szUsn);
  1275. }
  1276. Error_Cleanup:
  1277. CsMemFree(prgFileExt);
  1278. if (szFullName)
  1279. CsMemFree(szFullName);
  1280. for (i = 0; i < cAttr; i++)
  1281. FreeAttr(pAttr[i]);
  1282. if (pAttrGot)
  1283. FreeADsMem(pAttrGot);
  1284. ADSICloseDSObject(hADs);
  1285. return RemapErrorCode(hr, m_szContainerName);
  1286. }
  1287. //---------------------------------------------------------------
  1288. // Function: ChangePackageSourceList
  1289. //
  1290. // Synopsis: Changes the priority of a Package corresp. to
  1291. // a file Extension.
  1292. //
  1293. // Arguments:
  1294. // [in]
  1295. // pszPackageName
  1296. // Package Name to identify the package.
  1297. // cSources
  1298. // Number of sources
  1299. // pszSourceList
  1300. // List of sources
  1301. //
  1302. // Returns:
  1303. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  1304. // Binds to the Package Object, Makes the new sourcelist with the order
  1305. // maintained.
  1306. //----------------------------------------------------------------
  1307. HRESULT CClassContainer::ChangePackageSourceList(
  1308. LPOLESTR pszPackageName,
  1309. UINT cSources,
  1310. LPOLESTR *pszSourceList
  1311. )
  1312. {
  1313. HRESULT hr = S_OK;
  1314. ULONG ulSize;
  1315. HANDLE hADs = NULL;
  1316. WCHAR *szFullName = NULL;
  1317. UINT count;
  1318. WCHAR szUsn[20];
  1319. LPOLESTR *pszPrioritySourceList = NULL;
  1320. ADS_ATTR_INFO pAttr[2];
  1321. DWORD cAttr = 0, cModified = 0, i=0;
  1322. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  1323. return E_INVALIDARG;
  1324. if ((!pszSourceList) ||
  1325. (IsBadReadPtr(pszSourceList, sizeof(LPOLESTR) * cSources)))
  1326. return E_INVALIDARG;
  1327. for (count = 0; (count < cSources); count++)
  1328. if ((!pszSourceList[count]) || (IsBadStringPtr(pszSourceList[count], _MAX_PATH)))
  1329. return E_INVALIDARG;
  1330. // Construct the Name of the Package Object.
  1331. GetDNFromPackageName(pszPackageName, &szFullName);
  1332. ERROR_ON_FAILURE(hr);
  1333. if (hr != S_OK)
  1334. return CS_E_OBJECT_NOTFOUND;
  1335. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(),
  1336. &hADs);
  1337. ERROR_ON_FAILURE(hr);
  1338. // Local variable for adding the order to the list.
  1339. pszPrioritySourceList = (LPOLESTR *)CsMemAlloc(cSources * sizeof(LPOLESTR));
  1340. if (!pszPrioritySourceList)
  1341. {
  1342. hr = E_OUTOFMEMORY;
  1343. ERROR_ON_FAILURE(hr);
  1344. }
  1345. // add the order to the list
  1346. for (count = 0; (count < cSources); count++)
  1347. {
  1348. ulSize = wcslen(pszSourceList[count])+1+1+1+NumDigits10(cSources);
  1349. pszPrioritySourceList[count] = (LPOLESTR)CsMemAlloc(sizeof(WCHAR)* ulSize);
  1350. if (!(pszPrioritySourceList[count]))
  1351. {
  1352. FREEARR(pszPrioritySourceList, count);
  1353. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1354. }
  1355. hr = StringCchPrintf(pszPrioritySourceList[count], ulSize, L"%d:%s", count, pszSourceList[count]);
  1356. ERROR_ON_FAILURE(hr);
  1357. }
  1358. //
  1359. // Update the TimeStamp
  1360. //
  1361. GetCurrentUsn(szUsn);
  1362. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  1363. cAttr++;
  1364. // Pack it into Attribute Structure.
  1365. PackStrArrToAttr(pAttr+cAttr, MSIFILELIST, pszPrioritySourceList, cSources);
  1366. cAttr++;
  1367. // Set the Attribute
  1368. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1369. if (SUCCEEDED(hr))
  1370. {
  1371. //
  1372. // Update Store Usn
  1373. //
  1374. UpdateStoreUsn(m_ADsContainer, szUsn);
  1375. }
  1376. Error_Cleanup:
  1377. if (hADs)
  1378. ADSICloseDSObject(hADs);
  1379. for (i = 0; i < cAttr; i++)
  1380. FreeAttr(pAttr[i]);
  1381. if (szFullName)
  1382. CsMemFree(szFullName);
  1383. return RemapErrorCode(hr, m_szContainerName);
  1384. }
  1385. //---------------------------------------------------------------
  1386. // Function: ChangePackageUpgradeList
  1387. //
  1388. // Synopsis: Changes the priority of a Package corresp. to
  1389. // a file Extension.
  1390. //
  1391. // Arguments:
  1392. // [in]
  1393. // pszPackageName
  1394. // Package Name to identify the package.
  1395. // cSources
  1396. // Number of sources
  1397. // pszSourceList
  1398. // List of sources
  1399. //
  1400. // Returns:
  1401. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  1402. // Binds to the Package Object, Makes the new sourcelist with the order
  1403. // maintained.
  1404. //----------------------------------------------------------------
  1405. HRESULT CClassContainer::ChangePackageUpgradeList(
  1406. LPOLESTR pszPackageName,
  1407. UINT cUpgrades,
  1408. UPGRADEINFO *prgUpgradeInfoList
  1409. )
  1410. {
  1411. HRESULT hr = S_OK;
  1412. HANDLE hADs = NULL;
  1413. WCHAR *szFullName = NULL;
  1414. UINT count = 0, count1 = 0, count2 = 0;
  1415. LPOLESTR *pProp = NULL, pAttrNames[] = {UPGRADESPACKAGES, OBJECTGUID, PACKAGEFLAGS}, *rpszUpgrades = NULL;
  1416. ADS_ATTR_INFO pAttr[3], *pAttrGot = NULL;
  1417. DWORD cAttr = 0, cModified = 0, i=0, posn = 0, cUpgradeInfoStored = 0,
  1418. cAddList = 0, cRemoveList = 0, cgot = 0;
  1419. GUID PkgGuid;
  1420. WCHAR szUsn[20];
  1421. UPGRADEINFO *pUpgradeInfoStored = NULL, *pAddList = NULL, *pRemoveList = NULL;
  1422. DWORD dwPackageFlags;
  1423. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  1424. return E_INVALIDARG;
  1425. if ((cUpgrades) && ((!prgUpgradeInfoList) ||
  1426. (IsBadReadPtr(prgUpgradeInfoList, sizeof(UPGRADEINFO) * cUpgrades))))
  1427. return E_INVALIDARG;
  1428. for (count = 0; (count < cUpgrades); count++)
  1429. {
  1430. if ((!(prgUpgradeInfoList[count].szClassStore)) ||
  1431. IsBadStringPtr((prgUpgradeInfoList[count].szClassStore), _MAX_PATH))
  1432. return E_INVALIDARG;
  1433. if (IsNullGuid(prgUpgradeInfoList[count].PackageGuid))
  1434. return E_INVALIDARG;
  1435. if (((prgUpgradeInfoList[count].Flag & UPGFLG_Uninstall) == 0) &&
  1436. ((prgUpgradeInfoList[count].Flag & UPGFLG_NoUninstall) == 0) &&
  1437. ((prgUpgradeInfoList[count].Flag & UPGFLG_UpgradedBy) == 0))
  1438. return E_INVALIDARG;
  1439. }
  1440. // Construct the Name of the Package Object.
  1441. hr = GetDNFromPackageName(pszPackageName, &szFullName);
  1442. ERROR_ON_FAILURE(hr);
  1443. if (hr != S_OK)
  1444. return CS_E_OBJECT_NOTFOUND;
  1445. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(),
  1446. &hADs);
  1447. ERROR_ON_FAILURE(hr);
  1448. // get the guid and upgrade info
  1449. hr = ADSIGetObjectAttributes(hADs, pAttrNames, 3, &pAttrGot, &cgot);
  1450. ERROR_ON_FAILURE(hr);
  1451. // Package guid
  1452. posn = GetPropertyFromAttr(pAttrGot, cgot, OBJECTGUID);
  1453. if (posn < cgot)
  1454. UnpackGUIDFrom(pAttrGot[posn], &PkgGuid);
  1455. // Upgrade package
  1456. posn = GetPropertyFromAttr(pAttrGot, cgot, UPGRADESPACKAGES);
  1457. if (posn < cgot)
  1458. UnpackStrArrFrom(pAttrGot[posn], &pProp, &cUpgradeInfoStored);
  1459. // Package Flags
  1460. posn = GetPropertyFromAttr(pAttrGot, cgot, PACKAGEFLAGS);
  1461. if (posn < cgot)
  1462. UnpackDWFrom(pAttrGot[posn], (DWORD *)&dwPackageFlags);
  1463. // allocating the lists
  1464. pUpgradeInfoStored = (UPGRADEINFO *)CsMemAlloc(sizeof(UPGRADEINFO)*(cUpgradeInfoStored));
  1465. pAddList = (UPGRADEINFO *)CsMemAlloc(sizeof(UPGRADEINFO)*(cUpgrades+cUpgradeInfoStored));
  1466. pRemoveList = (UPGRADEINFO *)CsMemAlloc(sizeof(UPGRADEINFO)*(cUpgrades+cUpgradeInfoStored));
  1467. if ((!pUpgradeInfoStored) || (!pAddList) || (!pRemoveList))
  1468. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  1469. // convert the strings to upgradinfo structures.
  1470. for (count = 0; count < (cUpgradeInfoStored); count++)
  1471. {
  1472. WCHAR *pStr = NULL;
  1473. LPOLESTR ptr = pProp[count];
  1474. UINT len = wcslen (ptr);
  1475. pUpgradeInfoStored[count].szClassStore = pProp[count];
  1476. if (len <= 41)
  1477. continue;
  1478. *(ptr + len - 3) = NULL;
  1479. pUpgradeInfoStored[count].Flag = wcstoul(ptr+(len-2), &pStr, 16);
  1480. *(ptr + len - 3 - 36 - 2) = L'\0';
  1481. /* -GUID-'::'*/
  1482. GUIDFromString(ptr+len-3-36, &(pUpgradeInfoStored[count].PackageGuid));
  1483. }
  1484. cUpgradeInfoStored = count; // we might have skipped some.
  1485. // AddList formed.
  1486. for (count = 0; count < cUpgrades; count++)
  1487. {
  1488. for (count1 = 0; count1 < cUpgradeInfoStored; count1++)
  1489. {
  1490. // ignore flag changes
  1491. if ((wcscmp(pUpgradeInfoStored[count1].szClassStore, prgUpgradeInfoList[count].szClassStore) == 0) &&
  1492. (memcmp(&pUpgradeInfoStored[count1].PackageGuid, &prgUpgradeInfoList[count].PackageGuid, sizeof(GUID)) == 0))
  1493. break;
  1494. }
  1495. if (count1 == cUpgradeInfoStored)
  1496. pAddList[cAddList++] = prgUpgradeInfoList[count];
  1497. }
  1498. // remove list formed.
  1499. for (count1 = 0; count1 < cUpgradeInfoStored; count1++)
  1500. {
  1501. for (count = 0; count < cUpgrades; count++)
  1502. {
  1503. // ignore flag changes
  1504. if ((wcscmp(pUpgradeInfoStored[count1].szClassStore, prgUpgradeInfoList[count].szClassStore) == 0) &&
  1505. (memcmp(&pUpgradeInfoStored[count1].PackageGuid, &prgUpgradeInfoList[count].PackageGuid, sizeof(GUID)) == 0))
  1506. break;
  1507. }
  1508. if (count == cUpgrades)
  1509. pRemoveList[cRemoveList++] = pUpgradeInfoStored[count];
  1510. }
  1511. for (count = 0; count < cAddList; count++)
  1512. {
  1513. // in case of UpgradedBy do no try to fix up the links.
  1514. if (!(pAddList[count].Flag & UPGFLG_UpgradedBy))
  1515. {
  1516. DWORD Flags = 0;
  1517. if (pAddList[count].Flag & UPGFLG_Enforced)
  1518. Flags = UPGFLG_Enforced;
  1519. }
  1520. }
  1521. for (count = 0; count < cRemoveList; count++)
  1522. {
  1523. // in case of UpgradedBy do no try to fix up the links.
  1524. if (!(pRemoveList[count].Flag & UPGFLG_UpgradedBy))
  1525. {
  1526. DWORD Flags = 0;
  1527. if (pRemoveList[count].Flag & UPGFLG_Enforced)
  1528. Flags = UPGFLG_Enforced;
  1529. }
  1530. }
  1531. rpszUpgrades = (LPOLESTR *)CsMemAlloc(sizeof(LPOLESTR)*cUpgrades);
  1532. if (!rpszUpgrades)
  1533. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1534. for (count = 0; (count < cUpgrades); count++)
  1535. {
  1536. WCHAR szPackageGuid[_MAX_PATH];
  1537. UINT len = wcslen(prgUpgradeInfoList[count].szClassStore);
  1538. ULONG ulSize = 36+PKG_UPG_DELIM1_LEN+len+PKG_UPG_DELIM2_LEN+2+2;
  1539. rpszUpgrades[count] = (LPOLESTR)CsMemAlloc(sizeof(WCHAR) *ulSize);
  1540. // Guid size+::+length++:+flagDigit+2
  1541. if (!rpszUpgrades[count])
  1542. {
  1543. FREEARR(rpszUpgrades, count);
  1544. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1545. }
  1546. StringFromGUID(prgUpgradeInfoList[count].PackageGuid, szPackageGuid);
  1547. hr = StringCchPrintf(rpszUpgrades[count], ulSize, L"%s%s%s%s%02x", prgUpgradeInfoList[count].szClassStore, PKG_UPG_DELIMITER1, szPackageGuid,
  1548. PKG_UPG_DELIMITER2, prgUpgradeInfoList[count].Flag%16);
  1549. ERROR_ON_FAILURE(hr);
  1550. }
  1551. PackStrArrToAttr(pAttr+cAttr, UPGRADESPACKAGES, rpszUpgrades, cUpgrades);
  1552. cAttr++;
  1553. //
  1554. // Update the TimeStamp
  1555. //
  1556. GetCurrentUsn(szUsn);
  1557. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  1558. cAttr++;
  1559. //
  1560. // Update the package flags -- this call will make sure the
  1561. // ugprade flag is set if there are upgrades, clear if not
  1562. //
  1563. hr = GetConsistentPackageFlags(
  1564. NULL,
  1565. &dwPackageFlags,
  1566. &cUpgrades,
  1567. NULL,
  1568. NULL,
  1569. &dwPackageFlags,
  1570. NULL);
  1571. ERROR_ON_FAILURE(hr);
  1572. PackDWToAttr (pAttr+cAttr, PACKAGEFLAGS,
  1573. dwPackageFlags);
  1574. cAttr++;
  1575. // Set the Attribute
  1576. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1577. if (SUCCEEDED(hr))
  1578. {
  1579. //
  1580. // Update Store Usn
  1581. //
  1582. UpdateStoreUsn(m_ADsContainer, szUsn);
  1583. }
  1584. Error_Cleanup:
  1585. if (hADs)
  1586. ADSICloseDSObject(hADs);
  1587. if (szFullName)
  1588. CsMemFree(szFullName);
  1589. for (i = 0; i < cAttr; i++)
  1590. FreeAttr(pAttr[i]);
  1591. if (pAttrGot)
  1592. FreeADsMem(pAttrGot);
  1593. if (pProp)
  1594. CsMemFree(pProp);
  1595. if (pUpgradeInfoStored)
  1596. CsMemFree(pUpgradeInfoStored);
  1597. if (pAddList)
  1598. CsMemFree(pAddList);
  1599. if (pRemoveList)
  1600. CsMemFree(pRemoveList);
  1601. return RemapErrorCode(hr, m_szContainerName);
  1602. }
  1603. extern LPOLESTR szAppCategoryColumns;
  1604. //---------------------------------------------------------------
  1605. // Function: GetAppCategories
  1606. //
  1607. // Synopsis: gets the list of Package Categories in the Domain.
  1608. //
  1609. // Arguments:
  1610. // [in]
  1611. // Locale
  1612. // Locale for the categories. Used to get the description.
  1613. // [out]
  1614. // pAppCategoryList
  1615. // the list of Application Categories in the domain
  1616. //
  1617. // Returns:
  1618. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  1619. //
  1620. // Gets the FullName of the Domain, binds to the AppCategory container
  1621. // below that. and gets all the categories with approp. types.
  1622. //----------------------------------------------------------------
  1623. HRESULT CClassContainer::GetAppCategories (
  1624. LCID Locale,
  1625. APPCATEGORYINFOLIST *pAppCategoryList
  1626. )
  1627. {
  1628. HRESULT hr = S_OK;
  1629. WCHAR szfilter[_MAX_PATH];
  1630. WCHAR szRootPath[_MAX_PATH], szAppCategoryContainer[_MAX_PATH];
  1631. HANDLE hADs = NULL;
  1632. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  1633. ADS_SEARCHPREF_INFO SearchPrefs[2];
  1634. WCHAR* szContainerNameForErrorReport;
  1635. // set the search preference.
  1636. SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  1637. SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
  1638. SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  1639. // we do not expect too many categories
  1640. SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  1641. SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
  1642. SearchPrefs[1].vValue.Integer = SEARCHPAGESIZE;
  1643. if (IsBadWritePtr(pAppCategoryList, sizeof(APPCATEGORYINFOLIST)))
  1644. return E_INVALIDARG;
  1645. // If an error occurs here, we assume it occurred at the domain root
  1646. szContainerNameForErrorReport = L"LDAP://rootdse";
  1647. // get the name of the domain.
  1648. hr = GetRootPath(NULL, szRootPath, _MAX_PATH);
  1649. ERROR_ON_FAILURE(hr);
  1650. // Names returned by GetRootPath are in only 1 format and we don't need to
  1651. // use BuildADsPath.
  1652. hr = StringCchPrintf(szAppCategoryContainer, _MAX_PATH, L"%s%s%s", LDAPPREFIX, APPCATEGORYCONTAINERNAME,
  1653. szRootPath+LDAPPREFIXLENGTH);
  1654. ERROR_ON_FAILURE(hr);
  1655. // If an error occurs now, we use the name of the category container
  1656. szContainerNameForErrorReport = szAppCategoryContainer;
  1657. hr = StringCchPrintf(szfilter, _MAX_PATH, L"(objectClass=%s)", CLASS_CS_CATEGORY);
  1658. ERROR_ON_FAILURE(hr);
  1659. //
  1660. // We use the secure option in the bind below because this can get called
  1661. // in client policy context (outside of the admin tool)
  1662. //
  1663. //binds to the category container
  1664. hr = DSServerOpenDSObject(&m_ServerContext, szAppCategoryContainer,
  1665. GetDsFlags(), &hADs);
  1666. ERROR_ON_FAILURE(hr);
  1667. hr = ADSISetSearchPreference(hADs, SearchPrefs, 2);
  1668. ERROR_ON_FAILURE(hr);
  1669. // gets a search handle
  1670. hr = ADSIExecuteSearch(hADs, szfilter, pszCategoryAttrNames, cCategoryAttr, &hADsSearchHandle);
  1671. ERROR_ON_FAILURE(hr);
  1672. //
  1673. // Retrieve the list of categories from the search
  1674. // if successful, memory will be allocated for the category list
  1675. //
  1676. hr = FetchCategory(hADs, hADsSearchHandle, pAppCategoryList, Locale);
  1677. ERROR_ON_FAILURE(hr);
  1678. Error_Cleanup:
  1679. if (hADsSearchHandle)
  1680. ADSICloseSearchHandle(hADs, hADsSearchHandle);
  1681. if (hADs)
  1682. ADSICloseDSObject(hADs);
  1683. return RemapErrorCode(hr, szAppCategoryContainer);
  1684. }
  1685. //---------------------------------------------------------------
  1686. // Function: RegisterAppCategory
  1687. //
  1688. // Synopsis: Adda category and assoc desc. for the whole Domain(This is per domain
  1689. // and not per class store.)
  1690. //
  1691. // Arguments:
  1692. // [in]
  1693. // pAppCategory
  1694. // Pointer to a APPCATEGORYINFO structure to be added.
  1695. //
  1696. // Returns:
  1697. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  1698. //
  1699. // Finds the root path of the domain. binds to the category container
  1700. // underneath it. deletes this particular AppCategory.
  1701. //----------------------------------------------------------------
  1702. HRESULT CClassContainer::RegisterAppCategory (
  1703. APPCATEGORYINFO *pAppCategory
  1704. )
  1705. {
  1706. WCHAR szRootPath[_MAX_PATH], localedescription[128+16],
  1707. szAppCategoryContainer[_MAX_PATH], szRDN[_MAX_PATH],
  1708. * szFullName = NULL, szAppCatid[_MAX_PATH];
  1709. HRESULT hr = S_OK;
  1710. HANDLE hADsContainer = NULL, hADs = NULL;
  1711. ULONG i, j, cdesc = 0, posn = 0;
  1712. LPOLESTR * pszDescExisting = NULL, pszDesc = NULL;
  1713. LPOLESTR AttrName = LOCALEDESCRIPTION;
  1714. ADS_ATTR_INFO * pAttrGot = NULL, pAttr[6];
  1715. DWORD cgot = 0, cAttr = 0;
  1716. BOOL fExists = TRUE;
  1717. if ((!pAppCategory) || (IsBadReadPtr(pAppCategory, sizeof(APPCATEGORYINFO))))
  1718. return E_INVALIDARG;
  1719. if ((pAppCategory->pszDescription == NULL) ||
  1720. (IsBadStringPtr(pAppCategory->pszDescription, _MAX_PATH)))
  1721. return E_INVALIDARG;
  1722. if (IsNullGuid(pAppCategory->AppCategoryId))
  1723. return E_INVALIDARG;
  1724. //
  1725. // Enforce the maximum category description size
  1726. //
  1727. if ( wcslen(pAppCategory->pszDescription) > CAT_DESC_MAX_LEN )
  1728. {
  1729. return E_INVALIDARG;
  1730. }
  1731. // get the name of the root of the domain
  1732. hr = GetRootPath(NULL, szRootPath, _MAX_PATH);
  1733. ERROR_ON_FAILURE(hr);
  1734. // Bind to a AppCategory container
  1735. // Names returned by GetRootPath are in only 1 format and we don't need to
  1736. // use BuildADsPath.
  1737. hr = StringCchPrintf(szAppCategoryContainer, _MAX_PATH, L"%s%s%s", LDAPPREFIX, APPCATEGORYCONTAINERNAME,
  1738. szRootPath+LDAPPREFIXLENGTH);
  1739. ERROR_ON_FAILURE(hr);
  1740. // container is supposed to exist.
  1741. hr = DSServerOpenDSObject(&m_ServerContext, szAppCategoryContainer, GetDsFlags(),
  1742. &hADsContainer);
  1743. ERROR_ON_FAILURE(hr);
  1744. RDNFromGUID(pAppCategory->AppCategoryId, szRDN);
  1745. hr = StringCchPrintf(localedescription, 128+16, L"%x %s %s", pAppCategory->Locale, CAT_DESC_DELIMITER,
  1746. pAppCategory->pszDescription);
  1747. ERROR_ON_FAILURE(hr);
  1748. BuildADsPathFromParent(szAppCategoryContainer, szRDN, &szFullName);
  1749. hr = DSServerOpenDSObject( &m_ServerContext, szFullName, GetDsFlags(), &hADs);
  1750. if (SUCCEEDED(hr))
  1751. hr = ADSIGetObjectAttributes(hADs, &AttrName, 1, &pAttrGot, &cgot);
  1752. if (SUCCEEDED(hr))
  1753. {
  1754. fExists = TRUE;
  1755. }
  1756. else
  1757. {
  1758. fExists = FALSE;
  1759. PackStrToAttr(pAttr, OBJECTCLASS, CLASS_CS_CATEGORY); cAttr++;
  1760. PackGUIDToAttr(pAttr+cAttr, CATEGORYCATID, &(pAppCategory->AppCategoryId)); cAttr++;
  1761. hr = ADSICreateDSObject(hADsContainer, szRDN, pAttr, cAttr);
  1762. for (j = 0; j < cAttr; j++)
  1763. FreeAttr(pAttr[j]);
  1764. cAttr = 0;
  1765. if (hADs)
  1766. {
  1767. ADSICloseDSObject(hADs);
  1768. hADs = NULL;
  1769. }
  1770. hr = DSServerOpenDSObject(&m_ServerContext, szFullName, GetDsFlags(), &hADs);
  1771. }
  1772. if (szFullName)
  1773. FreeADsMem(szFullName);
  1774. ERROR_ON_FAILURE(hr);
  1775. if (fExists) {
  1776. if (cgot)
  1777. {
  1778. UnpackStrArrFrom(pAttrGot[0], &pszDescExisting, &cdesc);
  1779. }
  1780. // Existing list of descriptions
  1781. if (posn = FindDescription(pszDescExisting, cdesc, &(pAppCategory->Locale), NULL, 0))
  1782. { // Delete the old value
  1783. PackStrArrToAttrEx(pAttr+cAttr, LOCALEDESCRIPTION, pszDescExisting+(posn-1), 1, FALSE); cAttr++;
  1784. }
  1785. CsMemFree(pszDescExisting);
  1786. }
  1787. pszDesc = localedescription;
  1788. PackStrArrToAttrEx(pAttr+cAttr, LOCALEDESCRIPTION, &pszDesc, 1, TRUE);
  1789. cAttr++;
  1790. DWORD cModified;
  1791. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1792. Error_Cleanup:
  1793. if (pAttrGot)
  1794. FreeADsMem(pAttrGot);
  1795. for (i = 0; i < cAttr; i++)
  1796. FreeAttr(pAttr[i]);
  1797. if (hADs)
  1798. ADSICloseDSObject(hADs);
  1799. if (hADsContainer)
  1800. ADSICloseDSObject(hADsContainer);
  1801. return RemapErrorCode(hr, m_szContainerName);
  1802. }
  1803. //---------------------------------------------------------------
  1804. // Function: UnregisterAppCategory
  1805. //
  1806. // Synopsis: Removes a category from the whole Domain(This is per domain)
  1807. // and not per class store.
  1808. //
  1809. // Arguments:
  1810. // [in]
  1811. // pAppCategoryId
  1812. // Pointer to a GUID that has to be removed.
  1813. //
  1814. // Returns:
  1815. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  1816. //
  1817. // Finds the root path of the domain. binds to the category container
  1818. // underneath it. deletes this particular AppCategory.
  1819. //----------------------------------------------------------------
  1820. HRESULT CClassContainer::UnregisterAppCategory (
  1821. GUID *pAppCategoryId
  1822. )
  1823. {
  1824. WCHAR szRootPath[_MAX_PATH], szRDN[_MAX_PATH],
  1825. szAppCategoryContainer[_MAX_PATH];
  1826. HRESULT hr = S_OK;
  1827. HANDLE hADs = NULL;
  1828. if (IsBadReadPtr(pAppCategoryId, sizeof(GUID)))
  1829. return E_INVALIDARG;
  1830. hr = GetRootPath(NULL, szRootPath, _MAX_PATH);
  1831. // Bind to a AppCategory container
  1832. // Names returned by GetRootPath are in only 1 format and we don't need to
  1833. // use BuildADsPath.
  1834. hr = StringCchPrintf(szAppCategoryContainer, _MAX_PATH, L"%s%s%s", LDAPPREFIX, APPCATEGORYCONTAINERNAME,
  1835. szRootPath+LDAPPREFIXLENGTH);
  1836. ERROR_ON_FAILURE(hr);
  1837. hr = DSServerOpenDSObject(&m_ServerContext, szAppCategoryContainer, GetDsFlags(),
  1838. &hADs);
  1839. ERROR_ON_FAILURE(hr);
  1840. RDNFromGUID(*pAppCategoryId, szRDN);
  1841. hr = ADSIDeleteDSObject(hADs, szRDN);
  1842. ADSICloseDSObject(hADs);
  1843. // Delete this category
  1844. Error_Cleanup:
  1845. return RemapErrorCode(hr, m_szContainerName);
  1846. }
  1847. //---------------------------------------------------------------
  1848. // Function: DeletePackage
  1849. //
  1850. // Synopsis: Permanently remove a package and the associated Classes
  1851. // from class store
  1852. //
  1853. // Arguments:
  1854. // [in]
  1855. // PackageGuid
  1856. // Guid of the package that has to be removed.
  1857. //
  1858. // Returns:
  1859. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  1860. //
  1861. // Deletes the package.
  1862. // Tries to delete all the upgrade relationships from this package.
  1863. // Errors are ignored.
  1864. //----------------------------------------------------------------
  1865. HRESULT CClassContainer::DeletePackage (LPOLESTR szFullName
  1866. )
  1867. {
  1868. HRESULT hr = S_OK;
  1869. DWORD cStr = 0, count = 0, cgot = 0, posn = 0;
  1870. LPOLESTR szRDN = NULL, szJunk = NULL;
  1871. LPOLESTR * szStr = NULL;
  1872. LPOLESTR pAttrName[] = {UPGRADESPACKAGES, OBJECTGUID, SCRIPTPATH};
  1873. LPOLESTR szScriptPath;
  1874. ADS_ATTR_INFO * pAttr = NULL;
  1875. HANDLE hADs = NULL;
  1876. WCHAR szUsn[20];
  1877. GUID PackageGuid;
  1878. hr = DSServerOpenDSObject(&m_ServerContext, szFullName, GetDsFlags(),
  1879. &hADs);
  1880. if (!SUCCEEDED(hr))
  1881. return hr;
  1882. GetCurrentUsn(szUsn);
  1883. hr = ADSIGetObjectAttributes(
  1884. hADs,
  1885. pAttrName,
  1886. sizeof(pAttrName) / sizeof(pAttrName[0]),
  1887. &pAttr, &cgot);
  1888. memset(&PackageGuid, 0, sizeof(GUID));
  1889. posn = GetPropertyFromAttr(pAttr, cgot, OBJECTGUID);
  1890. if (posn < cgot)
  1891. UnpackGUIDFrom(pAttr[posn], &PackageGuid);
  1892. posn = GetPropertyFromAttr(pAttr, cgot, SCRIPTPATH);
  1893. if (posn < cgot)
  1894. {
  1895. UnpackStrFrom(pAttr[posn], &szScriptPath);
  1896. if (szScriptPath)
  1897. {
  1898. BOOL fDeleted;
  1899. fDeleted = DeleteFile(szScriptPath);
  1900. CSDBGPrint((DM_WARNING,
  1901. IDS_CSTORE_DELETESCRIPT,
  1902. szScriptPath,
  1903. fDeleted ? ERROR_SUCCESS : GetLastError()));
  1904. }
  1905. }
  1906. posn = GetPropertyFromAttr(pAttr, cgot, UPGRADESPACKAGES);
  1907. if (posn < cgot)
  1908. UnpackStrArrFrom(pAttr[posn], &szStr, &cStr);
  1909. for (count = 0; count < cStr; count++)
  1910. {
  1911. GUID UpgradeeGuid;
  1912. WCHAR *pStr = NULL;
  1913. LPOLESTR ptr = szStr[count];
  1914. UINT len = wcslen (ptr);
  1915. DWORD UpgradeFlag, Flags = 0;
  1916. if (len <= 41)
  1917. continue;
  1918. *(ptr + (len - 3)) = NULL;
  1919. UpgradeFlag = wcstoul(ptr+(len-2), &pStr, 16);
  1920. *(ptr + (len - 3 - 36 - 2)) = L'\0';
  1921. /* -GUID-'::'*/
  1922. GUIDFromString(ptr+len-3-36, &UpgradeeGuid);
  1923. if (UpgradeFlag & UPGFLG_Enforced)
  1924. Flags = UPGFLG_Enforced;
  1925. }
  1926. if (szStr)
  1927. CsMemFree(szStr);
  1928. szStr = NULL;
  1929. cStr = 0;
  1930. // ignore errors
  1931. if (pAttr)
  1932. FreeADsMem(pAttr);
  1933. ADSICloseDSObject(hADs);
  1934. BuildADsParentPath(szFullName, &szJunk, &szRDN);
  1935. if (szJunk)
  1936. FreeADsMem(szJunk);
  1937. hr = ADSIDeleteDSObject(m_ADsPackageContainer, szRDN);
  1938. if (szRDN)
  1939. FreeADsMem(szRDN);
  1940. if (SUCCEEDED(hr))
  1941. {
  1942. //
  1943. // Update Store Usn
  1944. //
  1945. UpdateStoreUsn(m_ADsContainer, szUsn);
  1946. }
  1947. return hr;
  1948. }
  1949. //---------------------------------------------------------------
  1950. // Function: RemovePackage
  1951. //
  1952. // Synopsis: Mark a package as disabled or orphaned
  1953. // Or permanently remove a package and the associated Classes
  1954. // from class store
  1955. //
  1956. // Arguments:
  1957. // [in]
  1958. // PackageGuid
  1959. // Guid of the package that has to be removed.
  1960. // [in]
  1961. // dwFlags
  1962. // The new flags for the package. To delete the package explicitly
  1963. // use flag zero or orphan.
  1964. //
  1965. // Returns:
  1966. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  1967. //
  1968. // Calls Delete package if the flags is zero or Orphan.
  1969. // Otherwise it sets the new flags and stamps the new time stamp.
  1970. //----------------------------------------------------------------
  1971. HRESULT CClassContainer::RemovePackage (
  1972. LPOLESTR pszPackageName,
  1973. DWORD dwFlags
  1974. )
  1975. {
  1976. HRESULT hr = S_OK;
  1977. WCHAR *szRDN = NULL, *szFullName = NULL;
  1978. HANDLE hADs = NULL;
  1979. WCHAR szUsn[20];
  1980. ADS_ATTR_INFO pAttr[7];
  1981. DWORD cAttr = 0, cModified = 0, i=0;
  1982. if ((dwFlags != 0) && !(dwFlags & ACTFLG_Orphan) && !(dwFlags & ACTFLG_Uninstall))
  1983. return E_INVALIDARG;
  1984. hr = GetDNFromPackageName(pszPackageName, &szFullName);
  1985. ERROR_ON_FAILURE(hr);
  1986. if (hr != S_OK)
  1987. return CS_E_OBJECT_NOTFOUND;
  1988. if (dwFlags == 0)
  1989. // delete the package from the class store
  1990. {
  1991. hr = DeletePackage(szFullName);
  1992. }
  1993. else
  1994. {
  1995. GUID NewPackageId;
  1996. WCHAR szNewRDN[_MAX_PATH], *szJunk = NULL;
  1997. DWORD dwPackageFlags;
  1998. WCHAR wszSearchFlags[MAX_SEARCH_FLAGS];
  1999. //
  2000. // PackageName is unchanged.
  2001. //
  2002. GetCurrentUsn(szUsn);
  2003. // Bind to the Package Object.
  2004. hr = DSServerOpenDSObject(&m_ServerContext, szFullName, GetDsFlags(), &hADs);
  2005. ERROR_ON_FAILURE(hr);
  2006. //
  2007. // We use GetConsistentPackageFlags so that we can add in one flag without
  2008. // resetting the existing flags in the attribute.
  2009. //
  2010. hr = GetConsistentPackageFlags(
  2011. hADs,
  2012. &dwFlags,
  2013. NULL,
  2014. NULL,
  2015. NULL,
  2016. &dwPackageFlags,
  2017. wszSearchFlags);
  2018. ERROR_ON_FAILURE(hr);
  2019. // setting the flag as orphan/uninstall
  2020. PackDWToAttr (pAttr+cAttr, PACKAGEFLAGS, dwPackageFlags);
  2021. cAttr++;
  2022. if (*wszSearchFlags)
  2023. {
  2024. PackStrToAttr(pAttr+cAttr, SEARCHFLAGS, wszSearchFlags);
  2025. cAttr++;
  2026. }
  2027. // stamping the modification time for cleanup later.
  2028. PackStrToAttr (pAttr+cAttr, PKGUSN, szUsn);
  2029. cAttr++;
  2030. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  2031. if (hADs)
  2032. ADSICloseDSObject(hADs);
  2033. for (i = 0; i < cAttr; i++)
  2034. FreeAttr(pAttr[i]);
  2035. if (SUCCEEDED(hr))
  2036. {
  2037. //
  2038. // Update Class Store Usn
  2039. //
  2040. UpdateStoreUsn(m_ADsContainer, szUsn);
  2041. }
  2042. }
  2043. Error_Cleanup:
  2044. if (szFullName)
  2045. CsMemFree(szFullName);
  2046. return RemapErrorCode(hr, m_szContainerName);
  2047. }
  2048. // Merges list1 and List2 into ResList removing duplicates.
  2049. HRESULT MergePropList(LPOLESTR *List1, DWORD cList1,
  2050. LPOLESTR *List2, DWORD cList2,
  2051. LPOLESTR **ResList,DWORD *cResList)
  2052. {
  2053. DWORD i, j;
  2054. *cResList = 0;
  2055. *ResList = (LPOLESTR *)CsMemAlloc(sizeof(LPOLESTR)*(cList1+cList2));
  2056. if (!*ResList)
  2057. return E_OUTOFMEMORY;
  2058. for (i = 0; i < cList1; i++)
  2059. (*ResList)[i] = List1[i];
  2060. for (i = 0; i < cList2; i++) {
  2061. for (j = 0; j < cList1; j++)
  2062. if (wcscmp((*ResList)[j], List2[i]) == 0)
  2063. break;
  2064. if (j == cList1)
  2065. (*ResList)[(*cResList)++] = List2[i];
  2066. }
  2067. return S_OK;
  2068. }
  2069. #define SCRIPT_IN_DIRECTORY 256
  2070. //---------------------------------------------------------------
  2071. // Function: RedeployPackage
  2072. //
  2073. // Synopsis: Redeploys an package object in the DS with new
  2074. // package detail information
  2075. //
  2076. // Arguments:
  2077. //
  2078. // [in]
  2079. // pPackageGuid
  2080. // Points to a guid indicating the package we wish
  2081. // to redeploy
  2082. //
  2083. // [in]
  2084. // pPackageDetail
  2085. // Pointer to a PACKAGEDETAIL info for this package
  2086. // The various validations that is done is documented
  2087. // in associated class store doc.
  2088. //
  2089. // Returns:
  2090. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  2091. //
  2092. // Validates the packagedetail structure. Packs ADS_ATTR_INFO structure with
  2093. // the values and sets those attributes on the existing object in the ds.
  2094. // If this returns an error the existing package is unaffected.
  2095. //
  2096. //----------------------------------------------------------------
  2097. HRESULT CClassContainer::RedeployPackage (
  2098. GUID* pPackageGuid,
  2099. PACKAGEDETAIL *pPackageDetail
  2100. )
  2101. {
  2102. HANDLE hExistingPackage;
  2103. HRESULT hr;
  2104. WCHAR* szFullName;
  2105. hExistingPackage = NULL;
  2106. szFullName = NULL;
  2107. //
  2108. // First, get the dn for the existing package
  2109. //
  2110. hr = BuildDNFromPackageGuid(*pPackageGuid, &szFullName);
  2111. ERROR_ON_FAILURE(hr);
  2112. //
  2113. // Bind to the existing package
  2114. //
  2115. hr = DSServerOpenDSObject( &m_ServerContext,
  2116. szFullName,
  2117. GetDsFlags(),
  2118. &hExistingPackage);
  2119. ERROR_ON_FAILURE(hr);
  2120. //
  2121. // Now we can redeploy it with the new package detail. We
  2122. // pass in a NULL package guid param because we won't
  2123. // be changing the package id.
  2124. //
  2125. hr = DeployPackage(
  2126. hExistingPackage,
  2127. pPackageDetail,
  2128. NULL);
  2129. Error_Cleanup:
  2130. if (szFullName)
  2131. {
  2132. CsMemFree(szFullName);
  2133. }
  2134. if (hExistingPackage)
  2135. {
  2136. ADSICloseDSObject(hExistingPackage);
  2137. }
  2138. return hr;
  2139. }
  2140. //---------------------------------------------------------------
  2141. // Function: AddPackage
  2142. //
  2143. // Synopsis: Adds a package object in the DS.
  2144. //
  2145. // Arguments:
  2146. // [out]
  2147. // pszPackageId
  2148. // An Id that is returned corresponding to the package.
  2149. // [in]
  2150. // pPackageDetail
  2151. // Pointer to a PACKAGEDETAIL info for this package
  2152. // The various validations that is done is documented
  2153. // in associated class store doc.
  2154. //
  2155. // Returns:
  2156. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  2157. //
  2158. // Validates the packagedetail structure. Packs ADS_ATTR_INFO structure with
  2159. // the values and tries to create the object in the DS.
  2160. // If this returns error
  2161. // the whole package is removed.
  2162. //----------------------------------------------------------------
  2163. HRESULT CClassContainer::AddPackage (
  2164. PACKAGEDETAIL *pPackageDetail,
  2165. GUID *pPkgGuid
  2166. )
  2167. {
  2168. //
  2169. // Validate parameters specific to AddPackage, then
  2170. // let the DeployPackage function do the rest of the validation
  2171. // common between this and other methods that use it
  2172. //
  2173. if (!pPkgGuid || IsBadReadPtr(pPkgGuid, sizeof(GUID)))
  2174. {
  2175. return E_INVALIDARG;
  2176. }
  2177. return DeployPackage(
  2178. NULL, // create a new package
  2179. pPackageDetail,
  2180. pPkgGuid);
  2181. }
  2182. //---------------------------------------------------------------
  2183. // Function: DeployPackage
  2184. //
  2185. // Synopsis: Deploys a package object in the DS.
  2186. //
  2187. // Arguments:
  2188. // [in]
  2189. // hExistingPackage
  2190. // Handle to an existing package to redeploy. If NULL,
  2191. // a new package is created
  2192. //
  2193. // [out]
  2194. // pszPackageId
  2195. // An Id that is returned corresponding to a new package.
  2196. // Must be specified if hExistingPackage is NULL. Not set
  2197. // on return of hExistingPackage is non-NULL.
  2198. //
  2199. // [in]
  2200. // pPackageDetail
  2201. // Pointer to a PACKAGEDETAIL info for this package
  2202. // The various validations that is done is documented
  2203. // in associated class store doc.
  2204. //
  2205. // Returns:
  2206. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  2207. //
  2208. // Validates the packagedetail structure. Packs ADS_ATTR_INFO structure with
  2209. // the values and tries to create and / or set attributes
  2210. // for the package the object in the DS.
  2211. // If this returns error when creating a new package, the whole package is removed.
  2212. // If this returns error when redeploying an existing package, the existing
  2213. // package is unaffected.
  2214. //----------------------------------------------------------------
  2215. HRESULT CClassContainer::DeployPackage(
  2216. HANDLE hExistingPackage,
  2217. PACKAGEDETAIL *pPackageDetail,
  2218. GUID *pPkgGuid
  2219. )
  2220. {
  2221. HRESULT hr = S_OK;
  2222. WCHAR szRDN [_MAX_PATH];
  2223. LPOLESTR * pszGuid1 = NULL, *pszGuid2 = NULL,
  2224. * pszGuid3 = NULL, *pszGuid4 = NULL,
  2225. * pszProgId = NULL, *pszFileExt = NULL,
  2226. * rpszUpgrades = NULL, *rpszSources = NULL,
  2227. szPackageId = NULL, szJunk = NULL;
  2228. DWORD * pdwArch=NULL, count = 0, cPackProgId = 0;
  2229. ADS_ATTR_INFO pAttr[30];
  2230. DWORD cAttr = 0;
  2231. WCHAR szUsn[20];
  2232. BOOL fPackageCreated = FALSE, GenerateGuid = FALSE;
  2233. GUID PackageGuidId;
  2234. DWORD dwPersistedPackageFlags;
  2235. WCHAR wszSearchFlags[MAX_SEARCH_FLAGS];
  2236. BOOL bCreateNewPackage;
  2237. bCreateNewPackage = hExistingPackage ? FALSE : TRUE;
  2238. if ((!(pPackageDetail->pszPackageName)) ||
  2239. IsBadStringPtr((pPackageDetail->pszPackageName), _MAX_PATH))
  2240. return E_INVALIDARG;
  2241. if (!pPackageDetail)
  2242. return E_INVALIDARG;
  2243. if (IsBadReadPtr(pPackageDetail, sizeof(PACKAGEDETAIL)))
  2244. return E_INVALIDARG;
  2245. // validating ActivationInfo.
  2246. if (pPackageDetail->pActInfo)
  2247. {
  2248. if (IsBadReadPtr(pPackageDetail->pActInfo, sizeof(ACTIVATIONINFO)))
  2249. return E_INVALIDARG;
  2250. if (IsBadReadPtr(pPackageDetail->pActInfo->pClasses,
  2251. sizeof(CLASSDETAIL) * (pPackageDetail->pActInfo->cClasses)))
  2252. return E_INVALIDARG;
  2253. // validating classdetail
  2254. for (count = 0; (count < (pPackageDetail->pActInfo->cClasses)); count++)
  2255. {
  2256. CLASSDETAIL *pClassDetail = (pPackageDetail->pActInfo->pClasses)+count;
  2257. if (IsNullGuid(pClassDetail->Clsid))
  2258. return E_INVALIDARG;
  2259. for (DWORD count1 = 0; (count1 < (pClassDetail->cProgId)); count1++)
  2260. {
  2261. // if profid is NULL or an empty string.
  2262. if ((!((pClassDetail->prgProgId)[count1])) ||
  2263. (!((pClassDetail->prgProgId)[count1][0])))
  2264. return E_INVALIDARG;
  2265. }
  2266. }
  2267. if (IsBadReadPtr(pPackageDetail->pActInfo->prgShellFileExt,
  2268. sizeof(LPOLESTR) * (pPackageDetail->pActInfo->cShellFileExt)))
  2269. return E_INVALIDARG;
  2270. for (count = 0; count < (pPackageDetail->pActInfo->cShellFileExt); count++)
  2271. {
  2272. if (!pPackageDetail->pActInfo->prgShellFileExt[count])
  2273. return E_INVALIDARG;
  2274. }
  2275. if (IsBadReadPtr(pPackageDetail->pActInfo->prgPriority,
  2276. sizeof(UINT) * (pPackageDetail->pActInfo->cShellFileExt)))
  2277. return E_INVALIDARG;
  2278. if (IsBadReadPtr(pPackageDetail->pActInfo->prgInterfaceId,
  2279. sizeof(IID) * (pPackageDetail->pActInfo->cInterfaces)))
  2280. return E_INVALIDARG;
  2281. if (IsBadReadPtr(pPackageDetail->pActInfo->prgTlbId,
  2282. sizeof(GUID) * (pPackageDetail->pActInfo->cTypeLib)))
  2283. return E_INVALIDARG;
  2284. }
  2285. // Validating InstallInfo
  2286. if ((pPackageDetail->pInstallInfo == NULL) ||
  2287. (IsBadReadPtr(pPackageDetail->pInstallInfo, sizeof(INSTALLINFO)))
  2288. )
  2289. return E_INVALIDARG;
  2290. //
  2291. // Only validate the product code if we expect one to be
  2292. // supplied -- this is only the case if this is a Windows
  2293. // Installer package, other deployments will not have
  2294. // a product code
  2295. //
  2296. if ( DrwFilePath == pPackageDetail->pInstallInfo->PathType )
  2297. {
  2298. if (IsNullGuid(pPackageDetail->pInstallInfo->ProductCode))
  2299. return E_INVALIDARG;
  2300. }
  2301. if (IsBadReadPtr(pPackageDetail->pInstallInfo->prgUpgradeInfoList,
  2302. sizeof(UPGRADEINFO)*(pPackageDetail->pInstallInfo->cUpgrades)))
  2303. return E_INVALIDARG;
  2304. for (count = 0; count < (pPackageDetail->pInstallInfo->cUpgrades); count++)
  2305. {
  2306. if ((!(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore)) ||
  2307. IsBadStringPtr((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore), _MAX_PATH))
  2308. return E_INVALIDARG;
  2309. if (IsNullGuid(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].PackageGuid))
  2310. return E_INVALIDARG;
  2311. if (((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_Uninstall) == 0) &&
  2312. ((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_NoUninstall) == 0) &&
  2313. ((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_UpgradedBy) == 0))
  2314. return E_INVALIDARG;
  2315. }
  2316. // validating PlatformInfo
  2317. if ((pPackageDetail->pPlatformInfo == NULL) ||
  2318. (IsBadReadPtr(pPackageDetail->pPlatformInfo, sizeof(PLATFORMINFO)))
  2319. )
  2320. return E_INVALIDARG;
  2321. if (IsBadReadPtr(pPackageDetail->pPlatformInfo->prgPlatform,
  2322. sizeof(CSPLATFORM) * (pPackageDetail->pPlatformInfo->cPlatforms)))
  2323. return E_INVALIDARG;
  2324. if ((pPackageDetail->pPlatformInfo->cLocales == 0) ||
  2325. (pPackageDetail->pPlatformInfo->cPlatforms == 0))
  2326. return E_INVALIDARG;
  2327. if (IsBadReadPtr(pPackageDetail->pPlatformInfo->prgLocale,
  2328. sizeof(LCID) * (pPackageDetail->pPlatformInfo->cLocales)))
  2329. return E_INVALIDARG;
  2330. // validating InstallInfo
  2331. // Validating other fields in PackageDetail structure
  2332. if ((pPackageDetail->pszSourceList == NULL) ||
  2333. (IsBadReadPtr(pPackageDetail->pszSourceList,
  2334. sizeof(LPOLESTR) * (pPackageDetail->cSources))))
  2335. return E_INVALIDARG;
  2336. for (count = 0; count < (pPackageDetail->cSources); count++)
  2337. {
  2338. if ((!pPackageDetail->pszSourceList[count]) ||
  2339. (IsBadStringPtr(pPackageDetail->pszSourceList[count], _MAX_PATH)))
  2340. return E_INVALIDARG;
  2341. }
  2342. if (pPackageDetail->rpCategory)
  2343. {
  2344. if (IsBadReadPtr(pPackageDetail->rpCategory,
  2345. sizeof(GUID) * (pPackageDetail->cCategories)))
  2346. return E_INVALIDARG;
  2347. }
  2348. // If the restrictions are too constrictive then we should go to
  2349. // the DS, to see whether it is a valid name or not. till then..
  2350. hr = GetDNFromPackageName(pPackageDetail->pszPackageName, &szJunk);
  2351. if (szJunk)
  2352. CsMemFree(szJunk);
  2353. if (FAILED(hr))
  2354. return RemapErrorCode(hr, m_szContainerName);
  2355. //
  2356. // We expect this to return S_ADS_NOMORE_ROWS if the package doesn't
  2357. // exist, otherwise it returns S_OK -- we can use this to determine
  2358. // if the package exists already (we care only if we're trying to
  2359. // create a new package)
  2360. //
  2361. if ( bCreateNewPackage && (hr == S_OK))
  2362. {
  2363. return CS_E_OBJECT_ALREADY_EXISTS;
  2364. }
  2365. else
  2366. {
  2367. ASSERT( bCreateNewPackage || (S_ADS_NOMORE_ROWS == hr) || ( hExistingPackage && (hr == S_OK) ) );
  2368. }
  2369. szPackageId = (LPOLESTR)CsMemAlloc(sizeof(WCHAR)*41);
  2370. if (!(szPackageId))
  2371. return E_OUTOFMEMORY;
  2372. memset(&PackageGuidId, 0, sizeof(GUID));
  2373. //
  2374. // generate guid if we are creating a new package -- otherwise, we don't
  2375. // need it
  2376. //
  2377. if (bCreateNewPackage)
  2378. {
  2379. CreateGuid(&PackageGuidId);
  2380. StringFromGUID(PackageGuidId, szPackageId);
  2381. //
  2382. // Create the RDN for the Package Object
  2383. //
  2384. hr = StringCchPrintf(szRDN, _MAX_PATH, L"CN=%s", szPackageId);
  2385. ERROR_ON_FAILURE(hr);
  2386. //
  2387. // Only set this attribute when creating a new object --
  2388. // Otherwise, a constraint violation will occur since it is
  2389. // not permissible to change an object's class
  2390. //
  2391. PackStrToAttr(pAttr+cAttr, OBJECTCLASS, CLASS_CS_PACKAGE); cAttr++;
  2392. }
  2393. // fill in the activation info
  2394. // add the class to the packagecontainer list
  2395. //
  2396. // Classes are not present during redeploy operations in a domain rename because
  2397. // GetPackageDetails does not return the classes. Normally, the ade regenerates
  2398. // the classes during redeploy, so this is not an issue, but for domain rename,
  2399. // class regeneration is time consuming and may generate different results
  2400. // due to the class generation api's (in Darwin) dependency on local state.
  2401. //
  2402. // We check for a special flag, ACTFLG_PreserveClasses to see if we should
  2403. // skip writing clsid's and progid's
  2404. //
  2405. BOOL bIgnoreClasses;
  2406. bIgnoreClasses = pPackageDetail->pInstallInfo->dwActFlags & ACTFLG_PreserveClasses;
  2407. if (pPackageDetail->pActInfo)
  2408. {
  2409. BOOL bWriteClasses;
  2410. BOOL bWriteEmptyValue;
  2411. UINT cClasses;
  2412. UINT cSourceClasses;
  2413. bWriteClasses = pPackageDetail->pActInfo->bHasClasses && ! bIgnoreClasses;
  2414. bWriteEmptyValue = ! pPackageDetail->pActInfo->bHasClasses;
  2415. cClasses = 0;
  2416. cSourceClasses = pPackageDetail->pActInfo->cClasses;
  2417. cPackProgId = 0;
  2418. if ( ! pPackageDetail->pActInfo->bHasClasses )
  2419. {
  2420. cSourceClasses = 0;
  2421. }
  2422. //
  2423. // To be consistent with NT5, we will not set the clsid or progid properties when the user has specified
  2424. // that we deploy classes but there are none. If the user has not specified that we should deploy
  2425. // classes, we will still set this property, but it will be zero-length
  2426. //
  2427. if ( bWriteClasses )
  2428. {
  2429. if ( cSourceClasses )
  2430. {
  2431. pszGuid1 = (LPOLESTR *)CsMemAlloc(cSourceClasses*sizeof(LPOLESTR));
  2432. if (!pszGuid1) {
  2433. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2434. }
  2435. for (count = 0; count < cSourceClasses; count++)
  2436. {
  2437. WCHAR szCtx[10];
  2438. pszGuid1[count] = (LPOLESTR)CsMemAlloc(sizeof(WCHAR)*(STRINGGUIDLEN+9));
  2439. if (!pszGuid1[count]) {
  2440. FREEARR(pszGuid1, count);
  2441. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2442. }
  2443. StringFromGUID(pPackageDetail->pActInfo->pClasses[count].Clsid, pszGuid1[count]);
  2444. hr = StringCchPrintf(szCtx, sizeof(szCtx)/sizeof(szCtx[0]), L":%8x", pPackageDetail->pActInfo->pClasses[count].dwComClassContext);
  2445. ERROR_ON_FAILURE(hr);
  2446. hr = StringCchCat(pszGuid1[count], STRINGGUIDLEN+9, szCtx);
  2447. ERROR_ON_FAILURE(hr);
  2448. cPackProgId += pPackageDetail->pActInfo->pClasses[count].cProgId;
  2449. }
  2450. cClasses = cSourceClasses;
  2451. }
  2452. }
  2453. //
  2454. // This flag should not be persisted in the ds, only used as a hint for redeploy
  2455. // to avoid overwriting the existing classes
  2456. //
  2457. pPackageDetail->pInstallInfo->dwActFlags &= ~ACTFLG_PreserveClasses;
  2458. LPOLESTR wszNullGuid;
  2459. LPOLESTR* ppszClsids;
  2460. ppszClsids = pszGuid1;
  2461. //
  2462. // If required, write the blank clsid value so that
  2463. // the NT 5.1 ADE can determine if this package has class information. Note that
  2464. // an NT 5.0 ADE will never see this because this uses a null guid -- both
  2465. // NT 5.0 and 5.1 ADE's will never accept a request from a caller to search
  2466. // for a null guid.
  2467. //
  2468. if ( bWriteEmptyValue )
  2469. {
  2470. wszNullGuid = PKG_EMPTY_CLSID_VALUE;
  2471. ppszClsids = &wszNullGuid;
  2472. cClasses = 1;
  2473. }
  2474. //
  2475. // If there are no clsids, this will cause the value to be cleared
  2476. //
  2477. if ( ( cClasses || ! bCreateNewPackage ) && ! bIgnoreClasses )
  2478. {
  2479. PackStrArrToAttr(pAttr+cAttr, PKGCLSIDLIST, ppszClsids, cClasses); cAttr++;
  2480. }
  2481. if ( bWriteClasses )
  2482. {
  2483. // collecting all the progids from the various clsids.
  2484. pszProgId = (LPOLESTR *)CsMemAlloc(sizeof(LPOLESTR)*cPackProgId);
  2485. if (!pszProgId) {
  2486. hr = E_OUTOFMEMORY;
  2487. ERROR_ON_FAILURE(hr);
  2488. }
  2489. //
  2490. // Reset our count of progid's -- we need to check for duplicates, so we
  2491. // do not assume that we will have as many progid's as we allocated space for above --
  2492. // we will increment the count for each unique progid we encounter.
  2493. //
  2494. cPackProgId = 0;
  2495. for (count = 0; count < cSourceClasses; count++) {
  2496. // for each clsid
  2497. DWORD cClassProgId, j = 0;
  2498. for (cClassProgId = 0; cClassProgId < pPackageDetail->pActInfo->pClasses[count].cProgId;
  2499. cClassProgId++)
  2500. {
  2501. // for each progid within ClassDetail
  2502. for (j = 0; j < cPackProgId; j++)
  2503. {
  2504. if (_wcsicmp(pszProgId[j],
  2505. pPackageDetail->pActInfo->pClasses[count].prgProgId[cClassProgId]) == 0)
  2506. break;
  2507. }
  2508. // needs to be added if there are no dups.
  2509. if (j == cPackProgId)
  2510. {
  2511. pszProgId[cPackProgId] =
  2512. pPackageDetail->pActInfo->pClasses[count].prgProgId[cClassProgId];
  2513. _wcslwr(pszProgId[cPackProgId]);
  2514. cPackProgId++;
  2515. }
  2516. }
  2517. }
  2518. }
  2519. else
  2520. {
  2521. //
  2522. // Reset this so that we clear out progid's if we are not writing any
  2523. //
  2524. cPackProgId = 0;
  2525. }
  2526. //
  2527. // If there are no clsids, this will cause the value to be cleared
  2528. //
  2529. if ( ( cPackProgId || ! bCreateNewPackage ) && ! bIgnoreClasses )
  2530. {
  2531. PackStrArrToAttr(pAttr+cAttr, PROGIDLIST, pszProgId, cPackProgId); cAttr++;
  2532. }
  2533. CsMemFree(pszProgId);
  2534. if (pPackageDetail->pActInfo->cShellFileExt) {
  2535. ULONG ulSize;
  2536. //
  2537. // Store a tuple in the format <file ext>:<priority>
  2538. //
  2539. pszFileExt = (LPOLESTR *)CsMemAlloc((pPackageDetail->pActInfo->cShellFileExt) * sizeof(LPOLESTR));
  2540. if (!pszFileExt)
  2541. {
  2542. hr = E_OUTOFMEMORY;
  2543. ERROR_ON_FAILURE(hr);
  2544. }
  2545. for (count = 0; count < pPackageDetail->pActInfo->cShellFileExt; count++)
  2546. {
  2547. ulSize = wcslen(pPackageDetail->pActInfo->prgShellFileExt[count])+1+2+1;
  2548. pszFileExt[count] = (LPOLESTR)CsMemAlloc(sizeof(WCHAR) *ulSize);
  2549. if (!pszFileExt[count])
  2550. {
  2551. FREEARR(pszFileExt, count);
  2552. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2553. }
  2554. // format is fileext+:+nn+NULL where nn = 2 digit priority
  2555. hr = StringCchPrintf(pszFileExt[count], ulSize, L"%s:%2d",
  2556. pPackageDetail->pActInfo->prgShellFileExt[count],
  2557. pPackageDetail->pActInfo->prgPriority[count]%100);
  2558. ERROR_ON_FAILURE(hr);
  2559. _wcslwr(pszFileExt[count]);
  2560. }
  2561. PackStrArrToAttr(pAttr+cAttr, PKGFILEEXTNLIST, pszFileExt,
  2562. pPackageDetail->pActInfo->cShellFileExt); cAttr++;
  2563. }
  2564. //
  2565. // Note: we no longer persist interfaces in the ds as this information
  2566. // is not used
  2567. //
  2568. }
  2569. // fill in the platforminfo
  2570. //
  2571. // Note that the os version contained in this structure is not referenced in the os
  2572. //
  2573. if (pPackageDetail->pPlatformInfo->cPlatforms) {
  2574. pdwArch = (DWORD *)CsMemAlloc(sizeof(DWORD)*(pPackageDetail->pPlatformInfo->cPlatforms));
  2575. if (!pdwArch)
  2576. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2577. for (count = 0; (count < (pPackageDetail->pPlatformInfo->cPlatforms)); count++)
  2578. UnpackPlatform (pdwArch+count, (pPackageDetail->pPlatformInfo->prgPlatform)+count);
  2579. PackDWArrToAttr(pAttr+cAttr, ARCHLIST, pdwArch, pPackageDetail->pPlatformInfo->cPlatforms);
  2580. cAttr++;
  2581. }
  2582. if (pPackageDetail->pPlatformInfo->cLocales) {
  2583. PackDWArrToAttr(pAttr+cAttr, LOCALEID, pPackageDetail->pPlatformInfo->prgLocale,
  2584. pPackageDetail->pPlatformInfo->cLocales);
  2585. cAttr++;
  2586. }
  2587. // fill in the installinfo
  2588. PackStrToAttr(pAttr+cAttr, PACKAGENAME, pPackageDetail->pszPackageName);
  2589. cAttr++;
  2590. // also include display name so that outside tools can get a friendly description
  2591. PackStrToAttr(pAttr+cAttr, PKGDISPLAYNAME, pPackageDetail->pszPackageName);
  2592. cAttr++;
  2593. PackDWToAttr(pAttr+cAttr, PACKAGETYPE, (DWORD)(pPackageDetail->pInstallInfo->PathType));
  2594. cAttr++;
  2595. if (pPackageDetail->pInstallInfo->pszScriptPath) {
  2596. PackStrToAttr(pAttr+cAttr, SCRIPTPATH, pPackageDetail->pInstallInfo->pszScriptPath);
  2597. cAttr++;
  2598. }
  2599. if (pPackageDetail->pInstallInfo->pszSetupCommand) {
  2600. PackStrToAttr(pAttr+cAttr, SETUPCOMMAND, pPackageDetail->pInstallInfo->pszSetupCommand);
  2601. cAttr++;
  2602. }
  2603. if (pPackageDetail->pInstallInfo->pszUrl) {
  2604. PackStrToAttr(pAttr+cAttr, HELPURL, pPackageDetail->pInstallInfo->pszUrl);
  2605. cAttr++;
  2606. }
  2607. //
  2608. // Store the current USN
  2609. //
  2610. GetCurrentUsn(szUsn);
  2611. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  2612. cAttr++;
  2613. // package flags
  2614. dwPersistedPackageFlags = pPackageDetail->pInstallInfo->dwActFlags |
  2615. ACTFLG_POSTBETA3;
  2616. //
  2617. // Now set the flags so that they reflect the state of this package
  2618. //
  2619. hr = GetConsistentPackageFlags(
  2620. NULL,
  2621. &dwPersistedPackageFlags,
  2622. &(pPackageDetail->pInstallInfo->cUpgrades),
  2623. &(pPackageDetail->pInstallInfo->InstallUiLevel),
  2624. &(pPackageDetail->pInstallInfo->PathType),
  2625. &dwPersistedPackageFlags,
  2626. wszSearchFlags);
  2627. ERROR_ON_FAILURE(hr);
  2628. //
  2629. // Add in a flag indicating this is a post-Beta 3 deployment
  2630. //
  2631. PackDWToAttr(pAttr+cAttr, PACKAGEFLAGS, dwPersistedPackageFlags);
  2632. cAttr++;
  2633. if (*wszSearchFlags)
  2634. {
  2635. PackStrToAttr(pAttr+cAttr, SEARCHFLAGS, wszSearchFlags);
  2636. cAttr++;
  2637. }
  2638. // product code, different from pkg guid
  2639. PackGUIDToAttr(pAttr+cAttr, PRODUCTCODE, &(pPackageDetail->pInstallInfo->ProductCode));
  2640. cAttr++;
  2641. // Mvipc
  2642. PackGUIDToAttr(pAttr+cAttr, MVIPC, &(pPackageDetail->pInstallInfo->Mvipc));
  2643. cAttr++;
  2644. // Hi Version of the package
  2645. PackDWToAttr(pAttr+cAttr, VERSIONHI, pPackageDetail->pInstallInfo->dwVersionHi);
  2646. cAttr++;
  2647. // Low Version of the package
  2648. PackDWToAttr(pAttr+cAttr, VERSIONLO, pPackageDetail->pInstallInfo->dwVersionLo);
  2649. cAttr++;
  2650. // Revision
  2651. PackDWToAttr(pAttr+cAttr, REVISION, pPackageDetail->pInstallInfo->dwRevision);
  2652. cAttr++;
  2653. // uilevel
  2654. PackDWToAttr (pAttr+cAttr, UILEVEL, (DWORD)pPackageDetail->pInstallInfo->InstallUiLevel);
  2655. cAttr++;
  2656. // adding cUpgrade number of Classstore/PackageGuid combinations
  2657. if (pPackageDetail->pInstallInfo->cUpgrades)
  2658. {
  2659. WCHAR szPackageGuid[_MAX_PATH];
  2660. rpszUpgrades = (LPOLESTR *)CsMemAlloc(sizeof(LPOLESTR)*pPackageDetail->pInstallInfo->cUpgrades);
  2661. if (!rpszUpgrades)
  2662. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2663. for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++)
  2664. {
  2665. UINT len = wcslen(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore);
  2666. ULONG ulSize = 36+PKG_UPG_DELIM1_LEN+len+PKG_UPG_DELIM2_LEN+2+2;
  2667. rpszUpgrades[count] = (LPOLESTR)CsMemAlloc(sizeof(WCHAR) *ulSize);
  2668. // Guid size+::+length++:+flagDigit+2
  2669. if (!rpszUpgrades[count])
  2670. {
  2671. FREEARR(rpszUpgrades, count);
  2672. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2673. }
  2674. StringFromGUID(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].PackageGuid,
  2675. szPackageGuid);
  2676. hr = StringCchPrintf(rpszUpgrades[count], ulSize, L"%s%s%s%s%02x",
  2677. pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore,
  2678. PKG_UPG_DELIMITER1,
  2679. szPackageGuid,
  2680. PKG_UPG_DELIMITER2,
  2681. pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag%16);
  2682. ERROR_ON_FAILURE(hr);
  2683. }
  2684. PackStrArrToAttr(pAttr+cAttr, UPGRADESPACKAGES, rpszUpgrades,
  2685. pPackageDetail->pInstallInfo->cUpgrades);
  2686. cAttr++;
  2687. }
  2688. // Fill in the source list
  2689. // Maintain the serial number associated with the sources. Order matters!!
  2690. if (pPackageDetail->cSources)
  2691. {
  2692. rpszSources = (LPOLESTR *)CsMemAlloc(sizeof(LPOLESTR)*(pPackageDetail->cSources));
  2693. if (!rpszSources)
  2694. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2695. for (count = 0; count < (pPackageDetail->cSources); count++)
  2696. {
  2697. ULONG ulSize = wcslen(pPackageDetail->pszSourceList[count])+1+1+NumDigits10(pPackageDetail->cSources);
  2698. rpszSources[count] = (LPOLESTR)CsMemAlloc(sizeof(WCHAR)* ulSize);
  2699. if (!rpszSources[count])
  2700. {
  2701. FREEARR(rpszSources, count);
  2702. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2703. }
  2704. hr = StringCchPrintf(rpszSources[count], ulSize, L"%d:%s", count, pPackageDetail->pszSourceList[count]);
  2705. ERROR_ON_FAILURE(hr);
  2706. }
  2707. PackStrArrToAttr(pAttr+cAttr, MSIFILELIST, rpszSources, pPackageDetail->cSources);
  2708. cAttr++;
  2709. }
  2710. // fill in the categories
  2711. // Add the package Categories
  2712. if (pPackageDetail->cCategories)
  2713. {
  2714. pszGuid4 = (LPOLESTR *)CsMemAlloc((pPackageDetail->cCategories) * sizeof(LPOLESTR));
  2715. if (!pszGuid4)
  2716. {
  2717. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2718. }
  2719. for (count = 0; (count < pPackageDetail->cCategories); count++)
  2720. {
  2721. pszGuid4[count] = (LPOLESTR)CsMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
  2722. if (!pszGuid4[count])
  2723. {
  2724. FREEARR(pszGuid4, count);
  2725. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2726. }
  2727. StringFromGUID((pPackageDetail->rpCategory)[count], pszGuid4[count]);
  2728. }
  2729. PackStrArrToAttr(pAttr+cAttr, PKGCATEGORYLIST, pszGuid4, pPackageDetail->cCategories);
  2730. cAttr++;
  2731. }
  2732. // fill in the vendor
  2733. // Publisher
  2734. if (pPackageDetail->pszPublisher)
  2735. {
  2736. PackStrToAttr(pAttr+cAttr, PUBLISHER, pPackageDetail->pszPublisher);
  2737. cAttr++;
  2738. }
  2739. //
  2740. // Create a new package if specified by the caller
  2741. //
  2742. if (bCreateNewPackage)
  2743. {
  2744. hr = ADSICreateDSObject(m_ADsPackageContainer, szRDN, pAttr, cAttr);
  2745. ERROR_ON_FAILURE(hr);
  2746. memset(pPkgGuid, 0, sizeof(GUID));
  2747. hr = GetPackageGuid(szRDN, pPkgGuid);
  2748. }
  2749. else
  2750. {
  2751. DWORD cModified;
  2752. //
  2753. // The caller specified us to use an existing package -- do not
  2754. // create a new one, just set the attributes for the existing package.
  2755. // The ADSISetObjectAttributes call will either set all attributes or
  2756. // none -- so if it fails, the package is just as it was
  2757. // before we attempted to redeploy.
  2758. //
  2759. hr = ADSISetObjectAttributes(hExistingPackage, pAttr, cAttr, &cModified);
  2760. }
  2761. ERROR_ON_FAILURE(hr);
  2762. fPackageCreated = bCreateNewPackage ? TRUE : FALSE;
  2763. if (!(pPackageDetail->pInstallInfo->dwActFlags & ACTFLG_Uninstall) &&
  2764. !(pPackageDetail->pInstallInfo->dwActFlags & ACTFLG_Orphan))
  2765. {
  2766. if (pPackageDetail->pInstallInfo->cUpgrades)
  2767. {
  2768. for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++)
  2769. CsMemFree(rpszUpgrades[count]);
  2770. CsMemFree(rpszUpgrades);
  2771. }
  2772. }
  2773. if (SUCCEEDED(hr))
  2774. {
  2775. //
  2776. // Update Store Usn
  2777. //
  2778. UpdateStoreUsn(m_ADsContainer, szUsn);
  2779. }
  2780. Error_Cleanup:
  2781. for (count = 0; count < cAttr; count++)
  2782. FreeAttr(pAttr[count]);
  2783. if (pszGuid1) {
  2784. for (count = 0; (count < pPackageDetail->pActInfo->cClasses); count++)
  2785. CsMemFree(pszGuid1[count]);
  2786. CsMemFree(pszGuid1);
  2787. }
  2788. if (pszGuid2) {
  2789. for (count = 0; (count < (pPackageDetail->pActInfo->cInterfaces)); count++)
  2790. CsMemFree(pszGuid2[count]);
  2791. CsMemFree(pszGuid2);
  2792. }
  2793. if (pszGuid3) {
  2794. for (count = 0; (count < (pPackageDetail->pActInfo->cTypeLib)); count++)
  2795. CsMemFree(pszGuid3[count]);
  2796. CsMemFree(pszGuid3);
  2797. }
  2798. if (pszGuid4) {
  2799. for (count = 0; (count < pPackageDetail->cCategories); count++)
  2800. CsMemFree(pszGuid4[count]);
  2801. CsMemFree(pszGuid4);
  2802. }
  2803. if (pszFileExt) {
  2804. for (count = 0; (count < pPackageDetail->pActInfo->cShellFileExt); count++)
  2805. CsMemFree(pszFileExt[count]);
  2806. CsMemFree(pszFileExt);
  2807. }
  2808. if (pdwArch) {
  2809. CsMemFree(pdwArch);
  2810. }
  2811. if (rpszSources)
  2812. {
  2813. for (count = 0; (count < pPackageDetail->cSources); count++)
  2814. CsMemFree(rpszSources[count]);
  2815. CsMemFree(rpszSources);
  2816. }
  2817. //
  2818. // On failure, the package should be removed from the ds if we
  2819. // created it there.
  2820. //
  2821. if (FAILED(hr) && (fPackageCreated))
  2822. {
  2823. HRESULT hrDeleted;
  2824. LPWSTR wszPackageFullPath;
  2825. //
  2826. // Need to get a full path to the package in order to delete it.
  2827. //
  2828. hrDeleted = BuildADsPathFromParent(m_szPackageName, szRDN, &wszPackageFullPath);
  2829. ASSERT(SUCCEEDED(hrDeleted));
  2830. CSDBGPrint((DM_WARNING, IDS_CSTORE_ROLLBACK_ADD, wszPackageFullPath));
  2831. hrDeleted = DeletePackage(wszPackageFullPath);
  2832. //
  2833. // Free the full path
  2834. //
  2835. CsMemFree(wszPackageFullPath);
  2836. }
  2837. return RemapErrorCode(hr, m_szContainerName);
  2838. }
  2839. //+
  2840. //
  2841. // Cleanup old packages from Class Store based on lastChangeTime
  2842. //
  2843. HRESULT CClassContainer::Cleanup (
  2844. FILETIME *pTimeBefore
  2845. )
  2846. {
  2847. //
  2848. // Delete all packages marked as "Uninstall"
  2849. // OR "Orphan" and are older than the time given
  2850. //
  2851. ULONG cRowsFetched = 0;
  2852. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  2853. WCHAR szFilter[_MAX_PATH], szRDN[_MAX_PATH];
  2854. HRESULT hr = S_OK;
  2855. ADS_ATTR_INFO pAttr;
  2856. SYSTEMTIME SystemTime;
  2857. ADS_SEARCH_COLUMN column;
  2858. DWORD dwPackageFlags;
  2859. LPOLESTR pszPackageId = NULL;
  2860. if ((!pTimeBefore) ||
  2861. IsBadReadPtr(pTimeBefore, sizeof(FILETIME)))
  2862. return E_INVALIDARG;
  2863. FileTimeToSystemTime(
  2864. (CONST FILETIME *) pTimeBefore,
  2865. &SystemTime);
  2866. hr = StringCchPrintf (szFilter,
  2867. _MAX_PATH,
  2868. L"(%s<=%04d%02d%02d%02d%02d%02d)",
  2869. PKGUSN,
  2870. SystemTime.wYear,
  2871. SystemTime.wMonth,
  2872. SystemTime.wDay,
  2873. SystemTime.wHour,
  2874. SystemTime.wMinute,
  2875. SystemTime.wSecond);
  2876. ERROR_ON_FAILURE(hr);
  2877. CSDBGPrint((DM_VERBOSE,
  2878. IDS_CSTORE_CLEANSCRIPTS,
  2879. SystemTime.wMonth,
  2880. SystemTime.wDay,
  2881. SystemTime.wYear,
  2882. SystemTime.wHour,
  2883. SystemTime.wMinute,
  2884. SystemTime.wSecond));
  2885. // execute the search and keep the handle returned.
  2886. hr = ADSIExecuteSearch(m_ADsPackageContainer, szFilter, pszDeleteAttrNames,
  2887. cDeleteAttr, &hADsSearchHandle);
  2888. hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle);
  2889. while (TRUE)
  2890. {
  2891. if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
  2892. break;
  2893. dwPackageFlags = 0;
  2894. // Get the Package State
  2895. hr = DSGetAndValidateColumn(m_ADsPackageContainer, hADsSearchHandle, ADSTYPE_INTEGER, PACKAGEFLAGS, &column);
  2896. if (SUCCEEDED(hr))
  2897. {
  2898. UnpackDWFrom(column, &dwPackageFlags);
  2899. ADSIFreeColumn(m_ADsPackageContainer, &column);
  2900. }
  2901. //
  2902. // Check flag values to see if this package is Orphaned or Uninstalled
  2903. //
  2904. if ((dwPackageFlags & ACTFLG_Orphan) || (dwPackageFlags & ACTFLG_Uninstall))
  2905. {
  2906. hr = DSGetAndValidateColumn(m_ADsPackageContainer, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, OBJECTDN, &column);
  2907. if (SUCCEEDED(hr))
  2908. {
  2909. WCHAR * szDN = NULL;
  2910. UnpackStrFrom(column, &szDN);
  2911. hr = DeletePackage(szDN);
  2912. CSDBGPrint((DM_WARNING,
  2913. IDS_CSTORE_DELPACKAGE,
  2914. szDN,
  2915. dwPackageFlags,
  2916. hr));
  2917. ADSIFreeColumn(m_ADsPackageContainer, &column);
  2918. ERROR_ON_FAILURE(hr);
  2919. }
  2920. }
  2921. hr = ADSIGetNextRow(m_ADsPackageContainer, hADsSearchHandle);
  2922. }
  2923. Error_Cleanup:
  2924. if (hADsSearchHandle)
  2925. ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
  2926. return RemapErrorCode(hr, m_szContainerName);
  2927. }
  2928. HRESULT CClassContainer::GetGPOName( WCHAR** ppszPolicyName )
  2929. {
  2930. HRESULT hr;
  2931. HANDLE hGpo;
  2932. ADS_ATTR_INFO* pAttr;
  2933. LPOLESTR AttrNames[] = {GPNAME};
  2934. DWORD cgot;
  2935. DWORD posn;
  2936. WCHAR* wszGpoPath;
  2937. pAttr = NULL;
  2938. hGpo = NULL;
  2939. //
  2940. // This object contains the path to a class store container --
  2941. // this path is of the form LDAP://CN=ClassStore,CN=User,<gpopath>.
  2942. // This means that the gpo path is shorter than the class store path,
  2943. // and we can allocate memory accordingly.
  2944. //
  2945. DWORD cbClassStorePath;
  2946. cbClassStorePath = lstrlen( m_szContainerName ) * sizeof ( *m_szContainerName );
  2947. wszGpoPath = (WCHAR*) CsMemAlloc( cbClassStorePath );
  2948. if ( ! wszGpoPath )
  2949. {
  2950. hr = E_OUTOFMEMORY;
  2951. goto GetGpoName_ExitAndCleanup;
  2952. }
  2953. WCHAR* wszGpoSubPath;
  2954. //
  2955. // Get past the prefix
  2956. //
  2957. wszGpoSubPath = StripLinkPrefix( m_szContainerName );
  2958. //
  2959. // Now get past the next two delimiters
  2960. //
  2961. wszGpoSubPath = wcschr( wszGpoSubPath, L',' ) + 1;
  2962. wszGpoSubPath = wcschr( wszGpoSubPath, L',' );
  2963. //
  2964. // Move one past the last delimiter -- we are now at the gpo path
  2965. //
  2966. wszGpoSubPath++;
  2967. //
  2968. // Create the resultant path starting with the prefix
  2969. //
  2970. hr = StringCbCopy( wszGpoPath, cbClassStorePath, LDAPPREFIX );
  2971. if (FAILED(hr))
  2972. {
  2973. goto GetGpoName_ExitAndCleanup;
  2974. }
  2975. //
  2976. // Append the gpo path -- we now have a fully qualified
  2977. // LDAP path to the GPO
  2978. //
  2979. hr = StringCbCat( wszGpoPath, cbClassStorePath, wszGpoSubPath );
  2980. if (FAILED(hr))
  2981. {
  2982. goto GetGpoName_ExitAndCleanup;
  2983. }
  2984. hr = DSServerOpenDSObject(&m_ServerContext,
  2985. wszGpoPath,
  2986. GetDsFlags(),
  2987. &hGpo);
  2988. if (FAILED(hr))
  2989. {
  2990. goto GetGpoName_ExitAndCleanup;
  2991. }
  2992. //
  2993. // Now get the friendly name of this gpo
  2994. //
  2995. hr = ADSIGetObjectAttributes(
  2996. hGpo,
  2997. AttrNames,
  2998. sizeof(AttrNames) / sizeof(*AttrNames),
  2999. &pAttr,
  3000. &cgot);
  3001. if ( SUCCEEDED(hr) )
  3002. {
  3003. ASSERT( 1 == cgot );
  3004. UnpackStrAllocFrom(pAttr[0], ppszPolicyName);
  3005. if ( ! *ppszPolicyName )
  3006. {
  3007. hr = E_OUTOFMEMORY;
  3008. }
  3009. }
  3010. GetGpoName_ExitAndCleanup:
  3011. if ( pAttr )
  3012. {
  3013. FreeADsMem( pAttr );
  3014. }
  3015. if (hGpo)
  3016. {
  3017. ADSICloseDSObject( hGpo );
  3018. }
  3019. if (wszGpoPath)
  3020. {
  3021. CsMemFree( wszGpoPath );
  3022. }
  3023. return hr;
  3024. }