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

3160 lines
97 KiB

  1. //
  2. // Author: DebiM
  3. // Date: January 97
  4. //
  5. //
  6. // Class Store Administration Implementation
  7. //
  8. // This source file contains implementations for
  9. // IClassAdmin interface.
  10. //
  11. // It uses ADs interfaces (over LDAP) to talk to an LDAP
  12. // provider such as NTDS.
  13. //
  14. //---------------------------------------------------------------------
  15. #include "cstore.hxx"
  16. // utility functions
  17. HRESULT UpdateStoreUsn(HANDLE hADs, LPOLESTR szUsn)
  18. {
  19. ADS_ATTR_INFO pAttr[1];
  20. DWORD cModified = 0;
  21. HRESULT hr = S_OK;
  22. PackStrToAttr(pAttr, STOREUSN, szUsn);
  23. hr = ADSISetObjectAttributes(hADs, pAttr, 1, &cModified);
  24. FreeAttr(pAttr[0]);
  25. return hr;
  26. }
  27. //----------------------------------------------------------
  28. // Implementation for CClassContainer
  29. //----------------------------------------------------------
  30. //
  31. CClassContainer::CClassContainer()
  32. {
  33. m_fOpen = FALSE;
  34. m_ADsContainer = NULL;
  35. m_ADsClassContainer = NULL;
  36. m_ADsPackageContainer = NULL;
  37. m_ADsCategoryContainer = NULL;
  38. m_szCategoryName = NULL;
  39. m_szPackageName = NULL;
  40. m_szClassName = NULL;
  41. m_szPolicyName = NULL;
  42. memset (&m_PolicyId, 0, sizeof(GUID));
  43. m_uRefs = 1;
  44. }
  45. //---------------------------------------------------------------
  46. //
  47. // Function: Constructor
  48. //
  49. // Synopsis: Binds to the ClassStore given a class store path.
  50. //
  51. // Arguments:
  52. // [in]
  53. // szStoreName
  54. // Class Store Path without the leading ADCS:
  55. //
  56. // [out]
  57. // phr
  58. // Sucess code.
  59. //
  60. // Does an ADSI bind at the class store container and matches the
  61. // version numbers. if the version numbers match then it binds to the
  62. // class, package and category containers and keeps the bind handles.
  63. //----------------------------------------------------------------
  64. CClassContainer::CClassContainer(LPOLESTR szStoreName,
  65. HRESULT *phr)
  66. {
  67. DWORD dwStoreVersion = 0;
  68. LPOLESTR AttrNames[] = {STOREVERSION, POLICYDN, POLICYNAME};
  69. ADS_ATTR_INFO * pAttrsGot = NULL;
  70. DWORD cgot = 0, posn = 0;
  71. ADS_SEARCHPREF_INFO SearchPrefs[2];
  72. // set the search preference to one level search
  73. // and make the results come back in batches of size
  74. // 20 as default.
  75. SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  76. SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
  77. SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  78. SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  79. SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
  80. SearchPrefs[1].vValue.Integer = 20;
  81. // BUGBUG: This should be defined as a constant.
  82. // initialising.
  83. *phr = S_OK;
  84. m_fOpen = FALSE;
  85. m_ADsContainer = NULL;
  86. m_ADsClassContainer = NULL;
  87. m_ADsPackageContainer = NULL;
  88. m_ADsCategoryContainer = NULL;
  89. m_szCategoryName = NULL;
  90. m_szPackageName = NULL;
  91. m_szClassName = NULL;
  92. m_szPolicyName = NULL;
  93. memset (&m_PolicyId, 0, sizeof(GUID));
  94. // Bind to a Class Store Container Object
  95. // Cache the interface pointer
  96. //
  97. wcscpy (m_szContainerName, szStoreName);
  98. *phr = ADSIOpenDSObject(m_szContainerName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  99. &m_ADsContainer);
  100. ERROR_ON_FAILURE(*phr);
  101. //
  102. // Check the Schema Version of this container
  103. //
  104. *phr = ADSIGetObjectAttributes(m_ADsContainer, AttrNames, 3, &pAttrsGot, &cgot);
  105. if ((SUCCEEDED(*phr)) && (cgot))
  106. {
  107. posn = GetPropertyFromAttr(pAttrsGot, cgot, STOREVERSION);
  108. dwStoreVersion = 0;
  109. if (posn < cgot)
  110. {
  111. UnpackDWFrom(pAttrsGot[posn], &dwStoreVersion);
  112. }
  113. if ((!SUCCEEDED(*phr)) ||
  114. (dwStoreVersion != SCHEMA_VERSION_NUMBER))
  115. {
  116. *phr = CS_E_INVALID_VERSION;
  117. }
  118. if (SUCCEEDED(*phr))
  119. {
  120. LPOLESTR szPolicyPath = NULL, szPolicyName = NULL;
  121. posn = GetPropertyFromAttr(pAttrsGot, cgot, POLICYDN);
  122. if (posn < cgot)
  123. {
  124. LPOLESTR szParentPath = NULL, szPolicyGuid = NULL;
  125. UnpackStrFrom(pAttrsGot[posn], &szPolicyPath);
  126. //
  127. BuildADsParentPath(szPolicyPath, &szParentPath, &szPolicyGuid);
  128. if (szParentPath)
  129. FreeADsMem(szParentPath);
  130. if (szPolicyGuid)
  131. {
  132. if (wcslen(szPolicyGuid) == 41)
  133. {
  134. // valid GUID
  135. GUIDFromString(&szPolicyGuid[4], &m_PolicyId);
  136. }
  137. FreeADsMem(szPolicyGuid);
  138. }
  139. }
  140. posn = GetPropertyFromAttr(pAttrsGot, cgot, POLICYNAME);
  141. if (posn < cgot)
  142. {
  143. UnpackStrAllocFrom(pAttrsGot[posn], &m_szPolicyName);
  144. }
  145. }
  146. }
  147. else
  148. {
  149. *phr = CS_E_INVALID_VERSION;
  150. }
  151. if (pAttrsGot)
  152. FreeADsMem(pAttrsGot);
  153. ERROR_ON_FAILURE(*phr);
  154. //
  155. // Bind to the class container Object
  156. // Cache the interface pointer
  157. //
  158. // get the class container name.
  159. BuildADsPathFromParent(m_szContainerName, CLASSCONTAINERNAME, &m_szClassName);
  160. m_ADsClassContainer = NULL;
  161. // bind to the class container.
  162. *phr = ADSIOpenDSObject(m_szClassName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  163. &m_ADsClassContainer);
  164. ERROR_ON_FAILURE(*phr);
  165. // set the search preference on the handle.
  166. *phr = ADSISetSearchPreference(m_ADsClassContainer, SearchPrefs, 2);
  167. ERROR_ON_FAILURE(*phr);
  168. //
  169. // Bind to the Package container Object
  170. // Cache the interface pointer
  171. //
  172. // get the package container name.
  173. BuildADsPathFromParent(m_szContainerName, PACKAGECONTAINERNAME, &m_szPackageName);
  174. m_ADsPackageContainer = NULL;
  175. // bind to the package container.
  176. *phr = ADSIOpenDSObject(m_szPackageName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  177. &m_ADsPackageContainer);
  178. ERROR_ON_FAILURE(*phr);
  179. // set the search preference.
  180. *phr = ADSISetSearchPreference(m_ADsPackageContainer, SearchPrefs, 2);
  181. ERROR_ON_FAILURE(*phr);
  182. //
  183. // Bind to the category container Object
  184. // Cache the interface pointer
  185. //
  186. // get the category container name
  187. BuildADsPathFromParent(m_szContainerName, CATEGORYCONTAINERNAME, &m_szCategoryName);
  188. m_ADsCategoryContainer = NULL;
  189. // bind to the category container.
  190. *phr = ADSIOpenDSObject(m_szCategoryName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  191. &m_ADsCategoryContainer);
  192. ERROR_ON_FAILURE(*phr);
  193. // set the search preferences.
  194. *phr = ADSISetSearchPreference(m_ADsCategoryContainer, SearchPrefs, 2);
  195. ERROR_ON_FAILURE(*phr);
  196. m_fOpen = TRUE;
  197. m_uRefs = 1;
  198. Error_Cleanup:
  199. *phr = RemapErrorCode(*phr, m_szContainerName);
  200. return;
  201. }
  202. CClassContainer::~CClassContainer(void)
  203. {
  204. if (m_fOpen)
  205. {
  206. m_fOpen = FALSE;
  207. }
  208. if (m_ADsClassContainer)
  209. {
  210. ADSICloseDSObject(m_ADsClassContainer);
  211. m_ADsClassContainer = NULL;
  212. }
  213. // the bind might have failed while we succeeded in getting a path.
  214. if (m_szClassName)
  215. FreeADsMem(m_szClassName);
  216. if (m_ADsPackageContainer)
  217. {
  218. ADSICloseDSObject(m_ADsPackageContainer);
  219. m_ADsPackageContainer = NULL;
  220. }
  221. if (m_szPackageName)
  222. FreeADsMem(m_szPackageName);
  223. if (m_ADsCategoryContainer)
  224. {
  225. ADSICloseDSObject(m_ADsCategoryContainer);
  226. m_ADsCategoryContainer = NULL;
  227. }
  228. if (m_szCategoryName)
  229. FreeADsMem(m_szCategoryName);
  230. if (m_ADsContainer)
  231. {
  232. ADSICloseDSObject(m_ADsContainer);
  233. m_ADsContainer = NULL;
  234. }
  235. }
  236. // currently unused.
  237. BOOL InvalidDSName(LPWSTR pName)
  238. {
  239. if (wcslen(pName) >= 56)
  240. return TRUE;
  241. while (*pName)
  242. {
  243. if ((*pName == L':') ||
  244. (*pName == L',') ||
  245. (*pName == L';') ||
  246. (*pName == L'/') ||
  247. (*pName == L'<') ||
  248. (*pName == L'>') ||
  249. (*pName == L'\\')||
  250. (*pName == L'+'))
  251. return TRUE;
  252. ++pName;
  253. }
  254. return FALSE;
  255. }
  256. HRESULT CClassContainer::GetGPOInfo(GUID *pGPOId, LPOLESTR *pszPolicyName)
  257. {
  258. if ((!pGPOId) || (!IsValidPtrOut(pGPOId, sizeof(GUID))))
  259. return E_INVALIDARG;
  260. if ((!pszPolicyName) || (!IsValidPtrOut(pszPolicyName, sizeof(LPOLESTR))))
  261. return E_OUTOFMEMORY;
  262. memcpy(pGPOId, &m_PolicyId, sizeof(GUID));
  263. if (m_szPolicyName)
  264. {
  265. *pszPolicyName = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(1+wcslen(m_szPolicyName)));
  266. if (!(*pszPolicyName))
  267. return E_INVALIDARG;
  268. wcscpy(*pszPolicyName, m_szPolicyName);
  269. }
  270. else
  271. {
  272. *pszPolicyName = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*2);
  273. if (!(*pszPolicyName))
  274. return E_OUTOFMEMORY;
  275. (*pszPolicyName)[0] = L'\0';
  276. }
  277. return S_OK;
  278. }
  279. //
  280. // Removing a class from the database
  281. //
  282. //---------------------------------------------------------------
  283. //
  284. // Function: DeleteClass
  285. //
  286. // Synopsis: Internal function. Deletes the clsid from the ClassContainer.
  287. //
  288. // UsedBy RemovePackage
  289. //
  290. //
  291. // Arguments:
  292. // [in]
  293. // szClsid
  294. // Stringised Clsid
  295. //
  296. // Returns:
  297. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  298. //
  299. // Binds to the clsid object under the class container.
  300. // and decrements the reference count. If the reference
  301. // count goes to zero, then it deletes the clsid.
  302. // BUGBUG: If 2 objects try to delete it at the same
  303. // time this might not work properly.
  304. //----------------------------------------------------------------
  305. HRESULT CClassContainer::DeleteClass (LPOLESTR szClsid)
  306. {
  307. WCHAR szName[_MAX_PATH], *szFullName = NULL;
  308. HRESULT hr = S_OK;
  309. DWORD refcount = 0, cgot = 0, cAttr = 1, cModified = 0;
  310. HANDLE hADs = NULL;
  311. LPOLESTR AttrName = CLASSREFCOUNTER;
  312. ADS_ATTR_INFO * pAttr = NULL;
  313. ADS_ATTR_INFO Attr;
  314. if (!m_fOpen)
  315. return E_FAIL;
  316. // constructs the fullname from the clsid and class container Name.
  317. wsprintf(szName, L"CN=%s", szClsid);
  318. BuildADsPathFromParent(m_szClassName, szName, &szFullName);
  319. // binds to the class object.
  320. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  321. &hADs);
  322. if (szFullName)
  323. FreeADsMem(szFullName);
  324. ERROR_ON_FAILURE(hr);
  325. // gets the reference count attribute.
  326. hr = ADSIGetObjectAttributes(hADs, &AttrName, 1, &pAttr, &cgot);
  327. if ((SUCCEEDED(hr)) && (cgot))
  328. UnpackDWFrom(pAttr[0], (DWORD *)&refcount);
  329. if (pAttr)
  330. FreeADsMem(pAttr);
  331. if (refcount <= 1) {
  332. // Delete the object if the reference count is less than zero.
  333. hr = ADSIDeleteDSObject(m_ADsClassContainer, szName);
  334. if (hADs)
  335. ADSICloseDSObject(hADs);
  336. }
  337. else {
  338. // Decrement the reference count and store it back.
  339. refcount--;
  340. PackDWToAttr(&Attr, CLASSREFCOUNTER, refcount);
  341. hr = ADSISetObjectAttributes(hADs, &Attr, cAttr, &cModified);
  342. ADSICloseDSObject(hADs);
  343. FreeAttr(Attr);
  344. }
  345. Error_Cleanup:
  346. return RemapErrorCode(hr, m_szContainerName);
  347. }
  348. //---------------------------------------------------------------
  349. //
  350. // Function: EnumPackages
  351. //
  352. // Synopsis: Returns an Enumerator for all the packages that satisfies
  353. // the query.
  354. //
  355. // UsedBy Add/Remove Programs
  356. //
  357. // Arguments:
  358. // [in]
  359. // pszFileExt
  360. // FileExt that has to be queried on. ignored if NULL.
  361. // pCategory
  362. // Category that has to be queried on. ignored if NULL.
  363. // dwAppFlags
  364. // One of the APPINFO_XXX. ignored if it is APPINFO_ALL.
  365. // pdwLocale
  366. // Locale that has to be queried on. Ignored if NULL.
  367. // pPlatform
  368. // Platform that has to be queried on. Ignored if NULL.
  369. //
  370. // [out]
  371. // ppIEnumPackage
  372. // Enumerator is returned.
  373. // Returns:
  374. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  375. //
  376. // Validates the inputs, Creates a EnumPackage object, makes up the
  377. // search string made up of file extension, category.
  378. //----------------------------------------------------------------
  379. HRESULT CClassContainer::EnumPackages(
  380. LPOLESTR pszFileExt,
  381. GUID *pCategory,
  382. DWORD dwAppFlags,
  383. DWORD *pdwLocale,
  384. CSPLATFORM *pPlatform,
  385. IEnumPackage **ppIEnumPackage
  386. )
  387. {
  388. HRESULT hr = S_OK;
  389. CEnumPackage *pEnum = NULL;
  390. WCHAR szfilter[1000], szQry[1000];
  391. if (pszFileExt && IsBadStringPtr(pszFileExt, _MAX_PATH))
  392. return E_INVALIDARG;
  393. if (pCategory && !IsValidReadPtrIn(pCategory, sizeof(GUID)))
  394. return E_INVALIDARG;
  395. if (!IsValidPtrOut(ppIEnumPackage, sizeof(IEnumPackage *)))
  396. return E_INVALIDARG;
  397. *ppIEnumPackage = NULL;
  398. pEnum = new CEnumPackage(m_PolicyId, m_szPolicyName);
  399. if(NULL == pEnum)
  400. return E_OUTOFMEMORY;
  401. //
  402. // Create a CommandText
  403. //
  404. wsprintf(szfilter, L"(& (objectClass=%s) ", CLASS_CS_PACKAGE);
  405. if (pszFileExt)
  406. {
  407. wsprintf(szQry, L"(%s=%s*) ", PKGFILEEXTNLIST, pszFileExt);
  408. wcscat(szfilter, szQry);
  409. }
  410. if (pCategory)
  411. {
  412. STRINGGUID szCat;
  413. StringFromGUID (*pCategory, szCat);
  414. wsprintf(szQry, L"(%s=%s) ", PKGCATEGORYLIST, szCat);
  415. wcscat(szfilter, szQry);
  416. }
  417. wcscat(szfilter, L")");
  418. hr = pEnum->Initialize(m_szPackageName, szfilter,
  419. dwAppFlags, pPlatform);
  420. ERROR_ON_FAILURE(hr);
  421. hr = pEnum->QueryInterface(IID_IEnumPackage, (void**)ppIEnumPackage);
  422. ERROR_ON_FAILURE(hr);
  423. return S_OK;
  424. Error_Cleanup:
  425. if (pEnum)
  426. delete pEnum;
  427. *ppIEnumPackage = NULL;
  428. return RemapErrorCode(hr, m_szContainerName);
  429. }
  430. HRESULT CClassContainer::GetDNFromPackageName(LPOLESTR pszPackageName, LPOLESTR *szDN)
  431. {
  432. HRESULT hr = S_OK;
  433. WCHAR szfilter[_MAX_PATH];
  434. LPOLESTR AttrNames[] = {OBJECTCLASS, PACKAGEFLAGS, OBJECTDN};
  435. DWORD cAttr = 3;
  436. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  437. ADS_SEARCH_COLUMN column;
  438. DWORD dwFlags = 0;
  439. wsprintf(szfilter, L"%s=%s", PACKAGENAME, pszPackageName);
  440. hr = ADSIExecuteSearch(m_ADsPackageContainer, szfilter, AttrNames, cAttr, &hADsSearchHandle);
  441. RETURN_ON_FAILURE(hr);
  442. for (hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle);
  443. ((SUCCEEDED(hr)) && (hr != S_ADS_NOMORE_ROWS));
  444. hr = ADSIGetNextRow(m_ADsPackageContainer, hADsSearchHandle))
  445. {
  446. hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, PACKAGEFLAGS, &column);
  447. if (SUCCEEDED(hr))
  448. {
  449. UnpackDWFrom(column, &dwFlags);
  450. ADSIFreeColumn(m_ADsPackageContainer, &column);
  451. }
  452. else
  453. continue;
  454. if ((dwFlags & ACTFLG_Orphan) || (dwFlags & ACTFLG_Uninstall))
  455. continue;
  456. hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, OBJECTDN, &column);
  457. if (SUCCEEDED(hr))
  458. {
  459. UnpackStrAllocFrom(column, szDN);
  460. ADSIFreeColumn(m_ADsPackageContainer, &column);
  461. }
  462. else
  463. continue;
  464. break;
  465. }
  466. if (hADsSearchHandle)
  467. ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
  468. return hr;
  469. }
  470. // Gets the RDN of a package given the package Guid.
  471. HRESULT CClassContainer::BuildDNFromPackageGuid(GUID PackageGuid, LPOLESTR *szDN)
  472. {
  473. HRESULT hr = S_OK;
  474. LPOLESTR AttrName = {OBJECTDN};
  475. WCHAR szfilter[_MAX_PATH];
  476. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  477. ADS_SEARCH_COLUMN column;
  478. LPWSTR EncodedGuid = NULL;
  479. hr = ADsEncodeBinaryData((PBYTE)&PackageGuid, sizeof(GUID), &EncodedGuid);
  480. wsprintf(szfilter, L"(%s=%s)", OBJECTGUID, EncodedGuid);
  481. FreeADsMem(EncodedGuid);
  482. hr = ADSIExecuteSearch(m_ADsPackageContainer, szfilter, &AttrName, 1, &hADsSearchHandle);
  483. RETURN_ON_FAILURE(hr);
  484. hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle);
  485. if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
  486. {
  487. ERROR_ON_FAILURE(hr = CS_E_PACKAGE_NOTFOUND);
  488. }
  489. hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, AttrName, &column);
  490. ERROR_ON_FAILURE(hr);
  491. if (SUCCEEDED(hr))
  492. {
  493. UnpackStrAllocFrom(column, szDN);
  494. }
  495. ADSIFreeColumn(m_ADsPackageContainer, &column);
  496. Error_Cleanup:
  497. if (hADsSearchHandle)
  498. ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
  499. return hr;
  500. }
  501. HRESULT CClassContainer::GetPackageGuid(WCHAR *szRDN, GUID *pPackageGuid)
  502. {
  503. HRESULT hr = S_OK;
  504. LPOLESTR AttrName = {OBJECTGUID};
  505. WCHAR szfilter[_MAX_PATH];
  506. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  507. ADS_SEARCH_COLUMN column;
  508. hr = ADSIExecuteSearch(m_ADsPackageContainer, szRDN, &AttrName, 1, &hADsSearchHandle);
  509. RETURN_ON_FAILURE(hr);
  510. hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle);
  511. if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
  512. {
  513. ERROR_ON_FAILURE(hr = CS_E_PACKAGE_NOTFOUND);
  514. }
  515. hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, AttrName, &column);
  516. ERROR_ON_FAILURE(hr);
  517. if (SUCCEEDED(hr))
  518. UnpackGUIDFrom(column, pPackageGuid);
  519. ADSIFreeColumn(m_ADsPackageContainer, &column);
  520. Error_Cleanup:
  521. if (hADsSearchHandle)
  522. ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
  523. return hr;
  524. }
  525. //---------------------------------------------------------------
  526. //
  527. // Function: GetPackageDetails
  528. //
  529. // Synopsis: Returns the PackageDetail corresponding to the PackageName.
  530. //
  531. // Arguments:
  532. // [in]
  533. // pszPackageId
  534. // Id of the Package.
  535. // [out]
  536. // pPackageDetail
  537. // PackageDetail info that is returned.
  538. // Returns:
  539. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  540. //
  541. // Binds to the Package object and calls GetPackageDetail with it.
  542. //----------------------------------------------------------------
  543. HRESULT CClassContainer::GetPackageDetails (
  544. LPOLESTR pszPackageName,
  545. PACKAGEDETAIL * pPackageDetail
  546. )
  547. {
  548. HRESULT hr = S_OK;
  549. HANDLE hADs = NULL;
  550. WCHAR * szFullName = NULL;
  551. ADS_ATTR_INFO * pAttr = NULL;
  552. DWORD cgot = 0;
  553. // this can be made into a search based API. Not required for the time being.
  554. // Should change it if perf is a big issue.
  555. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  556. return E_INVALIDARG;
  557. hr = GetDNFromPackageName(pszPackageName, &szFullName);
  558. ERROR_ON_FAILURE(hr);
  559. if (hr != S_OK)
  560. return CS_E_OBJECT_NOTFOUND;
  561. // binding to the package object.
  562. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &hADs);
  563. ERROR_ON_FAILURE(hr);
  564. // calling GetPackageDetail.
  565. hr = GetPackageDetail (hADs, m_szClassName, pPackageDetail);
  566. ADSICloseDSObject(hADs);
  567. if (pAttr)
  568. FreeADsMem(pAttr);
  569. if (szFullName)
  570. CoTaskMemFree(szFullName);
  571. Error_Cleanup:
  572. return RemapErrorCode(hr, m_szContainerName);
  573. }
  574. //---------------------------------------------------------------
  575. //
  576. // Function: GetPackageDetails
  577. //
  578. // Synopsis: Returns the PackageDetail corresponding to the PackageName.
  579. //
  580. // Arguments:
  581. // [in]
  582. // pszPackageId
  583. // Id of the Package.
  584. // [out]
  585. // pPackageDetail
  586. // PackageDetail info that is returned.
  587. // Returns:
  588. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  589. //
  590. // Binds to the Package object and calls GetPackageDetail with it.
  591. //----------------------------------------------------------------
  592. HRESULT CClassContainer::GetPackageDetailsFromGuid (
  593. GUID PkgGuid,
  594. PACKAGEDETAIL *pPackageDetail
  595. )
  596. {
  597. HRESULT hr = S_OK;
  598. HANDLE hADs = NULL;
  599. WCHAR * szFullName = NULL, szRDN[_MAX_PATH];
  600. ADS_ATTR_INFO * pAttr = NULL;
  601. DWORD cgot = 0;
  602. // this can be made into a search based API. Not required for the time being.
  603. // Should change it if perf is a big issue.
  604. if (IsNullGuid(PkgGuid))
  605. return E_INVALIDARG;
  606. BuildDNFromPackageGuid(PkgGuid, &szFullName);
  607. ERROR_ON_FAILURE(hr);
  608. if (hr != S_OK)
  609. return CS_E_OBJECT_NOTFOUND;
  610. // binding to the package object.
  611. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION, &hADs);
  612. ERROR_ON_FAILURE(hr);
  613. // calling GetPackageDetail.
  614. hr = GetPackageDetail (hADs, m_szClassName, pPackageDetail);
  615. ADSICloseDSObject(hADs);
  616. if (pAttr)
  617. FreeADsMem(pAttr);
  618. if (szFullName)
  619. CoTaskMemFree(szFullName);
  620. Error_Cleanup:
  621. return RemapErrorCode(hr, m_szContainerName);
  622. }
  623. #define FREEARR(ARR, SZ) { \
  624. DWORD curIndex; \
  625. for (curIndex = 0; curIndex < (SZ); curIndex++) \
  626. CoTaskMemFree((ARR)[curIndex]); \
  627. CoTaskMemFree(ARR); \
  628. ARR = NULL; \
  629. } \
  630. //---------------------------------------------------------------
  631. //
  632. // Function: ChangePackageUpgradeInfoIncremental
  633. //
  634. // Synopsis: Mark the package as upgraded by another package
  635. //
  636. // Arguments:
  637. // [in]
  638. // PackageGuid
  639. // Package Guid to identify the package.
  640. // szUpgradedByClassStore
  641. // Class Store where the package that upgrades exists
  642. // UpgradedByPackageGuid
  643. // The Guid of the package that upgrades
  644. // Add Add or remove the upgradedByrelation
  645. //
  646. // Returns:
  647. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  648. // Otherwise it packs all the required attributes in the ATTR_INFO
  649. // structure and sends it to the Directory.
  650. //----------------------------------------------------------------
  651. HRESULT CClassContainer::ChangePackageUpgradeInfoIncremental(
  652. GUID PackageGuid,
  653. UPGRADEINFO UpgradeInfo,
  654. DWORD OpFlags
  655. )
  656. {
  657. HRESULT hr = S_OK;
  658. HANDLE hADs = NULL;
  659. WCHAR *szFullName=NULL, szGuid[_MAX_PATH], szUsn[20];
  660. LPOLESTR pProp = NULL;
  661. ADS_ATTR_INFO pAttr[2];
  662. DWORD cAttr = 0, cModified = 0, i=0;
  663. UINT len=0;
  664. hr = BuildDNFromPackageGuid(PackageGuid, &szFullName);
  665. ERROR_ON_FAILURE(hr);
  666. // Bind to the Package Object.
  667. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs);
  668. ERROR_ON_FAILURE(hr);
  669. StringFromGUID(UpgradeInfo.PackageGuid, szGuid);
  670. len = wcslen(UpgradeInfo.szClassStore);
  671. pProp = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *(36+PKG_UPG_DELIM1_LEN+len+PKG_UPG_DELIM2_LEN+2+2+1));
  672. // Guid size+::+length++:+flagDigit+2
  673. wsprintf(pProp, L"%s%s%s%s%02x", UpgradeInfo.szClassStore, PKG_UPG_DELIMITER1, szGuid, PKG_UPG_DELIMITER2, UpgradeInfo.Flag%16);
  674. PackStrArrToAttrEx(pAttr+cAttr, UPGRADESPACKAGES, &pProp, 1, OpFlags?TRUE:FALSE);
  675. cAttr++;
  676. //
  677. // Update the TimeStamp
  678. //
  679. GetCurrentUsn(szUsn);
  680. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  681. cAttr++;
  682. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  683. if (hADs)
  684. ADSICloseDSObject(hADs);
  685. // ignore it if the property already exists.
  686. if (hr == HRESULT_FROM_WIN32(ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS))
  687. hr = S_OK;
  688. for (i = 0; i < cAttr; i++)
  689. FreeAttr(pAttr[i]);
  690. Error_Cleanup:
  691. if (szFullName)
  692. CoTaskMemFree(szFullName);
  693. return RemapErrorCode(hr, m_szContainerName);
  694. }
  695. //---------------------------------------------------------------
  696. //
  697. // Function: ChangePackageProperties
  698. //
  699. // Synopsis: Change Various (most commonly changed) properties
  700. // for a given package.
  701. //
  702. // Arguments:
  703. // [in]
  704. // PackageId
  705. // Package Id to identify the package.
  706. // pszNewname
  707. // new Name for the Package. If it is being renamed
  708. // all other changes should be NULL.
  709. // pdwFlags
  710. // The Deployment Flags. Should be ACTFLG_XXX
  711. // Ignored if NULL.
  712. // pszUrl
  713. // Help Url for the Package. Ignored if NULL.
  714. // pszScriptPath
  715. // Script Path for the Package. Ignored if NULL.
  716. // pInstallUiLevel
  717. // The InstallationUiLevel. Ignored if NULL.
  718. // pdwRevision
  719. // REVISION. Ignored if NULL.
  720. //
  721. // Returns:
  722. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  723. // Otherwise it packs all the required attributes in the ATTR_INFO
  724. // structure and sends it to the Directory.
  725. //----------------------------------------------------------------
  726. HRESULT CClassContainer::ChangePackageProperties(
  727. LPOLESTR pszPackageName,
  728. LPOLESTR pszNewName,
  729. DWORD *pdwFlags,
  730. LPOLESTR pszUrl,
  731. LPOLESTR pszScriptPath,
  732. UINT *pInstallUiLevel,
  733. DWORD *pdwRevision
  734. )
  735. {
  736. HRESULT hr = S_OK;
  737. HANDLE hADs = NULL;
  738. WCHAR *szRDN=NULL, *szFullName=NULL;
  739. WCHAR szUsn[20];
  740. ADS_ATTR_INFO pAttr[7];
  741. DWORD cAttr = 0, cModified = 0, i=0;
  742. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  743. return E_INVALIDARG;
  744. hr = GetDNFromPackageName(pszPackageName, &szFullName);
  745. ERROR_ON_FAILURE(hr);
  746. if (hr != S_OK)
  747. return CS_E_OBJECT_NOTFOUND;
  748. // if no properties have to be changed.
  749. if (!(pszScriptPath || pszUrl || pdwFlags || pInstallUiLevel || pdwRevision || pszNewName))
  750. return E_INVALIDARG;
  751. if (pszNewName)
  752. {
  753. // rename package
  754. WCHAR szNewRDN[_MAX_PATH];
  755. BOOL GenerateGuid = FALSE;
  756. GUID PackageGuidId;
  757. WCHAR pszPackageNewId[_MAX_PATH], *szJunk = NULL;
  758. if (IsBadStringPtr(pszNewName, _MAX_PATH))
  759. return E_INVALIDARG;
  760. if (pszScriptPath || pszUrl || pdwFlags || pInstallUiLevel || pdwRevision)
  761. return E_INVALIDARG;
  762. // see whether the new name is valid.
  763. // GenerateGuid = InvalidDSName(pszNewName);
  764. // see whether the newName already exists. Notice that if the same package name is
  765. // entered it will return error.
  766. hr = GetDNFromPackageName(pszNewName, &szJunk);
  767. if (szJunk)
  768. CoTaskMemFree(szJunk);
  769. szJunk = NULL;
  770. ERROR_ON_FAILURE(hr);
  771. if (hr == S_OK)
  772. return CS_E_OBJECT_ALREADY_EXISTS;
  773. /*
  774. packages are going to have a guid as a name and nothing else.
  775. // generate guid if required.
  776. if (GenerateGuid)
  777. {
  778. CoCreateGuid(&PackageGuidId);
  779. StringFromGUID(PackageGuidId, pszPackageNewId);
  780. }
  781. else
  782. wcscpy(pszPackageNewId, pszNewName);
  783. // generate the new RDN
  784. wsprintf(szNewRDN, L"CN=%s", pszPackageNewId);
  785. BuildADsParentPath(szFullName, &szJunk, &szRDN);
  786. if (szJunk)
  787. FreeADsMem(szJunk);
  788. hr = ADSIModifyRdn(m_ADsPackageContainer, szRDN, szNewRDN);
  789. if (szRDN)
  790. FreeADsMem(szRDN);
  791. ERROR_ON_FAILURE(hr);
  792. if (szFullName)
  793. CoTaskMemFree(szFullName);
  794. szFullName = NULL;
  795. // construct the Full Path for the Package.
  796. BuildADsPathFromParent(m_szPackageName, szNewRDN, &szFullName);
  797. */
  798. // Bind to the Package Object.
  799. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  800. &hADs);
  801. if (szFullName)
  802. FreeADsMem(szFullName);
  803. szFullName = NULL;
  804. ERROR_ON_FAILURE(hr);
  805. }
  806. else
  807. {
  808. // Bind to the Package Object.
  809. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  810. &hADs);
  811. ERROR_ON_FAILURE(hr);
  812. if (szFullName)
  813. CoTaskMemFree(szFullName);
  814. szFullName = NULL;
  815. }
  816. // Just change some properties.
  817. //
  818. // Update the TimeStamp
  819. //
  820. GetCurrentUsn(szUsn);
  821. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  822. cAttr++;
  823. //
  824. // Change Package Flags
  825. //
  826. if (pdwFlags)
  827. {
  828. PackDWToAttr (pAttr+cAttr, PACKAGEFLAGS, *pdwFlags);
  829. cAttr++;
  830. }
  831. //
  832. // Change Package Script
  833. //
  834. if (pszScriptPath)
  835. {
  836. PackStrToAttr(pAttr+cAttr, SCRIPTPATH, pszScriptPath);
  837. cAttr++;
  838. }
  839. //
  840. // Change Package Help URL
  841. //
  842. if (pszUrl)
  843. {
  844. PackStrToAttr(pAttr+cAttr, HELPURL, pszUrl);
  845. cAttr++;
  846. }
  847. //
  848. // Change Package UI Level.
  849. //
  850. if (pInstallUiLevel)
  851. {
  852. PackDWToAttr (pAttr+cAttr, UILEVEL, *pInstallUiLevel);
  853. cAttr++;
  854. }
  855. //
  856. // Change Revision.
  857. //
  858. if (pdwRevision)
  859. {
  860. PackDWToAttr (pAttr+cAttr, REVISION, *pdwRevision);
  861. cAttr++;
  862. }
  863. if (pszNewName)
  864. {
  865. PackStrToAttr(pAttr+cAttr, PACKAGENAME, pszNewName);
  866. cAttr++;
  867. }
  868. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  869. if (hADs)
  870. ADSICloseDSObject(hADs);
  871. for (i = 0; i < cAttr; i++)
  872. FreeAttr(pAttr[i]);
  873. if (SUCCEEDED(hr))
  874. {
  875. //
  876. // Update Class Store Usn
  877. //
  878. UpdateStoreUsn(m_ADsContainer, szUsn);
  879. }
  880. Error_Cleanup:
  881. if (szFullName)
  882. CoTaskMemFree(szFullName);
  883. return RemapErrorCode(hr, m_szContainerName);
  884. }
  885. //---------------------------------------------------------------
  886. // Function: ChangePackageCategories
  887. //
  888. // Synopsis: Change (Not Add) the Categories that a package
  889. // belongs to.
  890. //
  891. // Arguments:
  892. // [in]
  893. // pszPackageName
  894. // Package Name to identify the package.
  895. // cCategories
  896. // Number of Categories.
  897. // rpCategory
  898. // Array of categories.
  899. //
  900. // Returns:
  901. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  902. // Binds to the Package Object, Converts all the categories to strings
  903. // Packs it and sends it to the DS.
  904. //----------------------------------------------------------------
  905. HRESULT CClassContainer::ChangePackageCategories(
  906. LPOLESTR pszPackageName,
  907. UINT cCategories,
  908. GUID *rpCategory
  909. )
  910. {
  911. //
  912. // Does not change USN
  913. //
  914. HRESULT hr = S_OK;
  915. HANDLE hADs = NULL;
  916. WCHAR *szFullName = NULL;
  917. LPOLESTR *pszGuid = NULL;
  918. UINT count;
  919. ADS_ATTR_INFO pAttr[1];
  920. DWORD cAttr = 0, cModified = 0, i=0;
  921. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  922. return E_INVALIDARG;
  923. if ((cCategories) && ((!rpCategory) ||
  924. (!IsValidReadPtrIn(rpCategory, sizeof(GUID) * cCategories))))
  925. return E_INVALIDARG;
  926. // Construct the Name of the Package Object.
  927. GetDNFromPackageName(pszPackageName, &szFullName);
  928. ERROR_ON_FAILURE(hr);
  929. if (hr != S_OK)
  930. return CS_E_OBJECT_NOTFOUND;
  931. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  932. &hADs);
  933. ERROR_ON_FAILURE(hr);
  934. // fill in the categories
  935. pszGuid = (LPOLESTR *)CoTaskMemAlloc(cCategories * sizeof(LPOLESTR));
  936. if (!pszGuid)
  937. {
  938. hr = E_OUTOFMEMORY;
  939. ERROR_ON_FAILURE(hr);
  940. }
  941. // convert the GUIDs to Strings.
  942. for (count = 0; (count < cCategories); count++)
  943. {
  944. pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
  945. if (!(pszGuid[count]))
  946. {
  947. FREEARR(pszGuid, count);
  948. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  949. }
  950. StringFromGUID(rpCategory[count], pszGuid[count]);
  951. }
  952. // Pack it into Attribute Structure.
  953. PackStrArrToAttr(pAttr+cAttr, PKGCATEGORYLIST, pszGuid, cCategories);
  954. cAttr++;
  955. // Set the Attribute
  956. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  957. Error_Cleanup:
  958. if (hADs)
  959. ADSICloseDSObject(hADs);
  960. if (pszGuid)
  961. for (count = 0; (count < cCategories); count++)
  962. CoTaskMemFree(pszGuid[count]);
  963. CoTaskMemFree(pszGuid);
  964. if (szFullName)
  965. CoTaskMemFree(szFullName);
  966. for (i = 0; i < cAttr; i++)
  967. FreeAttr(pAttr[i]);
  968. return RemapErrorCode(hr, m_szContainerName);
  969. }
  970. //---------------------------------------------------------------
  971. // Function: SetPriorityByFileExt
  972. //
  973. // Synopsis: Changes the priority of a Package corresp. to
  974. // a file Extension.
  975. //
  976. // Arguments:
  977. // [in]
  978. // pszPackageName
  979. // Package Name to identify the package.
  980. // pszFileExt
  981. // File Extension for which the priority has to be changed.
  982. // Priority
  983. // Priority for the Package.
  984. //
  985. // Returns:
  986. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  987. // Binds to the Package Object, Gets the file Extensions and changes
  988. // the priority corresponding to the File Extension.
  989. //----------------------------------------------------------------
  990. HRESULT CClassContainer::SetPriorityByFileExt(
  991. LPOLESTR pszPackageName,
  992. LPOLESTR pszFileExt,
  993. UINT Priority
  994. )
  995. {
  996. HRESULT hr = S_OK;
  997. HANDLE hADs = NULL;
  998. WCHAR *szFullName=NULL;
  999. LPOLESTR *prgFileExt = NULL;
  1000. WCHAR szUsn[20];
  1001. ADS_ATTR_INFO pAttr[4], *pAttrGot = NULL;
  1002. DWORD cAttr = 0, cAttrGot = 0, cModified = 0, cShellFileExt = 0, i=0;
  1003. LPOLESTR pAttrNames[] = {PKGFILEEXTNLIST};
  1004. // Construct the Package Name
  1005. GetDNFromPackageName(pszPackageName, &szFullName);
  1006. ERROR_ON_FAILURE(hr);
  1007. if (hr != S_OK)
  1008. return CS_E_OBJECT_NOTFOUND;
  1009. // Bind to the Package Object.
  1010. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  1011. &hADs);
  1012. ERROR_ON_FAILURE(hr);
  1013. //
  1014. // Update the TimeStamp
  1015. //
  1016. GetCurrentUsn(szUsn);
  1017. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  1018. cAttr++;
  1019. // get the file extensions.
  1020. hr = ADSIGetObjectAttributes(hADs, pAttrNames, 1, &pAttrGot, &cAttrGot);
  1021. if ((SUCCEEDED(hr)) && (cAttrGot))
  1022. UnpackStrArrFrom(pAttrGot[0], &prgFileExt, &cShellFileExt);
  1023. // Look for the given file extension.
  1024. for (i=0; i < cShellFileExt; ++i)
  1025. {
  1026. if (wcsncmp(prgFileExt[i], pszFileExt, wcslen(pszFileExt)) == 0)
  1027. {
  1028. // if the file extension is found, change the corresponding priority.
  1029. if (wcslen(prgFileExt[i]) != (wcslen(pszFileExt)+3))
  1030. continue;
  1031. wsprintf(prgFileExt[i], L"%s:%2d", pszFileExt, Priority%100);
  1032. break;
  1033. }
  1034. }
  1035. if (i == cShellFileExt)
  1036. {
  1037. ERROR_ON_FAILURE(hr = CS_E_OBJECT_NOTFOUND);
  1038. }
  1039. if (cShellFileExt)
  1040. {
  1041. PackStrArrToAttr(pAttr+cAttr, PKGFILEEXTNLIST, prgFileExt, cShellFileExt);
  1042. cAttr++;
  1043. }
  1044. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1045. if (SUCCEEDED(hr))
  1046. {
  1047. //
  1048. // Update Store Usn
  1049. //
  1050. UpdateStoreUsn(m_ADsContainer, szUsn);
  1051. }
  1052. Error_Cleanup:
  1053. CoTaskMemFree(prgFileExt);
  1054. if (szFullName)
  1055. CoTaskMemFree(szFullName);
  1056. for (i = 0; i < cAttr; i++)
  1057. FreeAttr(pAttr[i]);
  1058. if (pAttrGot)
  1059. FreeADsMem(pAttrGot);
  1060. ADSICloseDSObject(hADs);
  1061. return RemapErrorCode(hr, m_szContainerName);
  1062. }
  1063. //---------------------------------------------------------------
  1064. // Function: ChangePackageSourceList
  1065. //
  1066. // Synopsis: Changes the priority of a Package corresp. to
  1067. // a file Extension.
  1068. //
  1069. // Arguments:
  1070. // [in]
  1071. // pszPackageName
  1072. // Package Name to identify the package.
  1073. // cSources
  1074. // Number of sources
  1075. // pszSourceList
  1076. // List of sources
  1077. //
  1078. // Returns:
  1079. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  1080. // Binds to the Package Object, Makes the new sourcelist with the order
  1081. // maintained.
  1082. //----------------------------------------------------------------
  1083. HRESULT CClassContainer::ChangePackageSourceList(
  1084. LPOLESTR pszPackageName,
  1085. UINT cSources,
  1086. LPOLESTR *pszSourceList
  1087. )
  1088. {
  1089. HRESULT hr = S_OK;
  1090. HANDLE hADs = NULL;
  1091. WCHAR *szFullName = NULL;
  1092. UINT count;
  1093. WCHAR szUsn[20];
  1094. LPOLESTR *pszPrioritySourceList = NULL;
  1095. ADS_ATTR_INFO pAttr[2];
  1096. DWORD cAttr = 0, cModified = 0, i=0;
  1097. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  1098. return E_INVALIDARG;
  1099. if ((!pszSourceList) ||
  1100. (!IsValidReadPtrIn(pszSourceList, sizeof(LPOLESTR) * cSources)))
  1101. return E_INVALIDARG;
  1102. for (count = 0; (count < cSources); count++)
  1103. if ((!pszSourceList[count]) || (IsBadStringPtr(pszSourceList[count], _MAX_PATH)))
  1104. return E_INVALIDARG;
  1105. // Construct the Name of the Package Object.
  1106. GetDNFromPackageName(pszPackageName, &szFullName);
  1107. ERROR_ON_FAILURE(hr);
  1108. if (hr != S_OK)
  1109. return CS_E_OBJECT_NOTFOUND;
  1110. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  1111. &hADs);
  1112. ERROR_ON_FAILURE(hr);
  1113. // Local variable for adding the order to the list.
  1114. pszPrioritySourceList = (LPOLESTR *)CoTaskMemAlloc(cSources * sizeof(LPOLESTR));
  1115. if (!pszPrioritySourceList)
  1116. {
  1117. hr = E_OUTOFMEMORY;
  1118. ERROR_ON_FAILURE(hr);
  1119. }
  1120. // add the order to the list
  1121. for (count = 0; (count < cSources); count++)
  1122. {
  1123. pszPrioritySourceList[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(wcslen(pszSourceList[count])+
  1124. 1+1+1+NumDigits10(cSources)));
  1125. if (!(pszPrioritySourceList[count]))
  1126. {
  1127. FREEARR(pszPrioritySourceList, count);
  1128. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1129. }
  1130. wsprintf(pszPrioritySourceList[count], L"%d:%s", count, pszSourceList[count]);
  1131. }
  1132. //
  1133. // Update the TimeStamp
  1134. //
  1135. GetCurrentUsn(szUsn);
  1136. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  1137. cAttr++;
  1138. // Pack it into Attribute Structure.
  1139. PackStrArrToAttr(pAttr+cAttr, MSIFILELIST, pszPrioritySourceList, cSources);
  1140. cAttr++;
  1141. // Set the Attribute
  1142. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1143. if (SUCCEEDED(hr))
  1144. {
  1145. //
  1146. // Update Store Usn
  1147. //
  1148. UpdateStoreUsn(m_ADsContainer, szUsn);
  1149. }
  1150. Error_Cleanup:
  1151. if (hADs)
  1152. ADSICloseDSObject(hADs);
  1153. for (i = 0; i < cAttr; i++)
  1154. FreeAttr(pAttr[i]);
  1155. if (szFullName)
  1156. CoTaskMemFree(szFullName);
  1157. return RemapErrorCode(hr, m_szContainerName);
  1158. }
  1159. //---------------------------------------------------------------
  1160. // Function: ChangePackageUpgradeList
  1161. //
  1162. // Synopsis: Changes the priority of a Package corresp. to
  1163. // a file Extension.
  1164. //
  1165. // Arguments:
  1166. // [in]
  1167. // pszPackageName
  1168. // Package Name to identify the package.
  1169. // cSources
  1170. // Number of sources
  1171. // pszSourceList
  1172. // List of sources
  1173. //
  1174. // Returns:
  1175. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  1176. // Binds to the Package Object, Makes the new sourcelist with the order
  1177. // maintained.
  1178. //----------------------------------------------------------------
  1179. HRESULT CClassContainer::ChangePackageUpgradeList(
  1180. LPOLESTR pszPackageName,
  1181. UINT cUpgrades,
  1182. UPGRADEINFO *prgUpgradeInfoList
  1183. )
  1184. {
  1185. HRESULT hr = S_OK;
  1186. HANDLE hADs = NULL;
  1187. WCHAR *szFullName = NULL;
  1188. UINT count = 0, count1 = 0, count2 = 0;
  1189. LPOLESTR *pProp = NULL, pAttrNames[2] = {UPGRADESPACKAGES, OBJECTGUID}, *rpszUpgrades = NULL;
  1190. ADS_ATTR_INFO pAttr[2], *pAttrGot = NULL;
  1191. DWORD cAttr = 0, cModified = 0, i=0, posn = 0, cUpgradeInfoStored = 0,
  1192. cAddList = 0, cRemoveList = 0, cgot = 0;
  1193. GUID PkgGuid;
  1194. WCHAR szUsn[20];
  1195. UPGRADEINFO *pUpgradeInfoStored = NULL, *pAddList = NULL, *pRemoveList = NULL;
  1196. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  1197. return E_INVALIDARG;
  1198. if ((cUpgrades) && ((!prgUpgradeInfoList) ||
  1199. (!IsValidReadPtrIn(prgUpgradeInfoList, sizeof(UPGRADEINFO) * cUpgrades))))
  1200. return E_INVALIDARG;
  1201. for (count = 0; (count < cUpgrades); count++)
  1202. {
  1203. if ((!(prgUpgradeInfoList[count].szClassStore)) ||
  1204. IsBadStringPtr((prgUpgradeInfoList[count].szClassStore), _MAX_PATH))
  1205. return E_INVALIDARG;
  1206. if (IsNullGuid(prgUpgradeInfoList[count].PackageGuid))
  1207. return E_INVALIDARG;
  1208. if (((prgUpgradeInfoList[count].Flag & UPGFLG_Uninstall) == 0) &&
  1209. ((prgUpgradeInfoList[count].Flag & UPGFLG_NoUninstall) == 0) &&
  1210. ((prgUpgradeInfoList[count].Flag & UPGFLG_UpgradedBy) == 0))
  1211. return E_INVALIDARG;
  1212. }
  1213. // Construct the Name of the Package Object.
  1214. hr = GetDNFromPackageName(pszPackageName, &szFullName);
  1215. ERROR_ON_FAILURE(hr);
  1216. if (hr != S_OK)
  1217. return CS_E_OBJECT_NOTFOUND;
  1218. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  1219. &hADs);
  1220. ERROR_ON_FAILURE(hr);
  1221. // get the guid and upgrade info
  1222. hr = ADSIGetObjectAttributes(hADs, pAttrNames, 2, &pAttrGot, &cgot);
  1223. // Package guid
  1224. posn = GetPropertyFromAttr(pAttrGot, cgot, OBJECTGUID);
  1225. if (posn < cgot)
  1226. UnpackGUIDFrom(pAttrGot[posn], &PkgGuid);
  1227. // Upgrade package
  1228. posn = GetPropertyFromAttr(pAttrGot, cgot, UPGRADESPACKAGES);
  1229. if (posn < cgot)
  1230. UnpackStrArrFrom(pAttrGot[posn], &pProp, &cUpgradeInfoStored);
  1231. // allocating the lists
  1232. pUpgradeInfoStored = (UPGRADEINFO *)CoTaskMemAlloc(sizeof(UPGRADEINFO)*(cUpgradeInfoStored));
  1233. pAddList = (UPGRADEINFO *)CoTaskMemAlloc(sizeof(UPGRADEINFO)*(cUpgrades+cUpgradeInfoStored));
  1234. pRemoveList = (UPGRADEINFO *)CoTaskMemAlloc(sizeof(UPGRADEINFO)*(cUpgrades+cUpgradeInfoStored));
  1235. if ((!pUpgradeInfoStored) || (!pAddList) || (!pRemoveList))
  1236. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  1237. // convert the strings to upgradinfo structures.
  1238. for (count = 0; count < (cUpgradeInfoStored); count++)
  1239. {
  1240. WCHAR *pStr = NULL;
  1241. LPOLESTR ptr = pProp[count];
  1242. UINT len = wcslen (ptr);
  1243. pUpgradeInfoStored[count].szClassStore = pProp[count];
  1244. if (len <= 41)
  1245. continue;
  1246. *(ptr + len - 3) = NULL;
  1247. pUpgradeInfoStored[count].Flag = wcstoul(ptr+(len-2), &pStr, 16);
  1248. *(ptr + len - 3 - 36 - 2) = L'\0';
  1249. /* -GUID-'::'*/
  1250. GUIDFromString(ptr+len-3-36, &(pUpgradeInfoStored[count].PackageGuid));
  1251. }
  1252. cUpgradeInfoStored = count; // we might have skipped some.
  1253. // AddList formed.
  1254. for (count = 0; count < cUpgrades; count++)
  1255. {
  1256. for (count1 = 0; count1 < cUpgradeInfoStored; count1++)
  1257. {
  1258. // ignore flag changes
  1259. if ((wcscmp(pUpgradeInfoStored[count1].szClassStore, prgUpgradeInfoList[count].szClassStore) == 0) &&
  1260. (memcmp(&pUpgradeInfoStored[count1].PackageGuid, &prgUpgradeInfoList[count].PackageGuid, sizeof(GUID)) == 0))
  1261. break;
  1262. }
  1263. if (count1 == cUpgradeInfoStored)
  1264. pAddList[cAddList++] = prgUpgradeInfoList[count];
  1265. }
  1266. // remove list formed.
  1267. for (count1 = 0; count1 < cUpgradeInfoStored; count1++)
  1268. {
  1269. for (count = 0; count < cUpgrades; count++)
  1270. {
  1271. // ignore flag changes
  1272. if ((wcscmp(pUpgradeInfoStored[count1].szClassStore, prgUpgradeInfoList[count].szClassStore) == 0) &&
  1273. (memcmp(&pUpgradeInfoStored[count1].PackageGuid, &prgUpgradeInfoList[count].PackageGuid, sizeof(GUID)) == 0))
  1274. break;
  1275. }
  1276. if (count == cUpgrades)
  1277. pRemoveList[cRemoveList++] = pUpgradeInfoStored[count];
  1278. }
  1279. for (count = 0; count < cAddList; count++)
  1280. {
  1281. // in case of UpgradedBy do no try to fix up the links.
  1282. if (!(pAddList[count].Flag & UPGFLG_UpgradedBy))
  1283. {
  1284. DWORD Flags = 0;
  1285. if (pAddList[count].Flag & UPGFLG_Enforced)
  1286. Flags = UPGFLG_Enforced;
  1287. }
  1288. }
  1289. for (count = 0; count < cRemoveList; count++)
  1290. {
  1291. // in case of UpgradedBy do no try to fix up the links.
  1292. if (!(pRemoveList[count].Flag & UPGFLG_UpgradedBy))
  1293. {
  1294. DWORD Flags = 0;
  1295. if (pRemoveList[count].Flag & UPGFLG_Enforced)
  1296. Flags = UPGFLG_Enforced;
  1297. }
  1298. }
  1299. rpszUpgrades = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*cUpgrades);
  1300. if (!rpszUpgrades)
  1301. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1302. for (count = 0; (count < cUpgrades); count++)
  1303. {
  1304. WCHAR szPackageGuid[_MAX_PATH];
  1305. UINT len = wcslen(prgUpgradeInfoList[count].szClassStore);
  1306. rpszUpgrades[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *(36+PKG_UPG_DELIM1_LEN+len+PKG_UPG_DELIM2_LEN+2+2));
  1307. // Guid size+::+length++:+flagDigit+2
  1308. if (!rpszUpgrades[count])
  1309. {
  1310. FREEARR(rpszUpgrades, count);
  1311. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1312. }
  1313. StringFromGUID(prgUpgradeInfoList[count].PackageGuid, szPackageGuid);
  1314. wsprintf(rpszUpgrades[count], L"%s%s%s%s%02x", prgUpgradeInfoList[count].szClassStore, PKG_UPG_DELIMITER1, szPackageGuid,
  1315. PKG_UPG_DELIMITER2, prgUpgradeInfoList[count].Flag%16);
  1316. }
  1317. PackStrArrToAttr(pAttr+cAttr, UPGRADESPACKAGES, rpszUpgrades, cUpgrades);
  1318. cAttr++;
  1319. //
  1320. // Update the TimeStamp
  1321. //
  1322. GetCurrentUsn(szUsn);
  1323. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  1324. cAttr++;
  1325. // Set the Attribute
  1326. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1327. if (SUCCEEDED(hr))
  1328. {
  1329. //
  1330. // Update Store Usn
  1331. //
  1332. UpdateStoreUsn(m_ADsContainer, szUsn);
  1333. }
  1334. Error_Cleanup:
  1335. if (hADs)
  1336. ADSICloseDSObject(hADs);
  1337. if (szFullName)
  1338. CoTaskMemFree(szFullName);
  1339. for (i = 0; i < cAttr; i++)
  1340. FreeAttr(pAttr[i]);
  1341. if (pAttrGot)
  1342. FreeADsMem(pAttrGot);
  1343. if (pProp)
  1344. CoTaskMemFree(pProp);
  1345. if (pUpgradeInfoStored)
  1346. CoTaskMemFree(pUpgradeInfoStored);
  1347. if (pAddList)
  1348. CoTaskMemFree(pAddList);
  1349. if (pRemoveList)
  1350. CoTaskMemFree(pRemoveList);
  1351. return RemapErrorCode(hr, m_szContainerName);
  1352. }
  1353. extern LPOLESTR szAppCategoryColumns;
  1354. //---------------------------------------------------------------
  1355. // Function: GetAppCategories
  1356. //
  1357. // Synopsis: gets the list of Package Categories in the Domain.
  1358. //
  1359. // Arguments:
  1360. // [in]
  1361. // Locale
  1362. // Locale for the categories. Used to get the description.
  1363. // [out]
  1364. // pAppCategoryList
  1365. // the list of Application Categories in the domain
  1366. //
  1367. // Returns:
  1368. // S_OK, E_OUTOFMEMORY, CS_E_XXX
  1369. //
  1370. // Gets the FullName of the Domain, binds to the AppCategory container
  1371. // below that. and gets all the categories with approp. types.
  1372. //----------------------------------------------------------------
  1373. HRESULT CClassContainer::GetAppCategories (
  1374. LCID Locale,
  1375. APPCATEGORYINFOLIST *pAppCategoryList
  1376. )
  1377. {
  1378. HRESULT hr = S_OK;
  1379. WCHAR szfilter[_MAX_PATH];
  1380. WCHAR szRootPath[_MAX_PATH], szAppCategoryContainer[_MAX_PATH];
  1381. HANDLE hADs = NULL;
  1382. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  1383. ADS_SEARCHPREF_INFO SearchPrefs[2];
  1384. // set the search preference.
  1385. SearchPrefs[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  1386. SearchPrefs[0].vValue.dwType = ADSTYPE_INTEGER;
  1387. SearchPrefs[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  1388. // we do not expect too many categories
  1389. SearchPrefs[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  1390. SearchPrefs[1].vValue.dwType = ADSTYPE_INTEGER;
  1391. SearchPrefs[1].vValue.Integer = 20;
  1392. if (!IsValidPtrOut(pAppCategoryList, sizeof(APPCATEGORYINFOLIST)))
  1393. return E_INVALIDARG;
  1394. // get the name of the domain.
  1395. hr = GetRootPath(szRootPath);
  1396. ERROR_ON_FAILURE(hr);
  1397. // Names returned by GetRootPath are in only 1 format and we don't need to
  1398. // use BuildADsPath.
  1399. wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX, APPCATEGORYCONTAINERNAME,
  1400. szRootPath+LDAPPREFIXLENGTH);
  1401. wsprintf(szfilter, L"(objectClass=%s)", CLASS_CS_CATEGORY);
  1402. //binds to the category container
  1403. hr = ADSIOpenDSObject(szAppCategoryContainer, NULL, NULL,
  1404. ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs);
  1405. ERROR_ON_FAILURE(hr);
  1406. hr = ADSISetSearchPreference(hADs, SearchPrefs, 2);
  1407. ERROR_ON_FAILURE(hr);
  1408. // gets a search handle
  1409. hr = ADSIExecuteSearch(hADs, szfilter, pszCategoryAttrNames, cCategoryAttr, &hADsSearchHandle);
  1410. ERROR_ON_FAILURE(hr);
  1411. // tries to find out the number of categories.
  1412. pAppCategoryList->cCategory = 0;
  1413. for (hr = ADSIGetFirstRow(hADs, hADsSearchHandle);
  1414. ((SUCCEEDED(hr)) && (hr != S_ADS_NOMORE_ROWS));
  1415. hr = ADSIGetNextRow(hADs, hADsSearchHandle))
  1416. pAppCategoryList->cCategory++;
  1417. // get the number of elements.
  1418. pAppCategoryList->pCategoryInfo = (APPCATEGORYINFO *)CoTaskMemAlloc(
  1419. sizeof(APPCATEGORYINFO)*
  1420. pAppCategoryList->cCategory);
  1421. if (!(pAppCategoryList->pCategoryInfo))
  1422. {
  1423. pAppCategoryList->cCategory = 0;
  1424. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1425. }
  1426. // if it has come till here, it has to have a search handle
  1427. ADSICloseSearchHandle(hADs, hADsSearchHandle);
  1428. hADsSearchHandle = NULL;
  1429. memset(pAppCategoryList->pCategoryInfo, 0, sizeof(APPCATEGORYINFO)*pAppCategoryList->cCategory);
  1430. // gets a search handle
  1431. hr = ADSIExecuteSearch(hADs, szfilter, pszCategoryAttrNames, cCategoryAttr, &hADsSearchHandle);
  1432. ERROR_ON_FAILURE(hr);
  1433. // passes the search handle and gets the categorylist.
  1434. hr = FetchCategory(hADs, hADsSearchHandle, pAppCategoryList, Locale);
  1435. ERROR_ON_FAILURE(hr);
  1436. Error_Cleanup:
  1437. if (hADsSearchHandle)
  1438. ADSICloseSearchHandle(hADs, hADsSearchHandle);
  1439. if (hADs)
  1440. ADSICloseDSObject(hADs);
  1441. return RemapErrorCode(hr, m_szContainerName);
  1442. }
  1443. //---------------------------------------------------------------
  1444. // Function: RegisterAppCategory
  1445. //
  1446. // Synopsis: Adda category and assoc desc. for the whole Domain(This is per domain
  1447. // and not per class store.)
  1448. //
  1449. // Arguments:
  1450. // [in]
  1451. // pAppCategory
  1452. // Pointer to a APPCATEGORYINFO structure to be added.
  1453. //
  1454. // Returns:
  1455. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  1456. //
  1457. // Finds the root path of the domain. binds to the category container
  1458. // underneath it. deletes this particular AppCategory.
  1459. //----------------------------------------------------------------
  1460. HRESULT CClassContainer::RegisterAppCategory (
  1461. APPCATEGORYINFO *pAppCategory
  1462. )
  1463. {
  1464. WCHAR szRootPath[_MAX_PATH], localedescription[128+16],
  1465. szAppCategoryContainer[_MAX_PATH], szRDN[_MAX_PATH],
  1466. * szFullName = NULL, szAppCatid[_MAX_PATH];
  1467. HRESULT hr = S_OK;
  1468. HANDLE hADsContainer = NULL, hADs = NULL;
  1469. ULONG i, j, cdesc = 0, posn = 0;
  1470. LPOLESTR * pszDescExisting = NULL, pszDesc = NULL;
  1471. LPOLESTR AttrName = LOCALEDESCRIPTION;
  1472. ADS_ATTR_INFO * pAttrGot = NULL, pAttr[6];
  1473. DWORD cgot = 0, cAttr = 0;
  1474. BOOL fExists = TRUE;
  1475. if ((!pAppCategory) || (!IsValidReadPtrIn(pAppCategory, sizeof(APPCATEGORYINFO))))
  1476. return E_INVALIDARG;
  1477. if ((pAppCategory->pszDescription == NULL) ||
  1478. (IsBadStringPtr(pAppCategory->pszDescription, _MAX_PATH)))
  1479. return E_INVALIDARG;
  1480. if (IsNullGuid(pAppCategory->AppCategoryId))
  1481. return E_INVALIDARG;
  1482. // get the name of the root of the domain
  1483. hr = GetRootPath(szRootPath);
  1484. ERROR_ON_FAILURE(hr);
  1485. // Bind to a AppCategory container
  1486. // Names returned by GetRootPath are in only 1 format and we don't need to
  1487. // use BuildADsPath.
  1488. wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX, APPCATEGORYCONTAINERNAME,
  1489. szRootPath+LDAPPREFIXLENGTH);
  1490. // container is supposed to exist.
  1491. hr = ADSIOpenDSObject(szAppCategoryContainer, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  1492. &hADsContainer);
  1493. ERROR_ON_FAILURE(hr);
  1494. RDNFromGUID(pAppCategory->AppCategoryId, szRDN);
  1495. wsprintf(localedescription, L"%x %s %s", pAppCategory->Locale, CAT_DESC_DELIMITER,
  1496. pAppCategory->pszDescription);
  1497. BuildADsPathFromParent(szAppCategoryContainer, szRDN, &szFullName);
  1498. // BUGBUG:: ADS_FAST_BIND and the create seems to be going twice. why?
  1499. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs);
  1500. if (SUCCEEDED(hr))
  1501. hr = ADSIGetObjectAttributes(hADs, &AttrName, 1, &pAttrGot, &cgot);
  1502. if (SUCCEEDED(hr))
  1503. {
  1504. fExists = TRUE;
  1505. }
  1506. else
  1507. {
  1508. fExists = FALSE;
  1509. PackStrToAttr(pAttr, OBJECTCLASS, CLASS_CS_CATEGORY); cAttr++;
  1510. PackGUIDToAttr(pAttr+cAttr, CATEGORYCATID, &(pAppCategory->AppCategoryId)); cAttr++;
  1511. hr = ADSICreateDSObject(hADsContainer, szRDN, pAttr, cAttr);
  1512. for (j = 0; j < cAttr; j++)
  1513. FreeAttr(pAttr[j]);
  1514. cAttr = 0;
  1515. if (hADs)
  1516. {
  1517. ADSICloseDSObject(hADs);
  1518. hADs = NULL;
  1519. }
  1520. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs);
  1521. }
  1522. if (szFullName)
  1523. FreeADsMem(szFullName);
  1524. ERROR_ON_FAILURE(hr);
  1525. if (fExists) {
  1526. if (cgot)
  1527. {
  1528. UnpackStrArrFrom(pAttrGot[0], &pszDescExisting, &cdesc);
  1529. }
  1530. // Existing list of descriptions
  1531. if (posn = FindDescription(pszDescExisting, cdesc, &(pAppCategory->Locale), NULL, 0))
  1532. { // Delete the old value
  1533. PackStrArrToAttrEx(pAttr+cAttr, LOCALEDESCRIPTION, pszDescExisting+(posn-1), 1, FALSE); cAttr++;
  1534. }
  1535. CoTaskMemFree(pszDescExisting);
  1536. }
  1537. pszDesc = localedescription;
  1538. PackStrArrToAttrEx(pAttr+cAttr, LOCALEDESCRIPTION, &pszDesc, 1, TRUE);
  1539. cAttr++;
  1540. DWORD cModified;
  1541. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1542. Error_Cleanup:
  1543. if (pAttrGot)
  1544. FreeADsMem(pAttrGot);
  1545. for (i = 0; i < cAttr; i++)
  1546. FreeAttr(pAttr[i]);
  1547. if (hADs)
  1548. ADSICloseDSObject(hADs);
  1549. if (hADsContainer)
  1550. ADSICloseDSObject(hADsContainer);
  1551. return RemapErrorCode(hr, m_szContainerName);
  1552. }
  1553. //---------------------------------------------------------------
  1554. // Function: UnregisterAppCategory
  1555. //
  1556. // Synopsis: Removes a category from the whole Domain(This is per domain)
  1557. // and not per class store.
  1558. //
  1559. // Arguments:
  1560. // [in]
  1561. // pAppCategoryId
  1562. // Pointer to a GUID that has to be removed.
  1563. //
  1564. // Returns:
  1565. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  1566. //
  1567. // Finds the root path of the domain. binds to the category container
  1568. // underneath it. deletes this particular AppCategory.
  1569. //----------------------------------------------------------------
  1570. HRESULT CClassContainer::UnregisterAppCategory (
  1571. GUID *pAppCategoryId
  1572. )
  1573. {
  1574. WCHAR szRootPath[_MAX_PATH], szRDN[_MAX_PATH],
  1575. szAppCategoryContainer[_MAX_PATH];
  1576. HRESULT hr = S_OK;
  1577. HANDLE hADs = NULL;
  1578. if (!IsValidReadPtrIn(pAppCategoryId, sizeof(GUID)))
  1579. return E_INVALIDARG;
  1580. hr = GetRootPath(szRootPath);
  1581. // Bind to a AppCategory container
  1582. // Names returned by GetRootPath are in only 1 format and we don't need to
  1583. // use BuildADsPath.
  1584. wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX, APPCATEGORYCONTAINERNAME,
  1585. szRootPath+LDAPPREFIXLENGTH);
  1586. hr = ADSIOpenDSObject(szAppCategoryContainer, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  1587. &hADs);
  1588. ERROR_ON_FAILURE(hr);
  1589. RDNFromGUID(*pAppCategoryId, szRDN);
  1590. hr = ADSIDeleteDSObject(hADs, szRDN);
  1591. ADSICloseDSObject(hADs);
  1592. // Delete this category
  1593. Error_Cleanup:
  1594. return RemapErrorCode(hr, m_szContainerName);
  1595. }
  1596. //---------------------------------------------------------------
  1597. // Function: DeletePackage
  1598. //
  1599. // Synopsis: Permanently remove a package and the associated Classes
  1600. // from class store
  1601. //
  1602. // Arguments:
  1603. // [in]
  1604. // PackageGuid
  1605. // Guid of the package that has to be removed.
  1606. //
  1607. // Returns:
  1608. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  1609. //
  1610. // Deletes the package and all the clsids associated with the
  1611. // package (using DeleteClass) Ignores the error from DeleteClass
  1612. // Tries to delete all the upgrade relationships from this package.
  1613. // Errors are ignored.
  1614. //----------------------------------------------------------------
  1615. HRESULT CClassContainer::DeletePackage (LPOLESTR szFullName
  1616. )
  1617. {
  1618. HRESULT hr = S_OK;
  1619. DWORD cStr = 0, count = 0, cgot = 0, posn = 0;
  1620. LPOLESTR szRDN = NULL, szJunk = NULL;
  1621. LPOLESTR * szStr = NULL;
  1622. LPOLESTR pAttrName[] = {PKGCLSIDLIST, UPGRADESPACKAGES, OBJECTGUID};
  1623. ADS_ATTR_INFO * pAttr = NULL;
  1624. HANDLE hADs = NULL;
  1625. WCHAR szUsn[20];
  1626. GUID PackageGuid;
  1627. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
  1628. &hADs);
  1629. if (!SUCCEEDED(hr))
  1630. return hr;
  1631. GetCurrentUsn(szUsn);
  1632. hr = ADSIGetObjectAttributes(hADs, pAttrName, 3, &pAttr, &cgot);
  1633. memset(&PackageGuid, 0, sizeof(GUID));
  1634. posn = GetPropertyFromAttr(pAttr, cgot, OBJECTGUID);
  1635. if (posn < cgot)
  1636. UnpackGUIDFrom(pAttr[posn], &PackageGuid);
  1637. posn = GetPropertyFromAttr(pAttr, cgot, PKGCLSIDLIST);
  1638. if (posn < cgot)
  1639. UnpackStrArrFrom(pAttr[posn], &szStr, &cStr);
  1640. for (count = 0; count < cStr; count++)
  1641. {
  1642. if (wcslen(szStr[count]) > (STRINGGUIDLEN-1))
  1643. szStr[count][STRINGGUIDLEN-1] = L'\0';
  1644. hr = DeleteClass(szStr[count]);
  1645. }
  1646. if (szStr)
  1647. CoTaskMemFree(szStr);
  1648. szStr = NULL;
  1649. cStr = 0;
  1650. posn = GetPropertyFromAttr(pAttr, cgot, UPGRADESPACKAGES);
  1651. if (posn < cgot)
  1652. UnpackStrArrFrom(pAttr[posn], &szStr, &cStr);
  1653. for (count = 0; count < cStr; count++)
  1654. {
  1655. GUID UpgradeeGuid;
  1656. WCHAR *pStr = NULL;
  1657. LPOLESTR ptr = szStr[count];
  1658. UINT len = wcslen (ptr);
  1659. DWORD UpgradeFlag, Flags = 0;
  1660. if (len <= 41)
  1661. continue;
  1662. *(ptr + (len - 3)) = NULL;
  1663. UpgradeFlag = wcstoul(ptr+(len-2), &pStr, 16);
  1664. *(ptr + (len - 3 - 36 - 2)) = L'\0';
  1665. /* -GUID-'::'*/
  1666. GUIDFromString(ptr+len-3-36, &UpgradeeGuid);
  1667. if (UpgradeFlag & UPGFLG_Enforced)
  1668. Flags = UPGFLG_Enforced;
  1669. }
  1670. if (szStr)
  1671. CoTaskMemFree(szStr);
  1672. szStr = NULL;
  1673. cStr = 0;
  1674. // ignore errors
  1675. if (pAttr)
  1676. FreeADsMem(pAttr);
  1677. ADSICloseDSObject(hADs);
  1678. BuildADsParentPath(szFullName, &szJunk, &szRDN);
  1679. if (szJunk)
  1680. FreeADsMem(szJunk);
  1681. hr = ADSIDeleteDSObject(m_ADsPackageContainer, szRDN);
  1682. if (szRDN)
  1683. FreeADsMem(szRDN);
  1684. if (SUCCEEDED(hr))
  1685. {
  1686. //
  1687. // Update Store Usn
  1688. //
  1689. UpdateStoreUsn(m_ADsContainer, szUsn);
  1690. }
  1691. return hr;
  1692. }
  1693. //---------------------------------------------------------------
  1694. // Function: RemovePackage
  1695. //
  1696. // Synopsis: Mark a package as disabled or orphaned
  1697. // Or permanently remove a package and the associated Classes
  1698. // from class store
  1699. //
  1700. // Arguments:
  1701. // [in]
  1702. // PackageGuid
  1703. // Guid of the package that has to be removed.
  1704. // [in]
  1705. // dwFlags
  1706. // The new flags for the package. To delete the package explicitly
  1707. // use flag zero or orphan.
  1708. //
  1709. // Returns:
  1710. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  1711. //
  1712. // Calls Delete package if the flags is zero or Orphan.
  1713. // Otherwise it sets the new flags and stamps the new time stamp.
  1714. //----------------------------------------------------------------
  1715. HRESULT CClassContainer::RemovePackage (
  1716. LPOLESTR pszPackageName,
  1717. DWORD dwFlags
  1718. )
  1719. {
  1720. HRESULT hr = S_OK;
  1721. WCHAR *szRDN = NULL, *szFullName = NULL;
  1722. HANDLE hADs = NULL;
  1723. WCHAR szUsn[20];
  1724. ADS_ATTR_INFO pAttr[7];
  1725. DWORD cAttr = 0, cModified = 0, i=0;
  1726. if ((dwFlags != 0) && (dwFlags != ACTFLG_Orphan) && (dwFlags != ACTFLG_Uninstall))
  1727. return E_INVALIDARG;
  1728. hr = GetDNFromPackageName(pszPackageName, &szFullName);
  1729. ERROR_ON_FAILURE(hr);
  1730. if (hr != S_OK)
  1731. return CS_E_OBJECT_NOTFOUND;
  1732. if (dwFlags == 0)
  1733. // delete the package from the class store
  1734. {
  1735. hr = DeletePackage(szFullName);
  1736. }
  1737. else
  1738. {
  1739. GUID NewPackageId;
  1740. WCHAR szNewRDN[_MAX_PATH], *szRDN = NULL, *szJunk = NULL;
  1741. //
  1742. // PackageName is unchanged.
  1743. //
  1744. GetCurrentUsn(szUsn);
  1745. /*
  1746. CoCreateGuid(&NewPackageId);
  1747. RDNFromGUID(NewPackageId, szNewRDN);
  1748. BuildADsParentPath(szFullName, &szJunk, &szRDN);
  1749. if (szJunk)
  1750. FreeADsMem(szJunk);
  1751. hr = ADSIModifyRdn(m_ADsPackageContainer, szRDN, szNewRDN);
  1752. if (szRDN)
  1753. FreeADsMem(szRDN);
  1754. ERROR_ON_FAILURE(hr);
  1755. // construct the Full Path for the Package.
  1756. BuildADsPathFromParent(m_szPackageName, szNewRDN, &szFullName);
  1757. */
  1758. // Bind to the Package Object.
  1759. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, &hADs);
  1760. ERROR_ON_FAILURE(hr);
  1761. // setting the flag as orphan/uninstall
  1762. PackDWToAttr (pAttr+cAttr, PACKAGEFLAGS, dwFlags);
  1763. cAttr++;
  1764. // stamping the modification time for cleanup later.
  1765. PackStrToAttr (pAttr+cAttr, PKGUSN, szUsn);
  1766. cAttr++;
  1767. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1768. if (hADs)
  1769. ADSICloseDSObject(hADs);
  1770. for (i = 0; i < cAttr; i++)
  1771. FreeAttr(pAttr[i]);
  1772. if (SUCCEEDED(hr))
  1773. {
  1774. //
  1775. // Update Class Store Usn
  1776. //
  1777. UpdateStoreUsn(m_ADsContainer, szUsn);
  1778. }
  1779. }
  1780. Error_Cleanup:
  1781. if (szFullName)
  1782. CoTaskMemFree(szFullName);
  1783. return RemapErrorCode(hr, m_szContainerName);
  1784. }
  1785. // Merges list1 and List2 into ResList removing duplicates.
  1786. HRESULT MergePropList(LPOLESTR *List1, DWORD cList1,
  1787. LPOLESTR *List2, DWORD cList2,
  1788. LPOLESTR **ResList,DWORD *cResList)
  1789. {
  1790. DWORD i, j;
  1791. *cResList = 0;
  1792. *ResList = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*(cList1+cList2));
  1793. if (!*ResList)
  1794. return E_OUTOFMEMORY;
  1795. for (i = 0; i < cList1; i++)
  1796. (*ResList)[i] = List1[i];
  1797. for (i = 0; i < cList2; i++) {
  1798. for (j = 0; j < cList1; j++)
  1799. if (wcscmp((*ResList)[j], List2[i]) == 0)
  1800. break;
  1801. if (j == cList1)
  1802. (*ResList)[(*cResList)++] = List2[i];
  1803. }
  1804. return S_OK;
  1805. }
  1806. //---------------------------------------------------------------
  1807. // Function: NewClass
  1808. //
  1809. // Synopsis: Adds classes corresp. to a package under the DS.
  1810. // Called by AddPackage.
  1811. //
  1812. // Arguments:
  1813. // [in]
  1814. // pClassDetail
  1815. // Class Detail of the clsid that needs to be added.
  1816. // Validation is specified in class store doc.
  1817. //
  1818. // Returns:
  1819. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  1820. //
  1821. // Validates the classdetail structure. If the clsid already exists in
  1822. // the DS, it adds these values under the same clsid and increases the refcount.
  1823. //----------------------------------------------------------------
  1824. HRESULT CClassContainer::NewClass (CLASSDETAIL *pClassDetail)
  1825. {
  1826. HRESULT hr = S_OK;
  1827. STRINGGUID szGUID1, szGUID2;
  1828. WCHAR szRDN [_MAX_PATH], * szFullName = NULL;
  1829. ADS_ATTR_INFO pAttr[6], *pAttrsGot = NULL;
  1830. BOOL fExists = FALSE;
  1831. HANDLE hADs = NULL;
  1832. LPOLESTR AttrNames[] = {PKGFILEEXTNLIST, PROGIDLIST, CLASSREFCOUNTER};
  1833. DWORD posn = 0, cProp = 0, cPropMerged = 0, refcount = 0,
  1834. cAttr = 0, cModified = 0, cgot = 0, i;
  1835. LPOLESTR * pszProp = NULL, *pszPropMerged = NULL;
  1836. if (!m_fOpen)
  1837. return E_FAIL;
  1838. //
  1839. // Cant be a NULL guid
  1840. //
  1841. if (IsNullGuid(pClassDetail->Clsid))
  1842. return E_INVALIDARG;
  1843. // Not using RDNFrom GUID b'cos szGUID1 is used below
  1844. StringFromGUID(pClassDetail->Clsid, szGUID1);
  1845. wsprintf(szRDN, L"CN=%s", szGUID1);
  1846. BuildADsPathFromParent(m_szClassName, szRDN, &szFullName);
  1847. hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
  1848. &hADs);
  1849. if (SUCCEEDED(hr)) {
  1850. fExists = TRUE;
  1851. hr = ADSIGetObjectAttributes(hADs, AttrNames, 3, &pAttrsGot, &cgot);
  1852. }
  1853. // BUGBUG :: bug in adsldpc doesn't return error in open.
  1854. if (!SUCCEEDED(hr))
  1855. fExists = FALSE;
  1856. //
  1857. // Create the RDN for the Class Object
  1858. //
  1859. if (!fExists) {
  1860. PackStrToAttr(pAttr+cAttr, OBJECTCLASS, CLASS_CS_CLASS); cAttr++;
  1861. PackStrToAttr(pAttr+cAttr, CLASSCLSID, szGUID1); cAttr++;
  1862. }
  1863. if (pClassDetail->cProgId)
  1864. {
  1865. if (fExists)
  1866. posn = GetPropertyFromAttr(pAttrsGot, cgot, PROGIDLIST);
  1867. if (posn < cgot)
  1868. UnpackStrArrFrom(pAttrsGot[posn], &pszProp, &cProp);
  1869. // we can not just append b'cos duplicate values are valid conditions.
  1870. MergePropList(pszProp, cProp,
  1871. pClassDetail->prgProgId, pClassDetail->cProgId,
  1872. &pszPropMerged, &cPropMerged);
  1873. PackStrArrToAttr(pAttr+cAttr, PROGIDLIST, pszPropMerged, cPropMerged);
  1874. cAttr++;
  1875. CoTaskMemFree(pszPropMerged);
  1876. pszPropMerged = NULL; cPropMerged = 0;
  1877. CoTaskMemFree(pszProp);
  1878. pszProp = NULL; cProp = 0;
  1879. }
  1880. if (!IsNullGuid(pClassDetail->TreatAs))
  1881. {
  1882. StringFromGUID(pClassDetail->TreatAs, szGUID2);
  1883. PackStrToAttr(pAttr+cAttr, TREATASCLSID, szGUID2);
  1884. cAttr++;
  1885. }
  1886. // this is going to be modified if find that an entry already exists.
  1887. if (fExists) {
  1888. posn = GetPropertyFromAttr(pAttrsGot, cgot, CLASSREFCOUNTER);
  1889. if (posn < cgot) {
  1890. UnpackDWFrom(pAttrsGot[posn], &refcount);
  1891. }
  1892. }
  1893. refcount++;
  1894. PackDWToAttr(pAttr+cAttr, CLASSREFCOUNTER, refcount);
  1895. cAttr++;
  1896. if (fExists)
  1897. hr = ADSISetObjectAttributes(hADs, pAttr, cAttr, &cModified);
  1898. else
  1899. hr = ADSICreateDSObject(m_ADsClassContainer, szRDN, pAttr, cAttr);
  1900. if (pAttrsGot)
  1901. FreeADsMem(pAttrsGot);
  1902. if (szFullName)
  1903. FreeADsMem(szFullName);
  1904. for (i = 0; i < cAttr; i++)
  1905. FreeAttr(pAttr[i]);
  1906. return RemapErrorCode(hr, m_szContainerName);
  1907. }
  1908. #define SCRIPT_IN_DIRECTORY 256
  1909. //---------------------------------------------------------------
  1910. // Function: AddPackage
  1911. //
  1912. // Synopsis: Adds a package object in the DS.
  1913. //
  1914. // Arguments:
  1915. // [out]
  1916. // pszPackageId
  1917. // An Id that is returned corresponding to the package.
  1918. // [in]
  1919. // pPackageDetail
  1920. // Pointer to a PACKAGEDETAIL info for this package
  1921. // The various validations that is done is documented
  1922. // in associated class store doc.
  1923. //
  1924. // Returns:
  1925. // S_OK, E_OUTOFMEMORY, E_INVALIDARG, CS_E_XXX
  1926. //
  1927. // Validates the packagedetail structure. Packs ADS_ATTR_INFO structure with
  1928. // the values and tries to create the object in the DS.
  1929. // Calls NewClass to add all the clsids after that.
  1930. // If this returns error
  1931. // the whole package is removed.
  1932. //----------------------------------------------------------------
  1933. HRESULT CClassContainer::AddPackage (
  1934. PACKAGEDETAIL *pPackageDetail,
  1935. GUID *pPkgGuid
  1936. )
  1937. {
  1938. HRESULT hr = S_OK;
  1939. WCHAR szRDN [_MAX_PATH];
  1940. LPOLESTR * pszGuid1 = NULL, *pszGuid2 = NULL,
  1941. * pszGuid3 = NULL, *pszGuid4 = NULL,
  1942. * pszProgId = NULL, *pszFileExt = NULL,
  1943. * rpszUpgrades = NULL, *rpszSources = NULL,
  1944. szPackageId = NULL, szJunk = NULL;
  1945. DWORD * pdwArch=NULL, count = 0, cPackProgId = 0;
  1946. ADS_ATTR_INFO pAttr[29];
  1947. DWORD cAttr = 0;
  1948. WCHAR szUsn[20];
  1949. BOOL fPackageCreated = FALSE, GenerateGuid = FALSE;
  1950. GUID PackageGuidId;
  1951. if ((!pPkgGuid) || !IsValidReadPtrIn(pPkgGuid, sizeof(GUID)))
  1952. return E_INVALIDARG;
  1953. if ((!(pPackageDetail->pszPackageName)) ||
  1954. IsBadStringPtr((pPackageDetail->pszPackageName), _MAX_PATH))
  1955. return E_INVALIDARG;
  1956. if (!pPackageDetail)
  1957. return E_INVALIDARG;
  1958. if (!IsValidReadPtrIn(pPackageDetail, sizeof(PACKAGEDETAIL)))
  1959. return E_INVALIDARG;
  1960. // validating ActivationInfo.
  1961. if (pPackageDetail->pActInfo)
  1962. {
  1963. if (!IsValidReadPtrIn(pPackageDetail->pActInfo, sizeof(ACTIVATIONINFO)))
  1964. return E_INVALIDARG;
  1965. if (!IsValidReadPtrIn(pPackageDetail->pActInfo->pClasses,
  1966. sizeof(CLASSDETAIL) * (pPackageDetail->pActInfo->cClasses)))
  1967. return E_INVALIDARG;
  1968. // validating classdetail
  1969. for (count = 0; (count < (pPackageDetail->pActInfo->cClasses)); count++)
  1970. {
  1971. CLASSDETAIL *pClassDetail = (pPackageDetail->pActInfo->pClasses)+count;
  1972. if (IsNullGuid(pClassDetail->Clsid))
  1973. return E_INVALIDARG;
  1974. for (DWORD count1 = 0; (count1 < (pClassDetail->cProgId)); count1++)
  1975. {
  1976. // if profid is NULL or an empty string.
  1977. if ((!((pClassDetail->prgProgId)[count1])) ||
  1978. (!((pClassDetail->prgProgId)[count1][0])))
  1979. return E_INVALIDARG;
  1980. }
  1981. }
  1982. if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgShellFileExt,
  1983. sizeof(LPOLESTR) * (pPackageDetail->pActInfo->cShellFileExt)))
  1984. return E_INVALIDARG;
  1985. for (count = 0; count < (pPackageDetail->pActInfo->cShellFileExt); count++)
  1986. {
  1987. if (!pPackageDetail->pActInfo->prgShellFileExt[count])
  1988. return E_INVALIDARG;
  1989. }
  1990. if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgPriority,
  1991. sizeof(UINT) * (pPackageDetail->pActInfo->cShellFileExt)))
  1992. return E_INVALIDARG;
  1993. if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgInterfaceId,
  1994. sizeof(IID) * (pPackageDetail->pActInfo->cInterfaces)))
  1995. return E_INVALIDARG;
  1996. if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgTlbId,
  1997. sizeof(GUID) * (pPackageDetail->pActInfo->cTypeLib)))
  1998. return E_INVALIDARG;
  1999. }
  2000. // Validating InstallInfo
  2001. // BUGBUG:: Validate ProductCode, Mvipc
  2002. if ((pPackageDetail->pInstallInfo == NULL) ||
  2003. (!IsValidReadPtrIn(pPackageDetail->pInstallInfo, sizeof(INSTALLINFO)))
  2004. )
  2005. return E_INVALIDARG;
  2006. if (!IsValidReadPtrIn(pPackageDetail->pInstallInfo->prgUpgradeInfoList,
  2007. sizeof(UPGRADEINFO)*(pPackageDetail->pInstallInfo->cUpgrades)))
  2008. return E_INVALIDARG;
  2009. for (count = 0; count < (pPackageDetail->pInstallInfo->cUpgrades); count++)
  2010. {
  2011. if ((!(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore)) ||
  2012. IsBadStringPtr((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore), _MAX_PATH))
  2013. return E_INVALIDARG;
  2014. if (IsNullGuid(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].PackageGuid))
  2015. return E_INVALIDARG;
  2016. if (((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_Uninstall) == 0) &&
  2017. ((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_NoUninstall) == 0) &&
  2018. ((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_UpgradedBy) == 0))
  2019. return E_INVALIDARG;
  2020. }
  2021. // validating PlatformInfo
  2022. if ((pPackageDetail->pPlatformInfo == NULL) ||
  2023. (!IsValidReadPtrIn(pPackageDetail->pPlatformInfo, sizeof(PLATFORMINFO)))
  2024. )
  2025. return E_INVALIDARG;
  2026. if (!IsValidReadPtrIn(pPackageDetail->pPlatformInfo->prgPlatform,
  2027. sizeof(CSPLATFORM) * (pPackageDetail->pPlatformInfo->cPlatforms)))
  2028. return E_INVALIDARG;
  2029. if ((pPackageDetail->pPlatformInfo->cLocales == 0) ||
  2030. (pPackageDetail->pPlatformInfo->cPlatforms == 0))
  2031. return E_INVALIDARG;
  2032. if (!IsValidReadPtrIn(pPackageDetail->pPlatformInfo->prgLocale,
  2033. sizeof(LCID) * (pPackageDetail->pPlatformInfo->cLocales)))
  2034. return E_INVALIDARG;
  2035. // validating InstallInfo
  2036. // Validating other fields in PackageDetail structure
  2037. if ((pPackageDetail->pszSourceList == NULL) ||
  2038. (!IsValidReadPtrIn(pPackageDetail->pszSourceList,
  2039. sizeof(LPOLESTR) * (pPackageDetail->cSources))))
  2040. return E_INVALIDARG;
  2041. for (count = 0; count < (pPackageDetail->cSources); count++)
  2042. {
  2043. if ((!pPackageDetail->pszSourceList[count]) ||
  2044. (IsBadStringPtr(pPackageDetail->pszSourceList[count], _MAX_PATH)))
  2045. return E_INVALIDARG;
  2046. }
  2047. if (pPackageDetail->rpCategory)
  2048. {
  2049. if (!IsValidReadPtrIn(pPackageDetail->rpCategory,
  2050. sizeof(GUID) * (pPackageDetail->cCategories)))
  2051. return E_INVALIDARG;
  2052. }
  2053. // If the restrictions are too constrictive then we should go to
  2054. // the DS, to see whether it is a valid name or not. till then..
  2055. // GenerateGuid = InvalidDSName(pPackageDetail->pszPackageName);
  2056. hr = GetDNFromPackageName(pPackageDetail->pszPackageName, &szJunk);
  2057. if (szJunk)
  2058. CoTaskMemFree(szJunk);
  2059. if (FAILED(hr))
  2060. return RemapErrorCode(hr, m_szContainerName);
  2061. if (hr == S_OK)
  2062. {
  2063. return CS_E_OBJECT_ALREADY_EXISTS;
  2064. }
  2065. /* szPackageId = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(GenerateGuid?41:
  2066. (wcslen(pPackageDetail->pszPackageName)+1)));
  2067. */
  2068. szPackageId = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*41);
  2069. if (!(szPackageId))
  2070. return E_OUTOFMEMORY;
  2071. memset(&PackageGuidId, 0, sizeof(GUID));
  2072. /*
  2073. if (GenerateGuid)
  2074. {
  2075. CoCreateGuid(&PackageGuidId);
  2076. StringFromGUID(PackageGuidId, szPackageId);
  2077. }
  2078. else
  2079. wcscpy(szPackageId, pPackageDetail->pszPackageName);
  2080. */
  2081. // always generate guid
  2082. CoCreateGuid(&PackageGuidId);
  2083. StringFromGUID(PackageGuidId, szPackageId);
  2084. //
  2085. // Create the RDN for the Package Object
  2086. //
  2087. wsprintf(szRDN, L"CN=%s", szPackageId);
  2088. PackStrToAttr(pAttr+cAttr, OBJECTCLASS, CLASS_CS_PACKAGE); cAttr++;
  2089. // fill in the activation info
  2090. // add the class to the packagecontainer list
  2091. if (pPackageDetail->pActInfo)
  2092. {
  2093. if (pPackageDetail->pActInfo->cClasses)
  2094. {
  2095. pszGuid1 = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cClasses)*sizeof(LPOLESTR));
  2096. if (!pszGuid1) {
  2097. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2098. }
  2099. for (count = 0; count < pPackageDetail->pActInfo->cClasses; count++)
  2100. {
  2101. WCHAR szCtx[9];
  2102. pszGuid1[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(STRINGGUIDLEN+9));
  2103. if (!pszGuid1[count]) {
  2104. FREEARR(pszGuid1, count);
  2105. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2106. }
  2107. StringFromGUID(pPackageDetail->pActInfo->pClasses[count].Clsid, pszGuid1[count]);
  2108. wsprintf(szCtx, L":%8x", pPackageDetail->pActInfo->pClasses[count].dwComClassContext);
  2109. wcscat(pszGuid1[count], szCtx);
  2110. cPackProgId += pPackageDetail->pActInfo->pClasses[count].cProgId;
  2111. }
  2112. PackStrArrToAttr(pAttr+cAttr, PKGCLSIDLIST, pszGuid1,
  2113. pPackageDetail->pActInfo->cClasses); cAttr++;
  2114. }
  2115. // collecting all the progids from the various clsids.
  2116. pszProgId = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*cPackProgId);
  2117. if (!pszProgId) {
  2118. hr = E_OUTOFMEMORY;
  2119. ERROR_ON_FAILURE(hr);
  2120. }
  2121. for (count = 0, cPackProgId = 0; count < pPackageDetail->pActInfo->cClasses; count++) {
  2122. // for each clsid
  2123. DWORD cClassProgId, j = 0;
  2124. for (cClassProgId = 0; cClassProgId < pPackageDetail->pActInfo->pClasses[count].cProgId;
  2125. cClassProgId++)
  2126. {
  2127. // for each progid within ClassDetail
  2128. for (j = 0; j < cPackProgId; j++)
  2129. {
  2130. if (_wcsicmp(pszProgId[j],
  2131. pPackageDetail->pActInfo->pClasses[count].prgProgId[cClassProgId]) == 0)
  2132. break;
  2133. }
  2134. // needs to be added if there are no dups.
  2135. if (j == cPackProgId)
  2136. {
  2137. pszProgId[cPackProgId] =
  2138. pPackageDetail->pActInfo->pClasses[count].prgProgId[cClassProgId];
  2139. _wcslwr(pszProgId[cPackProgId]);
  2140. CSDBGPrint((L"AddPackage: Progid = %s\n", pszProgId[cPackProgId]));
  2141. cPackProgId++;
  2142. }
  2143. }
  2144. }
  2145. if (cPackProgId) {
  2146. PackStrArrToAttr(pAttr+cAttr, PROGIDLIST, pszProgId, cPackProgId); cAttr++;
  2147. }
  2148. CoTaskMemFree(pszProgId);
  2149. if (pPackageDetail->pActInfo->cShellFileExt) {
  2150. //
  2151. // Store a tuple in the format <file ext>:<priority>
  2152. //
  2153. pszFileExt = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cShellFileExt) * sizeof(LPOLESTR));
  2154. if (!pszFileExt)
  2155. {
  2156. hr = E_OUTOFMEMORY;
  2157. ERROR_ON_FAILURE(hr);
  2158. }
  2159. for (count = 0; count < pPackageDetail->pActInfo->cShellFileExt; count++)
  2160. {
  2161. pszFileExt[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *
  2162. (wcslen(pPackageDetail->pActInfo->prgShellFileExt[count])+1+2+1));
  2163. if (!pszFileExt[count])
  2164. {
  2165. FREEARR(pszFileExt, count);
  2166. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2167. }
  2168. // format is fileext+:+nn+NULL where nn = 2 digit priority
  2169. wsprintf(pszFileExt[count], L"%s:%2d",
  2170. pPackageDetail->pActInfo->prgShellFileExt[count],
  2171. pPackageDetail->pActInfo->prgPriority[count]%100);
  2172. _wcslwr(pszFileExt[count]);
  2173. }
  2174. PackStrArrToAttr(pAttr+cAttr, PKGFILEEXTNLIST, pszFileExt,
  2175. pPackageDetail->pActInfo->cShellFileExt); cAttr++;
  2176. }
  2177. if (pPackageDetail->pActInfo->cInterfaces) {
  2178. pszGuid2 = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cInterfaces)*sizeof(LPOLESTR));
  2179. if (!pszGuid2) {
  2180. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2181. }
  2182. for (count = 0; (count < (pPackageDetail->pActInfo->cInterfaces)); count++) {
  2183. pszGuid2[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
  2184. if (!pszGuid2[count]) {
  2185. FREEARR(pszGuid2, count);
  2186. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2187. }
  2188. StringFromGUID((pPackageDetail->pActInfo->prgInterfaceId)[count], pszGuid2[count]);
  2189. }
  2190. PackStrArrToAttr(pAttr+cAttr, PKGIIDLIST, pszGuid2, pPackageDetail->pActInfo->cInterfaces);
  2191. cAttr++;
  2192. }
  2193. /*
  2194. if (pPackageDetail->pActInfo->cTypeLib) {
  2195. pszGuid3 = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cTypeLib)*sizeof(LPOLESTR));
  2196. if (!pszGuid3) {
  2197. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2198. }
  2199. for (count = 0; (count < (pPackageDetail->pActInfo->cTypeLib)); count++) {
  2200. pszGuid3[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
  2201. if (!pszGuid3[count]) {
  2202. FREEARR(pszGuid3, count);
  2203. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2204. }
  2205. StringFromGUID((pPackageDetail->pActInfo->prgTlbId)[count], pszGuid3[count]);
  2206. }
  2207. PackStrArrToAttr(pAttr+cAttr, PKGTLBIDLIST, pszGuid3, pPackageDetail->pActInfo->cTypeLib);
  2208. cAttr++;
  2209. }
  2210. */
  2211. }
  2212. // fill in the platforminfo
  2213. // BUGBUG::***os version
  2214. if (pPackageDetail->pPlatformInfo->cPlatforms) {
  2215. pdwArch = (DWORD *)CoTaskMemAlloc(sizeof(DWORD)*(pPackageDetail->pPlatformInfo->cPlatforms));
  2216. if (!pdwArch)
  2217. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2218. for (count = 0; (count < (pPackageDetail->pPlatformInfo->cPlatforms)); count++)
  2219. UnpackPlatform (pdwArch+count, (pPackageDetail->pPlatformInfo->prgPlatform)+count);
  2220. PackDWArrToAttr(pAttr+cAttr, ARCHLIST, pdwArch, pPackageDetail->pPlatformInfo->cPlatforms);
  2221. cAttr++;
  2222. }
  2223. if (pPackageDetail->pPlatformInfo->cLocales) {
  2224. PackDWArrToAttr(pAttr+cAttr, LOCALEID, pPackageDetail->pPlatformInfo->prgLocale,
  2225. pPackageDetail->pPlatformInfo->cLocales);
  2226. cAttr++;
  2227. }
  2228. // fill in the installinfo
  2229. PackStrToAttr(pAttr+cAttr, PACKAGENAME, pPackageDetail->pszPackageName);
  2230. cAttr++;
  2231. PackDWToAttr(pAttr+cAttr, PACKAGETYPE, (DWORD)(pPackageDetail->pInstallInfo->PathType));
  2232. cAttr++;
  2233. if (pPackageDetail->pInstallInfo->pszScriptPath) {
  2234. PackStrToAttr(pAttr+cAttr, SCRIPTPATH, pPackageDetail->pInstallInfo->pszScriptPath);
  2235. cAttr++;
  2236. }
  2237. if (pPackageDetail->pInstallInfo->pszSetupCommand) {
  2238. PackStrToAttr(pAttr+cAttr, SETUPCOMMAND, pPackageDetail->pInstallInfo->pszSetupCommand);
  2239. cAttr++;
  2240. }
  2241. if (pPackageDetail->pInstallInfo->pszUrl) {
  2242. PackStrToAttr(pAttr+cAttr, HELPURL, pPackageDetail->pInstallInfo->pszUrl);
  2243. cAttr++;
  2244. }
  2245. //
  2246. // Store the current USN
  2247. //
  2248. GetCurrentUsn(szUsn);
  2249. PackStrToAttr(pAttr+cAttr, PKGUSN, szUsn);
  2250. cAttr++;
  2251. // package flags
  2252. PackDWToAttr(pAttr+cAttr, PACKAGEFLAGS, pPackageDetail->pInstallInfo->dwActFlags);
  2253. cAttr++;
  2254. // product code, different from pkg guid
  2255. PackGUIDToAttr(pAttr+cAttr, PRODUCTCODE, &(pPackageDetail->pInstallInfo->ProductCode));
  2256. cAttr++;
  2257. // Mvipc
  2258. PackGUIDToAttr(pAttr+cAttr, MVIPC, &(pPackageDetail->pInstallInfo->Mvipc));
  2259. cAttr++;
  2260. // Hi Version of the package
  2261. PackDWToAttr(pAttr+cAttr, VERSIONHI, pPackageDetail->pInstallInfo->dwVersionHi);
  2262. cAttr++;
  2263. // Low Version of the package
  2264. PackDWToAttr(pAttr+cAttr, VERSIONLO, pPackageDetail->pInstallInfo->dwVersionLo);
  2265. cAttr++;
  2266. // Revision
  2267. PackDWToAttr(pAttr+cAttr, REVISION, pPackageDetail->pInstallInfo->dwRevision);
  2268. cAttr++;
  2269. // scriptsize
  2270. PackDWToAttr(pAttr+cAttr, SCRIPTSIZE, pPackageDetail->pInstallInfo->cScriptLen);
  2271. cAttr++;
  2272. // uilevel
  2273. PackDWToAttr (pAttr+cAttr, UILEVEL, (DWORD)pPackageDetail->pInstallInfo->InstallUiLevel);
  2274. cAttr++;
  2275. // adding cUpgrade number of Classstore/PackageGuid combinations
  2276. if (pPackageDetail->pInstallInfo->cUpgrades)
  2277. {
  2278. WCHAR szPackageGuid[_MAX_PATH];
  2279. rpszUpgrades = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*pPackageDetail->pInstallInfo->cUpgrades);
  2280. if (!rpszUpgrades)
  2281. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2282. for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++)
  2283. {
  2284. UINT len = wcslen(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore);
  2285. rpszUpgrades[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *(36+PKG_UPG_DELIM1_LEN+len+PKG_UPG_DELIM2_LEN+2+2));
  2286. // Guid size+::+length++:+flagDigit+2
  2287. if (!rpszUpgrades[count])
  2288. {
  2289. FREEARR(rpszUpgrades, count);
  2290. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2291. }
  2292. StringFromGUID(pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].PackageGuid,
  2293. szPackageGuid);
  2294. wsprintf(rpszUpgrades[count], L"%s%s%s%s%02x",
  2295. pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].szClassStore,
  2296. PKG_UPG_DELIMITER1,
  2297. szPackageGuid,
  2298. PKG_UPG_DELIMITER2,
  2299. pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag%16);
  2300. }
  2301. PackStrArrToAttr(pAttr+cAttr, UPGRADESPACKAGES, rpszUpgrades,
  2302. pPackageDetail->pInstallInfo->cUpgrades);
  2303. cAttr++;
  2304. }
  2305. // Fill in the source list
  2306. // Maintain the serial number associated with the sources. Order matters!!
  2307. if (pPackageDetail->cSources)
  2308. {
  2309. rpszSources = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*(pPackageDetail->cSources));
  2310. if (!rpszSources)
  2311. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2312. for (count = 0; count < (pPackageDetail->cSources); count++)
  2313. {
  2314. rpszSources[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(wcslen(pPackageDetail->pszSourceList[count])+
  2315. 1+1+NumDigits10(pPackageDetail->cSources)));
  2316. if (!rpszSources[count])
  2317. {
  2318. FREEARR(rpszSources, count);
  2319. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  2320. }
  2321. wsprintf(rpszSources[count], L"%d:%s", count, pPackageDetail->pszSourceList[count]);
  2322. }
  2323. PackStrArrToAttr(pAttr+cAttr, MSIFILELIST, rpszSources, pPackageDetail->cSources);
  2324. cAttr++;
  2325. }
  2326. // fill in the categories
  2327. // Add the package Categories
  2328. if (pPackageDetail->cCategories)
  2329. {
  2330. pszGuid4 = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->cCategories) * sizeof(LPOLESTR));
  2331. if (!pszGuid4)
  2332. {
  2333. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2334. }
  2335. for (count = 0; (count < pPackageDetail->cCategories); count++)
  2336. {
  2337. pszGuid4[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
  2338. if (!pszGuid4[count])
  2339. {
  2340. FREEARR(pszGuid4, count);
  2341. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  2342. }
  2343. StringFromGUID((pPackageDetail->rpCategory)[count], pszGuid4[count]);
  2344. }
  2345. PackStrArrToAttr(pAttr+cAttr, PKGCATEGORYLIST, pszGuid4, pPackageDetail->cCategories);
  2346. cAttr++;
  2347. }
  2348. // fill in the vendor
  2349. // Publisher
  2350. if (pPackageDetail->pszPublisher)
  2351. {
  2352. PackStrToAttr(pAttr+cAttr, PUBLISHER, pPackageDetail->pszPublisher);
  2353. cAttr++;
  2354. }
  2355. /*
  2356. //
  2357. // Store the script in the directory
  2358. //
  2359. if ((pPackageDetail->pInstallInfo->dwActFlags & SCRIPT_IN_DIRECTORY) &&
  2360. (pPackageDetail->pInstallInfo->cScriptLen))
  2361. {
  2362. if ((pPackageDetail->pInstallInfo->cScriptLen) &&
  2363. (!IsValidReadPtrIn(pPackageDetail->pInstallInfo->pScript, pPackageDetail->pInstallInfo->cScriptLen)))
  2364. return E_INVALIDARG;
  2365. if (pPackageDetail->pInstallInfo->cScriptLen)
  2366. {
  2367. PackBinToAttr(pAttr+cAttr, PKGSCRIPT, pPackageDetail->pInstallInfo->pScript,
  2368. pPackageDetail->pInstallInfo->cScriptLen);
  2369. cAttr++;
  2370. }
  2371. }
  2372. */
  2373. hr = ADSICreateDSObject(m_ADsPackageContainer, szRDN, pAttr, cAttr);
  2374. ERROR_ON_FAILURE(hr);
  2375. memset(pPkgGuid, 0, sizeof(GUID));
  2376. // memcpy(pPkgGuid, &PackageGuidId, sizeof(GUID));
  2377. hr = GetPackageGuid(szRDN, pPkgGuid);
  2378. ERROR_ON_FAILURE(hr);
  2379. fPackageCreated = TRUE;
  2380. if (pPackageDetail->pActInfo)
  2381. {
  2382. for (count = 0; count < pPackageDetail->pActInfo->cClasses; count++) {
  2383. hr = NewClass((pPackageDetail->pActInfo->pClasses)+count);
  2384. ERROR_ON_FAILURE(hr);
  2385. }
  2386. }
  2387. if (!(pPackageDetail->pInstallInfo->dwActFlags & ACTFLG_Uninstall) &&
  2388. !(pPackageDetail->pInstallInfo->dwActFlags & ACTFLG_Orphan))
  2389. {
  2390. if (pPackageDetail->pInstallInfo->cUpgrades)
  2391. {
  2392. //
  2393. // Need to fixup the other packages that this package upgrades
  2394. //
  2395. for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++)
  2396. {
  2397. if ((pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_Uninstall) ||
  2398. (pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_NoUninstall))
  2399. {
  2400. DWORD Flags = 0;
  2401. if (pPackageDetail->pInstallInfo->prgUpgradeInfoList[count].Flag & UPGFLG_Enforced)
  2402. Flags = UPGFLG_Enforced;
  2403. }
  2404. }
  2405. for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++)
  2406. CoTaskMemFree(rpszUpgrades[count]);
  2407. CoTaskMemFree(rpszUpgrades);
  2408. }
  2409. }
  2410. if (SUCCEEDED(hr))
  2411. {
  2412. //
  2413. // Update Store Usn
  2414. //
  2415. UpdateStoreUsn(m_ADsContainer, szUsn);
  2416. }
  2417. Error_Cleanup:
  2418. for (count = 0; count < cAttr; count++)
  2419. FreeAttr(pAttr[count]);
  2420. if (pszGuid1) {
  2421. for (count = 0; (count < pPackageDetail->pActInfo->cClasses); count++)
  2422. CoTaskMemFree(pszGuid1[count]);
  2423. CoTaskMemFree(pszGuid1);
  2424. }
  2425. if (pszGuid2) {
  2426. for (count = 0; (count < (pPackageDetail->pActInfo->cInterfaces)); count++)
  2427. CoTaskMemFree(pszGuid2[count]);
  2428. CoTaskMemFree(pszGuid2);
  2429. }
  2430. if (pszGuid3) {
  2431. for (count = 0; (count < (pPackageDetail->pActInfo->cTypeLib)); count++)
  2432. CoTaskMemFree(pszGuid3[count]);
  2433. CoTaskMemFree(pszGuid3);
  2434. }
  2435. if (pszGuid4) {
  2436. for (count = 0; (count < pPackageDetail->cCategories); count++)
  2437. CoTaskMemFree(pszGuid4[count]);
  2438. CoTaskMemFree(pszGuid4);
  2439. }
  2440. if (pszFileExt) {
  2441. for (count = 0; (count < pPackageDetail->pActInfo->cShellFileExt); count++)
  2442. CoTaskMemFree(pszFileExt[count]);
  2443. CoTaskMemFree(pszFileExt);
  2444. }
  2445. if (pdwArch) {
  2446. CoTaskMemFree(pdwArch);
  2447. }
  2448. if (rpszSources)
  2449. {
  2450. for (count = 0; (count < pPackageDetail->cSources); count++)
  2451. CoTaskMemFree(rpszSources[count]);
  2452. CoTaskMemFree(rpszSources);
  2453. }
  2454. //
  2455. // On failure, the package should be removed from the ds if we
  2456. // created it there.
  2457. //
  2458. if (FAILED(hr) && (fPackageCreated))
  2459. {
  2460. HRESULT hrDeleted;
  2461. LPWSTR wszPackageFullPath;
  2462. //
  2463. // Need to get a full path to the package in order to delete it.
  2464. //
  2465. hrDeleted = BuildADsPathFromParent(m_szPackageName, szRDN, &wszPackageFullPath);
  2466. ASSERT(SUCCEEDED(hrDeleted));
  2467. CSDBGPrint((L"AddPackage failed, attempting to remove deleted package with path %s\n", wszPackageFullPath));
  2468. hrDeleted = DeletePackage(wszPackageFullPath);
  2469. CSDBGPrint((L"DeletePackage returned %x\n", hrDeleted));
  2470. //
  2471. // Free the full path
  2472. //
  2473. CoTaskMemFree(wszPackageFullPath);
  2474. }
  2475. return RemapErrorCode(hr, m_szContainerName);
  2476. }
  2477. //+
  2478. //
  2479. // Cleanup old packages from Class Store based on lastChangeTime
  2480. //
  2481. HRESULT CClassContainer::Cleanup (
  2482. FILETIME *pTimeBefore
  2483. )
  2484. {
  2485. //
  2486. // Delete all packages marked as "Uninstall"
  2487. // OR "Orphan" and are older than the time given
  2488. //
  2489. ULONG cRowsFetched = 0;
  2490. ADS_SEARCH_HANDLE hADsSearchHandle = NULL;
  2491. WCHAR szFilter[_MAX_PATH], szRDN[_MAX_PATH];
  2492. HRESULT hr = S_OK;
  2493. ADS_ATTR_INFO pAttr;
  2494. SYSTEMTIME SystemTime;
  2495. ADS_SEARCH_COLUMN column;
  2496. DWORD dwPackageFlags;
  2497. LPOLESTR pszPackageId = NULL;
  2498. if ((!pTimeBefore) ||
  2499. !IsValidReadPtrIn(pTimeBefore, sizeof(FILETIME)))
  2500. return E_INVALIDARG;
  2501. FileTimeToSystemTime(
  2502. (CONST FILETIME *) pTimeBefore,
  2503. &SystemTime);
  2504. wsprintf (szFilter,
  2505. L"(%s<=%04d%02d%02d%02d%02d%02d)",
  2506. PKGUSN,
  2507. SystemTime.wYear,
  2508. SystemTime.wMonth,
  2509. SystemTime.wDay,
  2510. SystemTime.wHour,
  2511. SystemTime.wMinute,
  2512. SystemTime.wSecond);
  2513. // execute the search and keep the handle returned.
  2514. hr = ADSIExecuteSearch(m_ADsPackageContainer, szFilter, pszDeleteAttrNames,
  2515. cDeleteAttr, &hADsSearchHandle);
  2516. hr = ADSIGetFirstRow(m_ADsPackageContainer, hADsSearchHandle);
  2517. while (TRUE)
  2518. {
  2519. if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
  2520. break;
  2521. dwPackageFlags = 0;
  2522. // Get the Package State
  2523. hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, PACKAGEFLAGS, &column);
  2524. if (SUCCEEDED(hr))
  2525. {
  2526. UnpackDWFrom(column, &dwPackageFlags);
  2527. ADSIFreeColumn(m_ADsPackageContainer, &column);
  2528. }
  2529. //
  2530. // Check flag values to see if this package is Orphaned or Uninstalled
  2531. //
  2532. if ((dwPackageFlags & ACTFLG_Orphan) || (dwPackageFlags & ACTFLG_Uninstall))
  2533. {
  2534. hr = ADSIGetColumn(m_ADsPackageContainer, hADsSearchHandle, OBJECTDN, &column);
  2535. if (SUCCEEDED(hr))
  2536. {
  2537. WCHAR * szDN = NULL;
  2538. UnpackStrFrom(column, &szDN);
  2539. hr = DeletePackage(szDN);
  2540. ADSIFreeColumn(m_ADsPackageContainer, &column);
  2541. ERROR_ON_FAILURE(hr);
  2542. }
  2543. }
  2544. hr = ADSIGetNextRow(m_ADsPackageContainer, hADsSearchHandle);
  2545. }
  2546. Error_Cleanup:
  2547. if (hADsSearchHandle)
  2548. ADSICloseSearchHandle(m_ADsPackageContainer, hADsSearchHandle);
  2549. return RemapErrorCode(hr, m_szContainerName);
  2550. }