Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

831 lines
22 KiB

  1. //+------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997
  5. //
  6. // File: csmain.cxx
  7. //
  8. // Contents: All the exposed APIs.
  9. //
  10. // Author: DebiM
  11. //
  12. //-------------------------------------------------------------------------
  13. #include "cstore.hxx"
  14. // Globals
  15. DWORD gCsOptions = 0;
  16. //
  17. // Class Factory Objects
  18. //
  19. CClassContainerCF * g_pCF = NULL;
  20. CAppContainerCF * pCF = NULL;
  21. CClassAccessCF * pCSAccessCF = NULL;
  22. // Debugging Output Global values.
  23. DWORD gDebugLog = 0;
  24. DWORD gDebugOut = 0;
  25. DWORD gDebugEventLog = 0;
  26. DWORD gDebug = 0;
  27. //
  28. // Number of objects alive in cstore.dll
  29. //
  30. long ObjectCount = 0;
  31. //
  32. // Critical Section for All Global Objects.
  33. //
  34. CRITICAL_SECTION ClassStoreBindList;
  35. //-------------------------------------------------------------------
  36. // Function Uninitialize
  37. //
  38. // Synopsis: Class Store Server Uninitialization.
  39. // Disconnects from all Class Containers in use.
  40. // Flushes out all State information using ResetClassStoreState.
  41. // Unregisters Server registrations etc..
  42. //
  43. // Arguments: None
  44. //
  45. // Returns: None
  46. //
  47. //-------------------------------------------------------------------
  48. void Uninitialize()
  49. {
  50. //
  51. // Cleanup all open containers
  52. //
  53. //ResetClassStoreState();
  54. //
  55. // release the Class Factory objects
  56. //
  57. if (pCF)
  58. pCF->Release();
  59. if (pCSAccessCF)
  60. pCSAccessCF->Release();
  61. if (g_pCF)
  62. g_pCF->Release();
  63. //
  64. // get rid of the critical section
  65. //
  66. DeleteCriticalSection(&ClassStoreBindList);
  67. }
  68. //+---------------------------------------------------------------
  69. //
  70. // Function: InitDebugValues
  71. //
  72. // Synopsis: Initializes the Debug Values for the class store.
  73. //
  74. // Arguments:
  75. //
  76. // Returns:
  77. // S_OK
  78. //
  79. // Log will go into the Debugger if the first bit is 1.
  80. // If second bit is set, log will go into a log file.
  81. // If third bit is set, log will go into event log.
  82. //
  83. // Note that the above is only true of DL_CSTORE is specified --
  84. // if not, there is no debug output for the cstore component
  85. //
  86. // The gDebugLevel variable is initialized by the InitDebugSupport
  87. // call in the common static library
  88. //
  89. //----------------------------------------------------------------
  90. void InitDebugValues()
  91. {
  92. gDebugEventLog = gDebugLevel & DL_EVENTLOG;
  93. gDebugLog = gDebugLevel & DL_LOGFILE;
  94. gDebugOut = gDebugLevel & DL_NORMAL;
  95. gDebug = (gDebugLevel & DL_CSTORE) && (gDebugOut || gDebugLog || gDebugEventLog);
  96. }
  97. //---------------------------------------------------------------------------
  98. //
  99. // Function: InitializeClassStore
  100. //
  101. // History: 7-25-96 DebiM Created
  102. //
  103. // This entry point is called at DLL attach
  104. //----------------------------------------------------------------------------
  105. BOOL InitializeClassStore(BOOL fInit)
  106. {
  107. HRESULT hr;
  108. BOOL bStatus;
  109. ObjectCount = 1;
  110. InitDebugValues();
  111. InitializeLanguageSupport();
  112. pCF = new CAppContainerCF();
  113. pCSAccessCF = new CClassAccessCF();
  114. InitializeCriticalSection(&ClassStoreBindList);
  115. g_pCF = new CClassContainerCF;
  116. if (!pCF || !pCSAccessCF || !g_pCF)
  117. {
  118. return FALSE;
  119. }
  120. return TRUE;
  121. }
  122. void
  123. GetDefaultPlatform(CSPLATFORM *pPlatform,
  124. BOOL fArchitectureOverride,
  125. LONG OverridingArchitecture)
  126. {
  127. OSVERSIONINFO VersionInformation;
  128. VersionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  129. GetVersionEx(&VersionInformation);
  130. pPlatform->dwPlatformId = VersionInformation.dwPlatformId;
  131. pPlatform->dwVersionHi = VersionInformation.dwMajorVersion;
  132. pPlatform->dwVersionLo = VersionInformation.dwMinorVersion;
  133. //
  134. // Allow the caller to specify an overriding architecture for
  135. // cases where the default logic (use the current platform) is
  136. // not sufficient (demand install of inproc servers)
  137. //
  138. if ( fArchitectureOverride )
  139. {
  140. pPlatform->dwProcessorArch = OverridingArchitecture;
  141. }
  142. else
  143. {
  144. pPlatform->dwProcessorArch = DEFAULT_ARCHITECTURE;
  145. }
  146. }
  147. //+-------------------------------------------------------------------------
  148. //
  149. // Function: CsGetClassAccess
  150. //
  151. // Synopsis: Returns an instantiated interface to the Class Store
  152. // Co-ordinator object in Rpcss.
  153. //
  154. // Arguments: [ppIClassAccess] - where to put class access interface pointer
  155. //
  156. // Returns: S_OK - Got a Class Access Successfully
  157. // E_FAIL
  158. //
  159. //--------------------------------------------------------------------------
  160. STDAPI CsGetClassAccess(
  161. IClassAccess ** ppIClassAccess)
  162. {
  163. HRESULT hr;
  164. *ppIClassAccess = NULL;
  165. hr = pCSAccessCF->CreateInstance( NULL,
  166. IID_IClassAccess,
  167. (void **)ppIClassAccess);
  168. return hr;
  169. }
  170. //+-------------------------------------------------------------------
  171. //
  172. // CsEnumApps (DebiM 11/7/97)
  173. //
  174. // Returns an enumerator for packages in the Class Store (s).
  175. // The enumerator works across all class stores in the calling users profile.
  176. //
  177. //
  178. // This is used by:
  179. // - Add/Remove programs to select Corporate Apps
  180. // - winlogon to obtain the list of assigned apps
  181. //
  182. // Arguments:
  183. // [in]
  184. // pszPackageName : Optional Wildcard string for PackageName
  185. // pLastUsn : Optional Time Stamp for new packages
  186. // pCategory : Optional CategoryId
  187. // dwAppFlags : Per APPINFO_xxx in objbase.h
  188. // [out]
  189. // ppIEnumPackage : Returned Interface Pointer
  190. //
  191. // Returns :
  192. // S_OK or E_NO_CLASSSTORE
  193. //
  194. //--------------------------------------------------------------------
  195. STDAPI
  196. CsEnumApps(
  197. LPOLESTR pszPackageName, // Wildcard string for PackageName
  198. GUID *pCategory, // CategoryId
  199. ULONGLONG *pLastUsn, // Time Stamp for new packages
  200. DWORD dwAppFlags, // Per APPINFO_xxx in objbase.h
  201. IEnumPackage **ppIEnumPackage // Returned Interface Pointer
  202. )
  203. {
  204. HRESULT hr;
  205. IClassAccess * pIClassAccess = NULL;
  206. *ppIEnumPackage = NULL;
  207. //
  208. // Get an IClassAccess
  209. //
  210. hr = CsGetClassAccess(&pIClassAccess);
  211. if (!SUCCEEDED(hr))
  212. return hr;
  213. //
  214. // Get the enumerator
  215. //
  216. hr = pIClassAccess->EnumPackages (
  217. pszPackageName,
  218. pCategory,
  219. pLastUsn,
  220. dwAppFlags,
  221. ppIEnumPackage
  222. );
  223. pIClassAccess->Release();
  224. return hr;
  225. }
  226. //+-------------------------------------------------------------------
  227. //
  228. // Function: CsGetAppInfo
  229. //
  230. // Synopsis: Gets Package Information for a package that matches
  231. // the query.
  232. //
  233. // Used By:
  234. // services. CoCreateInstance (OLE)
  235. //
  236. // Arguments:
  237. // [in]
  238. // pClassSpec:
  239. // The query consisting of the name or clsid or ...
  240. // pQueryContext:
  241. // Execution context, architecture/Platform/locale req'd,
  242. // Default value is the ThreadLocale and the default Platform.
  243. //
  244. // [out]
  245. // pPackageInfo
  246. // Neccessary Package Information.
  247. //
  248. // Returns :
  249. // S_OK, CS_E_XXX errors.
  250. //
  251. // Looks up the given class specification in the DS. If an application for
  252. // this class specification is found, then the application details are returned.
  253. // Gets the IClassAccess Pointer and calls GetAppInfo on it.
  254. //
  255. // Caller needs to FREE the pPackageInfo using the Release APIs.
  256. //--------------------------------------------------------------------
  257. STDAPI
  258. CsGetAppInfo(
  259. uCLSSPEC * pClassSpec, // Class Spec (GUID/Ext/MIME)
  260. QUERYCONTEXT * pQueryContext,
  261. PACKAGEDISPINFO * pPackageInfo
  262. )
  263. {
  264. HRESULT hr = S_OK;
  265. IClassAccess * pIClassAccess = NULL;
  266. // Gets the IClassAccess pointer
  267. hr = CsGetClassAccess(&pIClassAccess);
  268. if (!SUCCEEDED(hr))
  269. return hr;
  270. // Calls the GetAppInfo method
  271. hr = pIClassAccess->GetAppInfo(pClassSpec, pQueryContext, pPackageInfo );
  272. pIClassAccess->Release();
  273. return hr;
  274. }
  275. //+-------------------------------------------------------------------
  276. //
  277. // Function: CsCreateClassStore
  278. //
  279. // Synopsis: Creates the class store.
  280. //
  281. // Used By:
  282. // mmc snapin.
  283. //
  284. // Arguments:
  285. // [in]
  286. // szCSPath:
  287. // Path where a new class store has to be created.
  288. //
  289. // Returns :
  290. // S_OK, CS_E_XXX errors.
  291. //
  292. // Gets the parent containers Name (GPO)
  293. // and the name of the class store. Creates a Class Store with this name
  294. // Below the parent object.
  295. //--------------------------------------------------------------------
  296. STDAPI
  297. CsCreateClassStore(LPOLESTR szServerName, LPOLESTR szCSPath)
  298. {
  299. LPOLESTR szPath = NULL;
  300. LPOLESTR szParentPath=NULL, szStoreName=NULL;
  301. HRESULT hr = S_OK;
  302. LPOLESTR szPolicyName = NULL, szUserMachine = NULL;
  303. CServerContext ServerContext;
  304. szPath = szCSPath;
  305. // Getting the path for the parent (Policy object) from the name.
  306. hr = BuildADsParentPath(szPath, &szParentPath, &szStoreName);
  307. ERROR_ON_FAILURE(hr);
  308. // Get the Policy Object
  309. hr = BuildADsParentPath(szParentPath, &szPolicyName, &szUserMachine);
  310. if (!SUCCEEDED(hr))
  311. {
  312. szPolicyName = NULL;
  313. }
  314. if (szUserMachine)
  315. FreeADsMem(szUserMachine);
  316. hr = ServerContext.Initialize( szServerName );
  317. ERROR_ON_FAILURE(hr);
  318. // creating class store. returns CS_E_XXX errors when it returns.
  319. hr = CreateRepository(&ServerContext, szParentPath, szStoreName, szPolicyName);
  320. Error_Cleanup:
  321. if (szPolicyName)
  322. FreeADsMem(szPolicyName);
  323. if (szParentPath)
  324. FreeADsMem(szParentPath);
  325. if (szStoreName)
  326. FreeADsMem(szStoreName);
  327. return hr;
  328. }
  329. //+-------------------------------------------------------------------
  330. //
  331. // Function: CsGetClassStore
  332. //
  333. // Synopsis: Gets the IClassAdmin interface pointer for the input class store.
  334. //
  335. // Used By:
  336. // mmc snapin.
  337. //
  338. // Arguments:
  339. // [in]
  340. // szPath:
  341. // Unicode Path For the Class Store.
  342. //
  343. // [out]
  344. // ppIClassAdmin:
  345. // IClassAdmin interface pointer.
  346. //
  347. //
  348. // Returns :
  349. // S_OK, or CS_E_XXX error codes.
  350. //--------------------------------------------------------------------
  351. STDAPI
  352. CsGetClassStore(LPOLESTR szPath, void **ppIClassAdmin)
  353. {
  354. return CsServerGetClassStore(
  355. NULL,
  356. szPath,
  357. ppIClassAdmin );
  358. }
  359. STDAPI
  360. CsServerGetClassStore(LPOLESTR szServerName, LPOLESTR szPath, void **ppIClassAdmin)
  361. {
  362. CServerContext ServerContext;
  363. HRESULT hr = ServerContext.Initialize( szServerName );
  364. if ( FAILED(hr) )
  365. {
  366. return hr;
  367. }
  368. return g_pCF->CreateConnectedInstance(
  369. &ServerContext,
  370. szPath,
  371. ppIClassAdmin);
  372. }
  373. //+---------------------------------------------------------------
  374. //
  375. // Function: CsDeleteClassStore
  376. //
  377. // Synopsis: Public entrypoint for deleting a class store container from DS.
  378. // Not implemented.
  379. //
  380. //----------------------------------------------------------------
  381. STDAPI
  382. CsDeleteClassStore(LPOLESTR szPath)
  383. {
  384. return E_NOTIMPL;
  385. }
  386. //+-------------------------------------------------------------------
  387. //
  388. // Function: CsRegisterAppCategory
  389. //
  390. // Synopsis: Registers a cetegory under the Domain.
  391. //
  392. // Used By:
  393. // This is used by Add/Remove programs.
  394. //
  395. // Arguments:
  396. // [in]
  397. // pAppCategory:
  398. // Category and its details that have to be added.
  399. //
  400. // Returns :
  401. // S_OK or CS_E_XXX error codes.
  402. //--------------------------------------------------------------------
  403. STDAPI
  404. CsRegisterAppCategory(APPCATEGORYINFO *pAppCategory)
  405. {
  406. HRESULT hr = S_OK;
  407. IClassAdmin * pIClassAdmin = NULL;
  408. // get the interface pointer
  409. hr = g_pCF->CreateInstance(
  410. NULL,
  411. IID_IClassAdmin,
  412. (void **)&pIClassAdmin);
  413. if (!SUCCEEDED(hr))
  414. return hr;
  415. // get the app categories list.
  416. hr = pIClassAdmin->RegisterAppCategory(pAppCategory);
  417. // release the interface pointer.
  418. pIClassAdmin->Release();
  419. return hr;
  420. }
  421. //+-------------------------------------------------------------------
  422. //
  423. // Function: CsUnregisterAppCategory
  424. //
  425. // Synopsis: Unregister an AppCategory from the Domain.
  426. //
  427. // Used By:
  428. // This is used by Add/Remove programs.
  429. //
  430. // Arguments:
  431. // [in]
  432. // pAppCategoryId:
  433. // Guid (category) that has to be unregistered.
  434. //
  435. // Returns :
  436. // S_OK or CS_E_XXX error codes.
  437. //--------------------------------------------------------------------
  438. STDAPI
  439. CsUnregisterAppCategory (GUID *pAppCategoryId)
  440. {
  441. HRESULT hr = S_OK;
  442. IClassAdmin * pIClassAdmin = NULL;
  443. // get the interface pointer
  444. hr = g_pCF->CreateInstance(
  445. NULL,
  446. IID_IClassAdmin,
  447. (void **)&pIClassAdmin);
  448. if (!SUCCEEDED(hr))
  449. return hr;
  450. // get the app categories list.
  451. hr = pIClassAdmin->UnregisterAppCategory(pAppCategoryId);
  452. // release the interface pointer.
  453. pIClassAdmin->Release();
  454. return hr;
  455. }
  456. //+-------------------------------------------------------------------
  457. //
  458. // Function: CsGetAppCategories
  459. //
  460. // Synopsis: get the definitive list of Application Categories and descriptions
  461. // based on default Locale.
  462. //
  463. // Used By:
  464. // This is used by Add/Remove programs.
  465. //
  466. // *Comments*:
  467. // The caller needs to free the memory allocated using CsMemFree().
  468. //
  469. // Arguments:
  470. // [out]
  471. // AppCategoryList:
  472. // Returned list of GUIDs and Unicode descriptions
  473. //
  474. // Returns :
  475. // S_OK or CS_E_XXX error codes.
  476. //
  477. // Gets the list of Categories published in the Domain.
  478. // The CALLER needs to FREE the memory using Release API.
  479. //--------------------------------------------------------------------
  480. STDAPI
  481. CsGetAppCategories (APPCATEGORYINFOLIST *pAppCategoryList)
  482. {
  483. HRESULT hr = S_OK;
  484. IClassAdmin * pIClassAdmin = NULL;
  485. // get the interface pointer
  486. hr = g_pCF->CreateInstance(
  487. NULL,
  488. IID_IClassAdmin,
  489. (void **)&pIClassAdmin);
  490. if (!SUCCEEDED(hr))
  491. return hr;
  492. // get the app categories list.
  493. hr = pIClassAdmin->GetAppCategories (
  494. GetUserDefaultLCID(),
  495. pAppCategoryList);
  496. // release the interface pointer.
  497. pIClassAdmin->Release();
  498. return hr;
  499. }
  500. //+-------------------------------------------------------------------
  501. //
  502. // Function: CsGetClassStorePath
  503. //
  504. // Synopsis: Returns the class store path.
  505. //
  506. // Used By:
  507. // Winlogon/mmc snapin.
  508. // Arguments:
  509. // [in]
  510. // DSProfilePath:
  511. // Path For the DS Object given to winlogon.
  512. // This is validated here.
  513. //
  514. // [out]
  515. // pCSPath:
  516. // Unicode Path to the class store.
  517. //
  518. // Returns :
  519. // S_OK, or CS_E_XXX error codes.
  520. //
  521. // Looks at the profile object and gets the DEFAULTCLASSSTOREPATH Property.
  522. // The CALLER needs to FREE the memory allocated using CsMemFree().
  523. //--------------------------------------------------------------------
  524. STDAPI
  525. CsGetClassStorePath(LPOLESTR DSProfilePath, LPOLESTR *pCSPath)
  526. {
  527. HRESULT hr;
  528. ULONG ulNoBytes;
  529. //
  530. // Initialize locals
  531. //
  532. hr = S_OK;
  533. //
  534. // Initialize out parameters
  535. //
  536. *pCSPath = NULL;
  537. //
  538. // Validate the ds path string -- make sure it's NULL terminated
  539. //
  540. if ((!DSProfilePath))
  541. ERROR_ON_FAILURE(hr = E_INVALIDARG);
  542. //
  543. // Make sure the ldap prefix is there
  544. //
  545. if (wcsncmp (DSProfilePath, LDAPPREFIX, LDAPPREFIXLENGTH) != 0)
  546. ERROR_ON_FAILURE(hr = E_INVALIDARG);
  547. //
  548. // Now build the class store path. It would be nice if we could use
  549. // BuildADsPathFromParent to do this, but it does not allocate memory
  550. // with CoTaskMemalloc, and the interface to this function requires that
  551. // the returned cs path is freed by the caller with CoTaskMemfree -- thus
  552. // we have to do all the memory allocation and copying ourselfves.
  553. //
  554. // First, get memory -- length is just the length of the current ds path
  555. // in addition to the length for a path separator and the name of the class
  556. // store container
  557. //
  558. ulNoBytes = wcslen(DSProfilePath) * sizeof (WCHAR) +
  559. sizeof (WCHAR) +
  560. sizeof (CLASSSTORECONTAINERNAME);
  561. *pCSPath = (LPOLESTR) CsMemAlloc(ulNoBytes);
  562. if (!(*pCSPath))
  563. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  564. //
  565. // Get the ds path past the prefix so we can use it
  566. // in creating the new path
  567. //
  568. LPOLESTR DSPathWithoutPrefix;
  569. DSPathWithoutPrefix = DSProfilePath + LDAPPREFIXLENGTH;
  570. //
  571. // currently, prefixing LDAP: at the beginning.
  572. //
  573. hr = StringCbPrintf(*pCSPath,
  574. ulNoBytes,
  575. L"%s%s",
  576. LDAPPREFIX CLASSSTORECONTAINERNAME LDAPPATHSEP,
  577. DSPathWithoutPrefix);
  578. if (FAILED(hr))
  579. {
  580. LocalFree(*pCSPath);
  581. *pCSPath = NULL;
  582. }
  583. Error_Cleanup:
  584. return RemapErrorCode(hr, DSProfilePath);
  585. }
  586. //----------------The release APIs-------------------------
  587. STDAPI
  588. ReleasePackageInfo(PACKAGEDISPINFO *pPackageInfo)
  589. {
  590. DWORD i;
  591. if (pPackageInfo)
  592. {
  593. CsMemFree(pPackageInfo->pszScriptPath);
  594. CsMemFree(pPackageInfo->pszPackageName);
  595. for (i = 0; i < (pPackageInfo->cUpgrades); i++)
  596. CsMemFree(pPackageInfo->prgUpgradeInfoList[i].szClassStore);
  597. CsMemFree(pPackageInfo->prgUpgradeInfoList);
  598. CsMemFree(pPackageInfo->pszPublisher);
  599. CsMemFree(pPackageInfo->rgSecurityDescriptor);
  600. CsMemFree(pPackageInfo->pszGpoPath);
  601. CsMemFree(pPackageInfo->pszUrl);
  602. DWORD iCategory;
  603. for ( iCategory = 0; iCategory < pPackageInfo->cCategories; iCategory++ )
  604. {
  605. CsMemFree( pPackageInfo->prgCategories[iCategory] );
  606. }
  607. CsMemFree(pPackageInfo->prgCategories);
  608. DWORD iTransform;
  609. for ( iTransform = 0; iTransform < pPackageInfo->cTransforms; iTransform++ )
  610. {
  611. CsMemFree( pPackageInfo->prgTransforms[iTransform] );
  612. }
  613. CsMemFree( pPackageInfo->prgTransforms );
  614. //
  615. // Destroy all the references in this structure so that
  616. // if this function is called twice in a row on the same
  617. // structure, we do not access invalid memory the second time.
  618. //
  619. memset( pPackageInfo, 0, sizeof( *pPackageInfo ) );
  620. }
  621. return S_OK;
  622. }
  623. STDAPI
  624. ReleaseAppCategoryInfoList(APPCATEGORYINFOLIST *pAppCategoryInfoList)
  625. {
  626. DWORD i;
  627. if (pAppCategoryInfoList)
  628. {
  629. for (i = 0; i < (pAppCategoryInfoList->cCategory); i++)
  630. CsMemFree((pAppCategoryInfoList->pCategoryInfo)[i].pszDescription);
  631. CsMemFree(pAppCategoryInfoList->pCategoryInfo);
  632. memset( pAppCategoryInfoList, 0, sizeof( *pAppCategoryInfoList ) );
  633. }
  634. return S_OK;
  635. }
  636. STDAPI
  637. ReleaseInstallInfo(INSTALLINFO *pInstallInfo)
  638. {
  639. DWORD i;
  640. if (pInstallInfo)
  641. {
  642. CsMemFree(pInstallInfo->pszSetupCommand);
  643. CsMemFree(pInstallInfo->pszScriptPath);
  644. CsMemFree(pInstallInfo->pszUrl);
  645. CsMemFree(pInstallInfo->pClsid);
  646. for (i = 0; i < (pInstallInfo->cUpgrades); i++)
  647. CsMemFree(pInstallInfo->prgUpgradeInfoList[i].szClassStore);
  648. CsMemFree(pInstallInfo->prgUpgradeInfoList);
  649. }
  650. return S_OK;
  651. }
  652. void
  653. ReleaseClassDetail(CLASSDETAIL ClassDetail)
  654. {
  655. DWORD i;
  656. for (i = 0; i < ClassDetail.cProgId; i++)
  657. CsMemFree(ClassDetail.prgProgId[i]);
  658. CsMemFree(ClassDetail.prgProgId);
  659. }
  660. STDAPI
  661. ReleasePackageDetail(PACKAGEDETAIL *pPackageDetail)
  662. {
  663. DWORD i;
  664. if (pPackageDetail)
  665. {
  666. if (pPackageDetail->pActInfo)
  667. {
  668. for (i = 0; i < pPackageDetail->pActInfo->cClasses; i++)
  669. ReleaseClassDetail((pPackageDetail->pActInfo->pClasses)[i]);
  670. CsMemFree(pPackageDetail->pActInfo->pClasses);
  671. for (i = 0; i < pPackageDetail->pActInfo->cShellFileExt; i++)
  672. CsMemFree((pPackageDetail->pActInfo->prgShellFileExt)[i]);
  673. CsMemFree(pPackageDetail->pActInfo->prgShellFileExt);
  674. CsMemFree(pPackageDetail->pActInfo->prgPriority);
  675. CsMemFree(pPackageDetail->pActInfo->prgInterfaceId);
  676. CsMemFree(pPackageDetail->pActInfo->prgTlbId);
  677. CsMemFree(pPackageDetail->pActInfo);
  678. }
  679. if (pPackageDetail->pPlatformInfo)
  680. {
  681. CsMemFree(pPackageDetail->pPlatformInfo->prgPlatform);
  682. CsMemFree(pPackageDetail->pPlatformInfo->prgLocale);
  683. CsMemFree(pPackageDetail->pPlatformInfo);
  684. }
  685. if (pPackageDetail->pInstallInfo)
  686. {
  687. ReleaseInstallInfo(pPackageDetail->pInstallInfo);
  688. CsMemFree(pPackageDetail->pInstallInfo);
  689. }
  690. for (i = 0; i < (pPackageDetail->cSources); i++)
  691. CsMemFree(pPackageDetail->pszSourceList[i]);
  692. CsMemFree(pPackageDetail->pszSourceList);
  693. CsMemFree(pPackageDetail->pszPackageName);
  694. CsMemFree(pPackageDetail->rpCategory);
  695. }
  696. return S_OK;
  697. }
  698. void CsSetOptions( DWORD dwOptions )
  699. {
  700. gCsOptions = dwOptions;
  701. }
  702.