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.

1454 lines
40 KiB

  1. //RETURN
  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 "csadm.hxx"
  16. void GetCurrentUsn(CSUSN *pStoreUsn);
  17. //----------------------------------------------------------
  18. // Implementation for CClassContainer
  19. //----------------------------------------------------------
  20. //
  21. CClassContainer::CClassContainer()
  22. {
  23. m_fOpen = FALSE;
  24. m_ADsContainer = NULL;
  25. m_pADsClassStore = NULL;
  26. m_ADsClassContainer = NULL;
  27. m_ADsPackageContainer = NULL;
  28. m_ADsCategoryContainer = NULL;
  29. m_uRefs = 1;
  30. StartQuery(&m_pIDBCreateCommand);
  31. }
  32. //
  33. // CClassContainer implementation
  34. //
  35. CClassContainer::CClassContainer(LPOLESTR szStoreName,
  36. HRESULT *phr)
  37. {
  38. IADs *pADs = NULL;
  39. LPOLESTR pszName = NULL;
  40. DWORD dwStoreVersion = 0;
  41. *phr = S_OK;
  42. m_fOpen = FALSE;
  43. m_ADsContainer = NULL;
  44. m_pADsClassStore = NULL;
  45. m_ADsClassContainer = NULL;
  46. m_ADsPackageContainer = NULL;
  47. m_ADsCategoryContainer = NULL;
  48. //
  49. // For every interface pointer, we create a separate Query session
  50. //
  51. StartQuery(&m_pIDBCreateCommand);
  52. // Bind to a Class Store Container Object
  53. // Cache the interface pointer
  54. //
  55. wcscpy (m_szContainerName, szStoreName);
  56. *phr = ADsGetObject(
  57. szStoreName,
  58. IID_IADsContainer,
  59. (void **)&m_ADsContainer
  60. );
  61. if (!SUCCEEDED(*phr))
  62. return;
  63. //
  64. // Check the Schema Version of this container
  65. //
  66. *phr = m_ADsContainer->QueryInterface (IID_IADs, (void **)&m_pADsClassStore);
  67. if (!SUCCEEDED(*phr))
  68. return;
  69. *phr = GetPropertyDW (m_pADsClassStore, STOREVERSION, &dwStoreVersion);
  70. if ((!SUCCEEDED(*phr)) ||
  71. (dwStoreVersion != SCHEMA_VERSION_NUMBER))
  72. {
  73. *phr = CS_E_INVALID_VERSION;
  74. return;
  75. }
  76. //
  77. // Bind to the class container Object
  78. // Cache the interface pointer
  79. //
  80. m_ADsClassContainer = NULL;
  81. *phr = m_ADsContainer->GetObject(
  82. NULL,
  83. CLASSCONTAINERNAME,
  84. (IDispatch **)&pADs
  85. );
  86. if (!SUCCEEDED(*phr))
  87. return;
  88. pADs->QueryInterface(IID_IADsContainer,
  89. (void **)&m_ADsClassContainer
  90. );
  91. *phr = pADs->get_ADsPath(&pszName);
  92. wcscpy (m_szClassName, pszName);
  93. SysFreeString(pszName);
  94. pADs->Release();
  95. pADs = NULL;
  96. if (!SUCCEEDED(*phr))
  97. return;
  98. //
  99. // Bind to the Package container Object
  100. // Cache the interface pointer
  101. //
  102. m_ADsPackageContainer = NULL;
  103. *phr = m_ADsContainer->GetObject(
  104. NULL,
  105. PACKAGECONTAINERNAME,
  106. (IDispatch **)&pADs);
  107. if (!SUCCEEDED(*phr))
  108. return;
  109. pADs->QueryInterface(IID_IADsContainer,
  110. (void **)&m_ADsPackageContainer
  111. );
  112. *phr = pADs->get_ADsPath(&pszName);
  113. wcscpy (m_szPackageName, pszName);
  114. SysFreeString(pszName);
  115. pADs->Release();
  116. pADs = NULL;
  117. if (!SUCCEEDED(*phr))
  118. return;
  119. //
  120. // Bind to the category container Object
  121. // Cache the interface pointer
  122. //
  123. m_ADsCategoryContainer = NULL;
  124. *phr = m_ADsContainer->GetObject(
  125. NULL,
  126. CATEGORYCONTAINERNAME,
  127. (IDispatch **)&pADs);
  128. if (!SUCCEEDED(*phr))
  129. return;
  130. pADs->QueryInterface(IID_IADsContainer,
  131. (void **)&m_ADsCategoryContainer
  132. );
  133. pADs->Release();
  134. pADs = NULL;
  135. m_fOpen = TRUE;
  136. m_uRefs = 1;
  137. return;
  138. }
  139. CClassContainer::~CClassContainer(void)
  140. {
  141. UINT i;
  142. EndQuery(m_pIDBCreateCommand);
  143. m_pIDBCreateCommand = NULL;
  144. if (m_fOpen)
  145. {
  146. m_fOpen = FALSE;
  147. }
  148. if (m_ADsClassContainer)
  149. {
  150. m_ADsClassContainer->Release();
  151. m_ADsClassContainer = NULL;
  152. }
  153. if (m_ADsPackageContainer)
  154. {
  155. m_ADsPackageContainer->Release();
  156. m_ADsPackageContainer = NULL;
  157. }
  158. if (m_ADsCategoryContainer)
  159. {
  160. m_ADsCategoryContainer->Release();
  161. m_ADsCategoryContainer = NULL;
  162. }
  163. if (m_ADsContainer)
  164. {
  165. m_ADsContainer->Release();
  166. m_ADsContainer = NULL;
  167. }
  168. if (m_pADsClassStore)
  169. {
  170. m_pADsClassStore->Release();
  171. m_pADsClassStore = NULL;
  172. }
  173. }
  174. //
  175. // Removing a class from the database
  176. //
  177. HRESULT CClassContainer::DeleteClass (LPOLESTR szClsid)
  178. {
  179. WCHAR szName[_MAX_PATH];
  180. HRESULT hr = S_OK;
  181. IADs *pADs = NULL;
  182. DWORD refcount = 0;
  183. if (!m_fOpen)
  184. return E_FAIL;
  185. wsprintf(szName, L"CN=%s", szClsid);
  186. hr = m_ADsClassContainer->GetObject(NULL, szName, (IDispatch **)&pADs);
  187. if (SUCCEEDED(hr))
  188. hr = GetPropertyDW(pADs, CLASSREFCOUNTER, &refcount);
  189. if (refcount <= 1)
  190. hr = m_ADsClassContainer->Delete(CLASS_CS_CLASS, szName);
  191. else {
  192. refcount--;
  193. hr = SetPropertyDW(pADs, CLASSREFCOUNTER, refcount);
  194. if (SUCCEEDED(hr))
  195. hr = StoreIt(pADs);
  196. }
  197. if (pADs)
  198. pADs->Release();
  199. return hr;
  200. }
  201. extern LPOLESTR szPackageInfoColumns;
  202. HRESULT CClassContainer::EnumPackages(
  203. LPOLESTR pszFileExt,
  204. GUID *pCategory,
  205. DWORD dwAppFlags,
  206. DWORD *pdwLocale,
  207. CSPLATFORM *pPlatform,
  208. IEnumPackage **ppIEnumPackage
  209. )
  210. {
  211. HRESULT hr = S_OK;
  212. CEnumPackage *pEnum = NULL;
  213. WCHAR szCommand[1000], szQry[1000];
  214. if (pszFileExt && IsBadStringPtr(pszFileExt, _MAX_PATH))
  215. return E_INVALIDARG;
  216. if (pCategory && !IsValidReadPtrIn(pCategory, sizeof(GUID)))
  217. return E_INVALIDARG;
  218. if (!IsValidPtrOut(ppIEnumPackage, sizeof(IEnumPackage *)))
  219. return E_INVALIDARG;
  220. *ppIEnumPackage = NULL;
  221. pEnum = new CEnumPackage;
  222. if(NULL == pEnum)
  223. return E_OUTOFMEMORY;
  224. //
  225. // Create a CommandText
  226. //
  227. wsprintf(szCommand, L"<%s>;(& (objectClass=packageRegistration) ", m_szPackageName);
  228. if (pszFileExt)
  229. {
  230. wsprintf(szQry, L"(%s=%s*) ", PKGFILEEXTNLIST, pszFileExt);
  231. wcscat(szCommand, szQry);
  232. }
  233. if (pCategory)
  234. {
  235. STRINGGUID szCat;
  236. StringFromGUID (*pCategory, szCat);
  237. wsprintf(szQry, L"(%s=%s) ", PKGCATEGORYLIST, szCat);
  238. wcscat(szCommand, szQry);
  239. }
  240. wcscat(szCommand, L");");
  241. wsprintf(szQry, L" %s", szPackageInfoColumns);
  242. wcscat(szCommand, szQry);
  243. hr = pEnum->Initialize(szCommand, dwAppFlags, pdwLocale, pPlatform);
  244. if (FAILED(hr)) {
  245. delete pEnum;
  246. return hr;
  247. }
  248. hr = pEnum->QueryInterface(IID_IEnumPackage, (void**)ppIEnumPackage);
  249. return hr;
  250. }
  251. // GetPackageDetails
  252. // pszPackageName : name of the package to be got.
  253. // pInstallInfo : InstallInfo to be filled in. ignored if NULL.
  254. // pPlatformInfo : PlatformInfo to be filled in. ignored if NULL.
  255. // both can be sent in as NULL to check whether package exists or not.
  256. HRESULT CClassContainer::GetPackageDetails (
  257. LPOLESTR pszPackageName,
  258. PACKAGEDETAIL *pPackageDetail)
  259. {
  260. HRESULT hr = S_OK;
  261. IADs *pPackageADs = NULL;
  262. WCHAR szRdn [_MAX_PATH];
  263. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  264. return E_INVALIDARG;
  265. wcscpy (szRdn, L"CN=");
  266. wcscat (szRdn, pszPackageName);
  267. hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pPackageADs);
  268. if (!SUCCEEDED(hr))
  269. return CS_E_PACKAGE_NOTFOUND;
  270. hr = GetPackageDetail (pPackageADs, pPackageDetail);
  271. return hr;
  272. }
  273. HRESULT CClassContainer::ChangePackageProperties(
  274. LPOLESTR pszPackageName,
  275. LPOLESTR pszNewName,
  276. DWORD *pdwFlags,
  277. LPOLESTR pszUrl,
  278. LPOLESTR pszScriptPath,
  279. DWORD *pInstallUiLevel
  280. )
  281. {
  282. HRESULT hr = S_OK;
  283. IADs *pPackageADs = NULL;
  284. WCHAR szRdn [_MAX_PATH];
  285. WCHAR szNewRdn [_MAX_PATH];
  286. LPOLESTR pszPackageDN;
  287. CSUSN Usn;
  288. if ((!pszPackageName) || IsBadStringPtr(pszPackageName, _MAX_PATH))
  289. return E_INVALIDARG;
  290. wcscpy (szRdn, L"CN=");
  291. wcscat (szRdn, pszPackageName);
  292. if (pszNewName)
  293. {
  294. //
  295. // rename package
  296. //
  297. if (IsBadStringPtr(pszNewName, _MAX_PATH))
  298. return E_INVALIDARG;
  299. //
  300. // Check to see if any other change is requested.
  301. //
  302. if (pszScriptPath ||
  303. pszUrl ||
  304. pdwFlags)
  305. return E_INVALIDARG;
  306. BuildADsPathFromParent (m_szPackageName, szRdn, &pszPackageDN);
  307. wcscpy (szNewRdn, L"CN=");
  308. wcscat (szNewRdn, pszNewName);
  309. hr = m_ADsPackageContainer->MoveHere(pszPackageDN, szNewRdn, (IDispatch **)&pPackageADs);
  310. FreeADsMem(pszPackageDN);
  311. if (SUCCEEDED(hr))
  312. pPackageADs->Release();
  313. else
  314. CSDbgPrint(("Error in MoveHere. hr=0x%x\n", hr));
  315. return hr;
  316. }
  317. //
  318. // No rename.
  319. // Just change some properties.
  320. //
  321. hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pPackageADs);
  322. if (!SUCCEEDED(hr))
  323. return CS_E_PACKAGE_NOTFOUND;
  324. //
  325. // Update the TimeStamp
  326. //
  327. GetCurrentUsn(&Usn);
  328. hr = UsnUpd(pPackageADs, PKGUSN, &Usn);
  329. ERROR_ON_FAILURE(hr);
  330. //
  331. // Change Package Flags
  332. //
  333. if (pdwFlags)
  334. {
  335. hr = SetPropertyDW (pPackageADs, PACKAGEFLAGS, *pdwFlags);
  336. ERROR_ON_FAILURE(hr);
  337. }
  338. //
  339. // Change Package Script
  340. //
  341. if (pszScriptPath)
  342. {
  343. hr = SetProperty(pPackageADs, SCRIPTPATH, pszScriptPath);
  344. ERROR_ON_FAILURE(hr);
  345. }
  346. //
  347. // Change Package Help URL
  348. //
  349. if (pszUrl)
  350. {
  351. hr = SetProperty(pPackageADs, HELPURL, pszUrl);
  352. ERROR_ON_FAILURE(hr);
  353. }
  354. //
  355. // Change UI Level
  356. //
  357. if (pInstallUiLevel)
  358. {
  359. hr = SetPropertyDW (pPackageADs, UILEVEL, *pInstallUiLevel);
  360. ERROR_ON_FAILURE(hr);
  361. }
  362. hr = StoreIt(pPackageADs);
  363. Error_Cleanup:
  364. pPackageADs->Release();
  365. return hr;
  366. }
  367. HRESULT CClassContainer::ChangePackageCategories(
  368. LPOLESTR pszPackageName,
  369. UINT cCategories,
  370. GUID *rpCategory
  371. )
  372. {
  373. //
  374. // Does not change USN
  375. //
  376. HRESULT hr = S_OK;
  377. IADs *pPackageADs = NULL;
  378. WCHAR szRdn [_MAX_PATH];
  379. LPOLESTR *pszGuid = NULL;
  380. CSUSN Usn;
  381. UINT count;
  382. wcscpy (szRdn, L"CN=");
  383. wcscat (szRdn, pszPackageName);
  384. if ((!cCategories) ||
  385. (!rpCategory) ||
  386. (!IsValidReadPtrIn(rpCategory, sizeof(GUID) * cCategories)))
  387. return E_INVALIDARG;
  388. hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pPackageADs);
  389. if (!SUCCEEDED(hr))
  390. return CS_E_PACKAGE_NOTFOUND;
  391. // fill in the categories
  392. pszGuid = (LPOLESTR *)CoTaskMemAlloc(cCategories * sizeof(LPOLESTR));
  393. if (!pszGuid)
  394. {
  395. hr = E_OUTOFMEMORY;
  396. ERROR_ON_FAILURE(hr);
  397. }
  398. for (count = 0; (count < cCategories); count++)
  399. {
  400. pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
  401. {
  402. hr = E_OUTOFMEMORY;
  403. ERROR_ON_FAILURE(hr);
  404. }
  405. StringFromGUID(rpCategory[count], pszGuid[count]);
  406. }
  407. hr = SetPropertyList(pPackageADs, PKGCATEGORYLIST, cCategories,
  408. pszGuid);
  409. ERROR_ON_FAILURE(hr);
  410. for (count = 0; (count < cCategories); count++)
  411. CoTaskMemFree(pszGuid[count]);
  412. CoTaskMemFree(pszGuid);
  413. hr = StoreIt(pPackageADs);
  414. Error_Cleanup:
  415. pPackageADs->Release();
  416. return hr;
  417. }
  418. HRESULT CClassContainer::SetPriorityByFileExt(
  419. LPOLESTR pszPackageName,
  420. LPOLESTR pszFileExt,
  421. UINT Priority
  422. )
  423. {
  424. //
  425. // Does not change USN
  426. //
  427. HRESULT hr = S_OK;
  428. IADs *pPackageADs = NULL;
  429. WCHAR szRdn [_MAX_PATH];
  430. LPOLESTR *prgFileExt = NULL;
  431. ULONG cShellFileExt;
  432. UINT i;
  433. wcscpy (szRdn, L"CN=");
  434. wcscat (szRdn, pszPackageName);
  435. hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pPackageADs);
  436. if (!SUCCEEDED(hr))
  437. return CS_E_PACKAGE_NOTFOUND;
  438. hr = GetPropertyListAlloc (pPackageADs, PKGFILEEXTNLIST,
  439. &cShellFileExt,
  440. &prgFileExt);
  441. for (i=0; i < cShellFileExt; ++i)
  442. {
  443. if (wcsncmp(prgFileExt[i], pszFileExt, wcslen(pszFileExt)) == 0)
  444. {
  445. wsprintf(prgFileExt[i], L"%s:%2d",
  446. pszFileExt,
  447. Priority);
  448. }
  449. }
  450. if (i == cShellFileExt)
  451. {
  452. ERROR_ON_FAILURE(CS_E_PACKAGE_NOTFOUND);
  453. }
  454. hr = SetPropertyList(pPackageADs, PKGFILEEXTNLIST, cShellFileExt, prgFileExt);
  455. hr = StoreIt(pPackageADs);
  456. Error_Cleanup:
  457. pPackageADs->Release();
  458. return hr;
  459. }
  460. extern LPOLESTR szAppCategoryColumns;
  461. HRESULT CClassContainer::GetAppCategories (
  462. LCID Locale,
  463. APPCATEGORYINFOLIST *pAppCategoryList
  464. )
  465. {
  466. HRESULT hr = S_OK;
  467. WCHAR szCommand[1000], szQry[1000];
  468. WCHAR szRootPath[_MAX_PATH],
  469. szAppCategoryContainer[_MAX_PATH];
  470. IRowset * pIRow = NULL;
  471. HACCESSOR HAcc;
  472. IAccessor * pIAccessor = NULL;
  473. IDBCreateCommand * pIDBCreateCommand = NULL;
  474. LPOLESTR ** ppszDesc = NULL;
  475. DWORD cgot = 0;
  476. if (!IsValidPtrOut(pAppCategoryList, sizeof(APPCATEGORYINFOLIST)))
  477. return E_INVALIDARG;
  478. hr = GetRootPath(szRootPath);
  479. wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX,
  480. APPCATEGORYCONTAINERNAME, szRootPath+wcslen(LDAPPREFIX));
  481. wsprintf(szCommand, L"<%s>; (objectClass=categoryRegistration); %s", szAppCategoryContainer,
  482. szAppCategoryColumns);
  483. hr = StartQuery(&(pIDBCreateCommand));
  484. RETURN_ON_FAILURE(hr);
  485. hr = ExecuteQuery (pIDBCreateCommand,
  486. szCommand,
  487. APPCATEGORY_COLUMN_COUNT,
  488. NULL,
  489. &HAcc,
  490. &pIAccessor,
  491. &pIRow
  492. );
  493. RETURN_ON_FAILURE(hr);
  494. pAppCategoryList->cCategory = 500;
  495. // upper limit presently.
  496. hr = FetchCategory(pIRow,
  497. HAcc,
  498. (pAppCategoryList->cCategory),
  499. &cgot,
  500. &(pAppCategoryList->pCategoryInfo),
  501. Locale);
  502. pAppCategoryList->cCategory = cgot;
  503. CloseQuery(pIAccessor,
  504. HAcc,
  505. pIRow);
  506. EndQuery(pIDBCreateCommand);
  507. return hr;
  508. }
  509. HRESULT CClassContainer::RegisterAppCategory (
  510. APPCATEGORYINFO *pAppCategory
  511. )
  512. {
  513. WCHAR szRootPath[_MAX_PATH], *localedescription = NULL,
  514. szAppCategoryContainer[_MAX_PATH], szRDN[_MAX_PATH];
  515. HRESULT hr = S_OK;
  516. IADsContainer *pADsContainer = NULL;
  517. IADs *pADs = NULL;
  518. IDispatch *pUnknown = NULL;
  519. ULONG i, j, cdesc, posn;
  520. LPOLESTR *pszDescExisting = NULL, *pszDesc = NULL;
  521. if (!IsValidReadPtrIn(pAppCategory, sizeof(APPCATEGORYINFO)))
  522. return E_INVALIDARG;
  523. if (IsBadStringPtr(pAppCategory->pszDescription, _MAX_PATH))
  524. return E_INVALIDARG;
  525. if (IsNullGuid(pAppCategory->AppCategoryId))
  526. return E_INVALIDARG;
  527. hr = GetRootPath(szRootPath);
  528. // Bind to a AppCategory container
  529. wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX,
  530. APPCATEGORYCONTAINERNAME, szRootPath+wcslen(LDAPPREFIX));
  531. hr = ADsGetObject(
  532. szAppCategoryContainer,
  533. IID_IADsContainer,
  534. (void **)&pADsContainer
  535. );
  536. RETURN_ON_FAILURE(hr);
  537. RdnFromGUID(pAppCategory->AppCategoryId, szRDN);
  538. localedescription = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*(128+16));
  539. wsprintf(localedescription, L"%x %s %s", pAppCategory->Locale, CATSEPERATOR,
  540. pAppCategory->pszDescription);
  541. hr = pADsContainer->GetObject(NULL, szRDN, (IDispatch **)&pADs);
  542. if (SUCCEEDED(hr))
  543. {
  544. hr = GetPropertyListAlloc (pADs, LOCALEDESCRIPTION, &cdesc, &pszDescExisting);
  545. ERROR_ON_FAILURE(hr);
  546. // Existing list of descriptions
  547. pszDesc = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*(cdesc+1));
  548. if ((cdesc) && (!pszDesc)) {
  549. hr = E_OUTOFMEMORY;
  550. ERROR_ON_FAILURE(hr);
  551. }
  552. for (j = 0; j < cdesc; j++)
  553. pszDesc[j] = pszDescExisting[j];
  554. if (!(posn = FindDescription(pszDescExisting, cdesc, &(pAppCategory->Locale), NULL, 0)))
  555. {
  556. // if no description exists for the lcid.
  557. pszDesc[cdesc] = localedescription;
  558. cdesc++;
  559. }
  560. else
  561. { // overwrite the old value
  562. CoTaskMemFree(pszDesc[posn-1]);
  563. pszDesc[posn-1] = localedescription;
  564. }
  565. }
  566. else
  567. {
  568. hr = pADsContainer->Create(
  569. CLASS_CS_CATEGORY,
  570. szRDN,
  571. &pUnknown
  572. );
  573. ERROR_ON_FAILURE(hr);
  574. pszDesc = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR));
  575. if (!pszDesc) {
  576. hr = E_OUTOFMEMORY;
  577. ERROR_ON_FAILURE(hr);
  578. }
  579. cdesc = 1;
  580. pszDesc[0] = localedescription;
  581. hr = pUnknown->QueryInterface(IID_IADs, (void **)&pADs);
  582. RETURN_ON_FAILURE(hr);
  583. pUnknown->Release();
  584. }
  585. hr = SetPropertyGuid(pADs, CATEGORYCATID, pAppCategory->AppCategoryId);
  586. ERROR_ON_FAILURE(hr);
  587. hr = SetPropertyList(pADs, LOCALEDESCRIPTION, cdesc, pszDesc);
  588. for (j = 0; j < cdesc; j++)
  589. CoTaskMemFree(pszDesc[j]);
  590. CoTaskMemFree(pszDesc);
  591. ERROR_ON_FAILURE(hr);
  592. hr = StoreIt(pADs);
  593. ERROR_ON_FAILURE(hr);
  594. Error_Cleanup:
  595. if (pADs)
  596. pADs->Release();
  597. if (pADsContainer)
  598. pADsContainer->Release();
  599. // Add this category.
  600. return hr;
  601. }
  602. HRESULT CClassContainer::UnregisterAppCategory (
  603. GUID *pAppCategoryId
  604. )
  605. {
  606. WCHAR szRootPath[_MAX_PATH], szRDN[_MAX_PATH],
  607. szAppCategoryContainer[_MAX_PATH];
  608. HRESULT hr = S_OK;
  609. IADsContainer *pADsContainer = NULL;
  610. if (!IsValidReadPtrIn(pAppCategoryId, sizeof(GUID)))
  611. return E_INVALIDARG;
  612. hr = GetRootPath(szRootPath);
  613. // Bind to a AppCategory container
  614. wsprintf(szAppCategoryContainer, L"%s%s%s", LDAPPREFIX,
  615. APPCATEGORYCONTAINERNAME, szRootPath+wcslen(LDAPPREFIX));
  616. hr = ADsGetObject(
  617. szAppCategoryContainer,
  618. IID_IADsContainer,
  619. (void **)&pADsContainer
  620. );
  621. RETURN_ON_FAILURE(hr);
  622. RdnFromGUID(*pAppCategoryId, szRDN);
  623. hr = pADsContainer->Delete(CLASS_CS_CATEGORY, szRDN);
  624. pADsContainer->Release();
  625. // Delete this category
  626. return hr;
  627. }
  628. //+
  629. HRESULT CClassContainer::RemovePackage (LPOLESTR pszPackageName)
  630. //
  631. // Remove a Package and the associated Classes from class store
  632. //
  633. {
  634. HRESULT hr = S_OK;
  635. IADs *pADs = NULL;
  636. DWORD cClasses = 0, count = 0;
  637. WCHAR szRdn [_MAX_PATH];
  638. LPOLESTR *szClasses;
  639. if (IsBadStringPtr(pszPackageName, _MAX_PATH))
  640. return E_INVALIDARG;
  641. if ((pszPackageName == NULL) ||
  642. (*(pszPackageName) == NULL))
  643. return E_INVALIDARG;
  644. wcscpy (szRdn, L"CN=");
  645. wcscat (szRdn, pszPackageName);
  646. if (!m_fOpen)
  647. return E_FAIL;
  648. hr = m_ADsPackageContainer->GetObject(NULL, szRdn, (IDispatch **)&pADs);
  649. RETURN_ON_FAILURE(hr);
  650. hr = GetPropertyListAlloc(pADs, PKGCLSIDLIST, &cClasses, &szClasses);
  651. for (count = 0; count < cClasses; count++)
  652. hr = DeleteClass(szClasses[count]);
  653. // ignore errors
  654. for (count = 0; count < cClasses; count++)
  655. CoTaskMemFree(szClasses[count]);
  656. CoTaskMemFree(szClasses);
  657. pADs->Release();
  658. hr = m_ADsPackageContainer->Delete(CLASS_CS_PACKAGE, szRdn);
  659. return hr;
  660. }
  661. //+
  662. HRESULT CClassContainer::NewClass (CLASSDETAIL *pClassDetail)
  663. //
  664. // Add a new class to the database
  665. //
  666. {
  667. HRESULT hr = S_OK;
  668. IADs * pADs = NULL;
  669. IDispatch * pUnknown = NULL;
  670. STRINGGUID szGUID;
  671. WCHAR szRDN [_MAX_PATH];
  672. if (!m_fOpen)
  673. return E_FAIL;
  674. //
  675. // Cant be a NULL guid
  676. //
  677. if (IsNullGuid(pClassDetail->Clsid))
  678. return E_INVALIDARG;
  679. StringFromGUID(pClassDetail->Clsid, szGUID);
  680. //
  681. // Create the RDN for the Class Object
  682. //
  683. // BUGBUG:: attaching package name creates problems.
  684. wsprintf(szRDN, L"CN=%s", szGUID);
  685. hr = m_ADsClassContainer->Create(
  686. CLASS_CS_CLASS,
  687. szRDN,
  688. &pUnknown
  689. );
  690. RETURN_ON_FAILURE(hr);
  691. hr = pUnknown->QueryInterface(
  692. IID_IADs,
  693. (void **)&pADs
  694. );
  695. pUnknown->Release();
  696. hr = SetProperty (pADs, CLASSCLSID, szGUID);
  697. ERROR_ON_FAILURE(hr);
  698. if (pClassDetail->cProgId)
  699. {
  700. hr = SetPropertyList(pADs, PROGIDLIST, pClassDetail->cProgId,
  701. pClassDetail->prgProgId);
  702. ERROR_ON_FAILURE(hr);
  703. }
  704. if (!IsNullGuid(pClassDetail->TreatAs))
  705. {
  706. StringFromGUID(pClassDetail->TreatAs, szGUID);
  707. hr = SetProperty (pADs, TREATASCLSID, szGUID);
  708. ERROR_ON_FAILURE(hr);
  709. }
  710. hr = SetPropertyDW(pADs, CLASSREFCOUNTER, 1);
  711. ERROR_ON_FAILURE(hr);
  712. hr = StoreIt (pADs);
  713. // this does not return an error for an alreay existing entry.
  714. if (hr == E_ADS_LDAP_ALREADY_EXISTS)
  715. {
  716. DWORD refcount = 0;
  717. pADs->Release(); // release the interface pointer already got.
  718. hr = m_ADsClassContainer->GetObject(NULL, // CLASS_CS_CLASS
  719. szRDN,
  720. (IDispatch **)&pADs);
  721. RETURN_ON_FAILURE(hr);
  722. if (pClassDetail->cProgId)
  723. {
  724. hr = SetPropertyListMerge(pADs, PROGIDLIST, pClassDetail->cProgId,
  725. pClassDetail->prgProgId);
  726. ERROR_ON_FAILURE(hr);
  727. }
  728. // increment reference counter.
  729. hr = GetPropertyDW(pADs, CLASSREFCOUNTER, &refcount);
  730. ERROR_ON_FAILURE(hr);
  731. refcount++;
  732. hr = SetPropertyDW(pADs, CLASSREFCOUNTER, refcount);
  733. ERROR_ON_FAILURE(hr);
  734. // No merging of the treatas.
  735. hr = StoreIt(pADs);
  736. }
  737. Error_Cleanup:
  738. pADs->Release();
  739. return hr;
  740. }
  741. #define SCRIPT_IN_DIRECTORY 256
  742. HRESULT CClassContainer::AddPackage(LPOLESTR pszPackageName,
  743. PACKAGEDETAIL *pPackageDetail)
  744. {
  745. HRESULT hr;
  746. IADs *pPackageADs = NULL;
  747. IDispatch *pUnknown = NULL;
  748. WCHAR szRDN [_MAX_PATH];
  749. LPOLESTR *pszGuid, *pszProgId;
  750. DWORD *pdwArch=NULL, count = 0, cPackProgId = 0;
  751. CSUSN Usn;
  752. if (!pszPackageName)
  753. return E_INVALIDARG;
  754. if (!pPackageDetail)
  755. return E_INVALIDARG;
  756. if (!IsValidReadPtrIn(pPackageDetail, sizeof(PACKAGEDETAIL)))
  757. return E_INVALIDARG;
  758. LPWSTR pName = pszPackageName;
  759. while (*pName)
  760. {
  761. if ((*pName == L':') ||
  762. (*pName == L',') ||
  763. (*pName == L';') ||
  764. (*pName == L'/') ||
  765. (*pName == L'<') ||
  766. (*pName == L'>') ||
  767. (*pName == L'\\'))
  768. return E_INVALIDARG;
  769. ++pName;
  770. }
  771. // Validating ActivationInfo
  772. if (pPackageDetail->pActInfo)
  773. {
  774. if (!IsValidReadPtrIn(pPackageDetail->pActInfo, sizeof(ACTIVATIONINFO)))
  775. return E_INVALIDARG;
  776. if (!IsValidReadPtrIn(pPackageDetail->pActInfo->pClasses,
  777. sizeof(CLASSDETAIL) * (pPackageDetail->pActInfo->cClasses)))
  778. return E_INVALIDARG;
  779. if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgShellFileExt,
  780. sizeof(LPOLESTR) * (pPackageDetail->pActInfo->cShellFileExt)))
  781. return E_INVALIDARG;
  782. for (count = 0; count < (pPackageDetail->pActInfo->cShellFileExt); count++)
  783. {
  784. if (!pPackageDetail->pActInfo->prgShellFileExt[count])
  785. return E_INVALIDARG;
  786. }
  787. if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgPriority,
  788. sizeof(UINT) * (pPackageDetail->pActInfo->cShellFileExt)))
  789. return E_INVALIDARG;
  790. if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgInterfaceId,
  791. sizeof(IID) * (pPackageDetail->pActInfo->cInterfaces)))
  792. return E_INVALIDARG;
  793. if (!IsValidReadPtrIn(pPackageDetail->pActInfo->prgTlbId,
  794. sizeof(GUID) * (pPackageDetail->pActInfo->cTypeLib)))
  795. return E_INVALIDARG;
  796. }
  797. // Validating InstallInfo
  798. if ((pPackageDetail->pInstallInfo == NULL) ||
  799. (!IsValidReadPtrIn(pPackageDetail->pInstallInfo, sizeof(INSTALLINFO)))
  800. )
  801. return E_INVALIDARG;
  802. // Validating PlatformInfo
  803. if ((pPackageDetail->pPlatformInfo == NULL) ||
  804. (!IsValidReadPtrIn(pPackageDetail->pPlatformInfo, sizeof(PLATFORMINFO)))
  805. )
  806. return E_INVALIDARG;
  807. if (!IsValidReadPtrIn(pPackageDetail->pPlatformInfo->prgPlatform,
  808. sizeof(CSPLATFORM) * (pPackageDetail->pPlatformInfo->cPlatforms)))
  809. return E_INVALIDARG;
  810. if ((pPackageDetail->pPlatformInfo->cLocales == 0) ||
  811. (pPackageDetail->pPlatformInfo->prgPlatform == 0))
  812. return E_INVALIDARG;
  813. if (!IsValidReadPtrIn(pPackageDetail->pPlatformInfo->prgLocale,
  814. sizeof(LCID) * (pPackageDetail->pPlatformInfo->cLocales)))
  815. return E_INVALIDARG;
  816. // Validating other fields in PackageDetail structure
  817. if ((pPackageDetail->pszSourceList == NULL) ||
  818. (!IsValidReadPtrIn(pPackageDetail->pszSourceList,
  819. sizeof(LPOLESTR) * (pPackageDetail->cSources)))
  820. )
  821. return E_INVALIDARG;
  822. for (count = 0; count < (pPackageDetail->cSources); count++)
  823. if (!pPackageDetail->pszSourceList[count])
  824. return E_INVALIDARG;
  825. if (pPackageDetail->rpCategory)
  826. {
  827. if (!IsValidReadPtrIn(pPackageDetail->rpCategory,
  828. sizeof(GUID) * (pPackageDetail->cCategories)))
  829. return E_INVALIDARG;
  830. }
  831. //
  832. // Now we create the package
  833. //
  834. wcscpy (szRDN, L"CN=");
  835. wcscat (szRDN, pszPackageName);
  836. pUnknown = NULL;
  837. hr = m_ADsPackageContainer->Create(
  838. CLASS_CS_PACKAGE,
  839. szRDN,
  840. &pUnknown
  841. );
  842. RETURN_ON_FAILURE(hr);
  843. hr = pUnknown->QueryInterface(
  844. IID_IADs,
  845. (void **)&pPackageADs
  846. );
  847. pUnknown->Release();
  848. // fill in the activation info
  849. if (pPackageDetail->pActInfo)
  850. {
  851. if ((pPackageDetail->pActInfo)->cClasses)
  852. {
  853. pszGuid = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cClasses)*sizeof(LPOLESTR));
  854. if (!pszGuid)
  855. {
  856. hr = E_OUTOFMEMORY;
  857. ERROR_ON_FAILURE(hr);
  858. }
  859. for (count = 0; count < pPackageDetail->pActInfo->cClasses; count++)
  860. {
  861. pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*STRINGGUIDLEN);
  862. StringFromGUID(pPackageDetail->pActInfo->pClasses[count].Clsid, pszGuid[count]);
  863. cPackProgId += pPackageDetail->pActInfo->pClasses[count].cProgId;
  864. }
  865. hr = SetPropertyList(pPackageADs, PKGCLSIDLIST, (pPackageDetail->pActInfo)->cClasses, pszGuid);
  866. ERROR_ON_FAILURE(hr);
  867. for (count = 0; (count < pPackageDetail->pActInfo->cClasses); count++)
  868. CoTaskMemFree(pszGuid[count]);
  869. CoTaskMemFree(pszGuid);
  870. }
  871. // collecting all the progids from the various clsids.
  872. if (cPackProgId)
  873. {
  874. pszProgId = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*cPackProgId);
  875. if (!pszProgId)
  876. {
  877. hr = E_OUTOFMEMORY;
  878. ERROR_ON_FAILURE(hr);
  879. }
  880. for (count = 0, cPackProgId = 0; count < pPackageDetail->pActInfo->cClasses; count++)
  881. {
  882. DWORD cClassProgId = 0;
  883. for (cClassProgId = 0; cClassProgId < pPackageDetail->pActInfo->pClasses[count].cProgId;
  884. cClassProgId++)
  885. {
  886. pszProgId[cPackProgId++] =
  887. pPackageDetail->pActInfo->pClasses[count].prgProgId[cClassProgId];
  888. }
  889. }
  890. hr = SetPropertyList(pPackageADs, PROGIDLIST, cPackProgId, pszProgId);
  891. CoTaskMemFree(pszProgId);
  892. }
  893. ERROR_ON_FAILURE(hr);
  894. if (pPackageDetail->pActInfo->cShellFileExt)
  895. {
  896. //
  897. // Store a tuple in the format <file ext>:<priority>
  898. //
  899. pszGuid = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cShellFileExt) * sizeof(LPOLESTR));
  900. if (!pszGuid)
  901. {
  902. hr = E_OUTOFMEMORY;
  903. ERROR_ON_FAILURE(hr);
  904. }
  905. for (count = 0; count < pPackageDetail->pActInfo->cShellFileExt; count++)
  906. {
  907. pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *
  908. (wcslen(pPackageDetail->pActInfo->prgShellFileExt[count])+1+2+1));
  909. // format is fileext+:+nn+NULL where nn = 2 digit priority
  910. wsprintf(pszGuid[count], L"%s:%2d",
  911. pPackageDetail->pActInfo->prgShellFileExt[count],
  912. pPackageDetail->pActInfo->prgPriority[count]);
  913. }
  914. hr = SetPropertyList(pPackageADs, PKGFILEEXTNLIST, pPackageDetail->pActInfo->cShellFileExt, pszGuid);
  915. for (count = 0; (count < pPackageDetail->pActInfo->cShellFileExt); count++)
  916. CoTaskMemFree(pszGuid[count]);
  917. CoTaskMemFree(pszGuid);
  918. //
  919. // Now IDS Workaround
  920. // BUGBUG. Remove this when the DS bug is fixed. 130491 in NTDEV
  921. //
  922. hr = SetPropertyList(pPackageADs,
  923. QRYFILEEXT,
  924. pPackageDetail->pActInfo->cShellFileExt,
  925. pPackageDetail->pActInfo->prgShellFileExt);
  926. }
  927. ERROR_ON_FAILURE(hr);
  928. if (pPackageDetail->pActInfo->cInterfaces)
  929. {
  930. pszGuid = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cInterfaces)*sizeof(LPOLESTR));
  931. if (!pszGuid)
  932. {
  933. hr = E_OUTOFMEMORY;
  934. ERROR_ON_FAILURE(hr);
  935. }
  936. for (count = 0; (count < (pPackageDetail->pActInfo->cInterfaces)); count++)
  937. {
  938. pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
  939. if (!pszGuid[count])
  940. {
  941. hr = E_OUTOFMEMORY;
  942. ERROR_ON_FAILURE(hr);
  943. }
  944. StringFromGUID((pPackageDetail->pActInfo->prgInterfaceId)[count], pszGuid[count]);
  945. }
  946. hr = SetPropertyList(pPackageADs, PKGIIDLIST, pPackageDetail->pActInfo->cInterfaces,
  947. pszGuid);
  948. ERROR_ON_FAILURE(hr);
  949. for (count = 0; (count < (pPackageDetail->pActInfo->cInterfaces)); count++)
  950. CoTaskMemFree(pszGuid[count]);
  951. CoTaskMemFree(pszGuid);
  952. }
  953. if (pPackageDetail->pActInfo->cTypeLib)
  954. {
  955. pszGuid = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->pActInfo->cTypeLib)*sizeof(LPOLESTR));
  956. if (!pszGuid)
  957. {
  958. hr = E_OUTOFMEMORY;
  959. ERROR_ON_FAILURE(hr);
  960. }
  961. for (count = 0; (count < (pPackageDetail->pActInfo)->cTypeLib); count++)
  962. {
  963. pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
  964. if (!pszGuid[count])
  965. {
  966. hr = E_OUTOFMEMORY;
  967. ERROR_ON_FAILURE(hr);
  968. }
  969. StringFromGUID((pPackageDetail->pActInfo->prgTlbId)[count], pszGuid[count]);
  970. }
  971. hr = SetPropertyList(pPackageADs, PKGTLBIDLIST, pPackageDetail->pActInfo->cTypeLib,
  972. pszGuid);
  973. ERROR_ON_FAILURE(hr);
  974. for (count = 0; (count < (pPackageDetail->pActInfo->cTypeLib)); count++)
  975. CoTaskMemFree(pszGuid[count]);
  976. CoTaskMemFree(pszGuid);
  977. }
  978. }
  979. // fill in the platforminfo
  980. // BUGBUG::***os version
  981. if ((pPackageDetail->pPlatformInfo)->cPlatforms)
  982. {
  983. pdwArch = (DWORD *)CoTaskMemAlloc(sizeof(DWORD)*
  984. ((pPackageDetail->pPlatformInfo)->cPlatforms));
  985. for (count = 0; (count < (pPackageDetail->pPlatformInfo)->cPlatforms); count++)
  986. UnpackPlatform (pdwArch+count, ((pPackageDetail->pPlatformInfo)->prgPlatform)+count);
  987. hr = SetPropertyListDW (pPackageADs, ARCHLIST, (pPackageDetail->pPlatformInfo)->cPlatforms, pdwArch);
  988. ERROR_ON_FAILURE(hr);
  989. CoTaskMemFree(pdwArch);
  990. }
  991. if ((pPackageDetail->pPlatformInfo)->cLocales)
  992. {
  993. hr = SetPropertyListDW (pPackageADs,
  994. LOCALEID, (pPackageDetail->pPlatformInfo)->cLocales,
  995. (pPackageDetail->pPlatformInfo)->prgLocale);
  996. ERROR_ON_FAILURE(hr);
  997. }
  998. // fill in the installinfo
  999. hr = SetProperty(pPackageADs, PACKAGENAME, pszPackageName);
  1000. ERROR_ON_FAILURE(hr);
  1001. hr = SetPropertyDW (pPackageADs, PACKAGETYPE, (DWORD)pPackageDetail->pInstallInfo->PathType);
  1002. ERROR_ON_FAILURE(hr);
  1003. if (pPackageDetail->pInstallInfo->pszScriptPath)
  1004. {
  1005. hr = SetProperty(pPackageADs, SCRIPTPATH, pPackageDetail->pInstallInfo->pszScriptPath);
  1006. ERROR_ON_FAILURE(hr);
  1007. }
  1008. if (pPackageDetail->pInstallInfo->pszSetupCommand)
  1009. {
  1010. hr = SetProperty(pPackageADs, SETUPCOMMAND, pPackageDetail->pInstallInfo->pszSetupCommand);
  1011. ERROR_ON_FAILURE(hr);
  1012. }
  1013. if (pPackageDetail->pInstallInfo->pszUrl)
  1014. {
  1015. hr = SetProperty(pPackageADs, HELPURL, pPackageDetail->pInstallInfo->pszUrl);
  1016. ERROR_ON_FAILURE(hr);
  1017. }
  1018. GetCurrentUsn(&Usn);
  1019. hr = UsnUpd(pPackageADs, PKGUSN, &Usn);
  1020. ERROR_ON_FAILURE(hr);
  1021. hr = SetPropertyDW (pPackageADs, PACKAGEFLAGS, pPackageDetail->pInstallInfo->dwActFlags);
  1022. ERROR_ON_FAILURE(hr);
  1023. hr = SetPropertyDW (pPackageADs, CLASSCTX, pPackageDetail->pInstallInfo->dwComClassContext);
  1024. ERROR_ON_FAILURE(hr);
  1025. hr = SetPropertyDW (pPackageADs, VERSIONHI, pPackageDetail->pInstallInfo->dwVersionHi);
  1026. ERROR_ON_FAILURE(hr);
  1027. hr = SetPropertyDW (pPackageADs, VERSIONLO, pPackageDetail->pInstallInfo->dwVersionLo);
  1028. ERROR_ON_FAILURE(hr);
  1029. hr = SetPropertyDW (pPackageADs, SCRIPTSIZE, pPackageDetail->pInstallInfo->cScriptLen);
  1030. ERROR_ON_FAILURE(hr);
  1031. hr = SetPropertyDW (pPackageADs, UILEVEL, (DWORD)pPackageDetail->pInstallInfo->InstallUiLevel);
  1032. ERROR_ON_FAILURE(hr);
  1033. if (pPackageDetail->pInstallInfo->cUpgrades)
  1034. {
  1035. LPOLESTR *rpszUpgrades;
  1036. rpszUpgrades = (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR)*pPackageDetail->pInstallInfo->cUpgrades);
  1037. for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++)
  1038. {
  1039. UINT l = wcslen(pPackageDetail->pInstallInfo->prgUpgradeScript[count]);
  1040. rpszUpgrades[count] = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR) *(4+l));
  1041. wsprintf(rpszUpgrades[count], L"%S:%1d",
  1042. pPackageDetail->pInstallInfo->prgUpgradeScript[count],
  1043. pPackageDetail->pInstallInfo->prgUpgradeFlag[count]);
  1044. }
  1045. hr = SetPropertyList(pPackageADs, UPGRADESCRIPTNAMES, pPackageDetail->pInstallInfo->cUpgrades,
  1046. rpszUpgrades);
  1047. ERROR_ON_FAILURE(hr);
  1048. for (count = 0; (count < pPackageDetail->pInstallInfo->cUpgrades); count++)
  1049. CoTaskMemFree(rpszUpgrades[count]);
  1050. CoTaskMemFree(rpszUpgrades);
  1051. }
  1052. // fill in the sources
  1053. if (pPackageDetail->cSources)
  1054. {
  1055. hr = SetPropertyList(pPackageADs, MSIFILELIST, pPackageDetail->cSources,
  1056. pPackageDetail->pszSourceList);
  1057. ERROR_ON_FAILURE(hr);
  1058. }
  1059. // fill in the categories
  1060. if (pPackageDetail->cCategories)
  1061. {
  1062. pszGuid = (LPOLESTR *)CoTaskMemAlloc((pPackageDetail->cCategories) * sizeof(LPOLESTR));
  1063. if (!pszGuid)
  1064. {
  1065. hr = E_OUTOFMEMORY;
  1066. ERROR_ON_FAILURE(hr);
  1067. }
  1068. for (count = 0; (count < pPackageDetail->cCategories); count++)
  1069. {
  1070. pszGuid[count] = (LPOLESTR)CoTaskMemAlloc(STRINGGUIDLEN*sizeof(WCHAR));
  1071. if (!pszGuid[count])
  1072. {
  1073. hr = E_OUTOFMEMORY;
  1074. ERROR_ON_FAILURE(hr);
  1075. }
  1076. StringFromGUID((pPackageDetail->rpCategory)[count], pszGuid[count]);
  1077. }
  1078. hr = SetPropertyList(pPackageADs, PKGCATEGORYLIST, pPackageDetail->cCategories,
  1079. pszGuid);
  1080. ERROR_ON_FAILURE(hr);
  1081. for (count = 0; (count < pPackageDetail->cCategories); count++)
  1082. CoTaskMemFree(pszGuid[count]);
  1083. CoTaskMemFree(pszGuid);
  1084. }
  1085. //
  1086. // Store the script in the directory
  1087. //
  1088. if ((pPackageDetail->pInstallInfo->dwActFlags & SCRIPT_IN_DIRECTORY) &&
  1089. (pPackageDetail->pInstallInfo->cScriptLen))
  1090. {
  1091. if ((pPackageDetail->pInstallInfo->cScriptLen) &&
  1092. (!IsValidReadPtrIn(pPackageDetail->pInstallInfo->pScript, pPackageDetail->pInstallInfo->cScriptLen)))
  1093. return E_INVALIDARG;
  1094. SAFEARRAYBOUND size; // Get rid of 16
  1095. SAFEARRAY FAR *psa;
  1096. CHAR HUGEP *pArray=NULL;
  1097. LONG dwSLBound = 0;
  1098. LONG dwSUBound = 0;
  1099. VARIANT vData;
  1100. VariantInit(&vData);
  1101. size.cElements = pPackageDetail->pInstallInfo->cScriptLen;
  1102. size.lLbound = 0;
  1103. psa = SafeArrayCreate(VT_UI1, 1, &size);
  1104. if (!psa) {
  1105. return(E_OUTOFMEMORY);
  1106. }
  1107. hr = SafeArrayAccessData( psa, (void HUGEP * FAR *) &pArray );
  1108. RETURN_ON_FAILURE(hr);
  1109. memcpy( pArray, pPackageDetail->pInstallInfo->pScript, size.cElements );
  1110. SafeArrayUnaccessData( psa );
  1111. V_VT(&vData) = VT_ARRAY | VT_UI1;
  1112. V_ARRAY(&vData) = psa;
  1113. hr = pPackageADs->Put(PKGSCRIPT, vData);
  1114. VariantClear(&vData);
  1115. ERROR_ON_FAILURE(hr);
  1116. }
  1117. hr = StoreIt(pPackageADs);
  1118. ERROR_ON_FAILURE(hr);
  1119. for (count = 0; count < pPackageDetail->pActInfo->cClasses; count++)
  1120. {
  1121. hr = NewClass((pPackageDetail->pActInfo->pClasses)+count);
  1122. ERROR_ON_FAILURE(hr);
  1123. }
  1124. Error_Cleanup:
  1125. pPackageADs->Release();
  1126. return hr;
  1127. }
  1128.