// // Author: DebiM // Date: March 97 // File: csdrt.cxx // // Class Store DRTs // // This is the main source file // The related files are csdrtad.cxx and csdrtgc.cxx // // Current DRTs test: // CClassContainer::IClassAdmin // CClassAccess::IClassAccess // // // It tests the following Class Store functionality // // Admin Interfaces // Browse Interfaces // GetAppInfo() // Tests with multiple class stores // // // To be extended to do: // 2. ACL tests // 3. Tests for error scenarios // 4. More comprehensive // - large no. of CLSIDs per Package // //--------------------------------------------------------------------- #include "csdrt.hxx" BOOL fBrowseTest; BOOL fVerbose; BOOL fAdminTest; BOOL fClassInfoTest; BOOL fClassInfoVerify; BOOL fComprehensive; BOOL fEmptyTest; BOOL fRemoveTest; BOOL fDllTest; BOOL fStress; BOOL fRefreshTest; BOOL fMultiStore; BOOL fCatTest; BOOL fLogonPerf = FALSE; BOOL fLogonPerfInitialize = FALSE; BOOL fOverwritePath = FALSE; BOOL fLogon = FALSE; IClassAccess *pIClassAccess = NULL; IClassAdmin *pIClassAdmin = NULL; IClassAdmin *pIClassAdmin2 = NULL; WCHAR szClassStorePath [2000+1]; WCHAR szContainer [2000+1]; WCHAR szContainer2 [2000+1]; WCHAR szNewContainer [2000+1]; WCHAR szLookupPackageName [_MAX_PATH]; WCHAR szUserName[_MAX_PATH]; WCHAR szPassword[_MAX_PATH]; LPOLESTR pszDomain, pszUser; UINT cLoops = 100; STDAPI_(void) UpdateClassStoreSettings(WCHAR *pwszNewPath); GUID NULLGUID = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x0, 0x00, 0x0, 0x00, 0x00, 0x00 } }; void Usage() { printf ("Usage is\n"); printf (" csdrt [-p] [-v] [-a] [-b] [-g] [-o]\n"); printf (" OR csdrt [-p] [-v] -e\n"); printf (" OR csdrt [-p] [-v] -c\n"); printf (" OR csdrt [-p] [-v] -s [-b] [-l] \n"); printf (" OR csdrt [-p] [-m[]] [-v] -s [-b] [-l] \n"); printf (" where:\n"); printf (" is a DNS pathname for a Class container.\n"); printf (" if absent defaults to env var DRT_CLASSSTORE.\n"); printf (" -v : Verbose.\n"); printf (" -a : Test IClassAdmin functionality.\n"); printf (" -b : Test Browse functionality - IEnumPackage.\n"); printf (" -q : Test Comcat functionality \n"); printf (" -g : Test GetPackageInfo(). -gV for verification. Class store has to be clean before this\n"); printf (" -r : Test IClassRefresh.\n"); printf (" -d : Test entry points in csadm.dll.\n"); printf (" -f : perf tests for IClassAccess. \n"); printf (" -t : Perf for logon procedure. Add I if it has to be initialized. have to be run alone\n"); printf (" -e : Empty the Class Store\n"); printf (" -c : A complete test of functionality.\n"); printf (" -m : Run Multi Class Store Tests. Needs env var DRT_CLASSSTORE2. \n"); printf (" -s : Stress Test. Tests GetClassInfo and Optionally Browse. \n"); printf (" -l : Loop count for Stress Test. Default = 100. Number of packages\n"); printf (" -o : overwrite path \n"); printf (" -u : domain\\user. \n"); printf (" -w : password. \n"); } HRESULT RunComprehensive() { HRESULT hr; VerbosePrint ("Running Comprehensive Suite of Class Store DRTs.\n"); fBrowseTest = fAdminTest = fRemoveTest = fClassInfoTest = fCatTest = fRefreshTest = TRUE; hr = RunTests(); CleanUp(); VerbosePrint ("End of Comprehensive Suite of Class Store DRTs.\n"); return hr; } HRESULT RunStress() { HRESULT hr; ULONG cCount, cPkgCount, cErrCount = 0, cPrevCount = 0; DWORD tc = GetTickCount(); pIClassAccess = NULL; pIClassAdmin = NULL; pIClassAdmin2 = NULL; printf ("Started Class Store Stress for %d passes.\n", cLoops); for (UINT i=0; i < cLoops; ++i) { if (i%100 == 0) // Before every hundredth time { // // Get an IClassAdmin interface pointer // hr = GetClassAdmin (szContainer, &pIClassAdmin); if (!SUCCEEDED(hr)) return hr; // // Get an IClassAccess interface pointer // hr = GetClassAccess (); if (!SUCCEEDED(hr)) return hr; hr = DoRemoveTest (&cPkgCount); hr = DoAdminTest(&cPkgCount); if (!SUCCEEDED(hr)) ++cErrCount; } if (fBrowseTest) { hr = DoBrowseTest(pIClassAdmin); if (!SUCCEEDED(hr)) ++cErrCount; } if (fClassInfoTest) { hr = DoClassInfoTest(); if (!SUCCEEDED(hr)) ++cErrCount; } if ((i+1)%10 == 0) // After every Tenth time { // // Progress Indicator. If errors display a :( else display a :) // if (cErrCount > cPrevCount) { printf (":( "); cPrevCount = cErrCount; } else printf (":) "); } if ((i+1)%100 == 0) // After every Hundredth time { // // Get rid of the interface pointers // CleanUp(); // // Detail Progress indicator // printf ("\n ... %d Stress Passes Completed (with %d Errors).\n", i+1, cErrCount); } } printf ("End of Class Store Stress for %d passes (%d MilliSec Per Loop) (%d Errors).\n", cLoops, (GetTickCount() - tc)/cLoops, cErrCount); return S_OK; } HRESULT RunTests() { HRESULT hr = S_OK; pIClassAccess = NULL; pIClassAdmin = NULL; pIClassAdmin2 = NULL; // // Depending on run parameters // invoke different tests // if (fBrowseTest || fAdminTest || fEmptyTest || fCatTest || fLogonPerfInitialize) { // // Get an IClassAdmin interface pointer // hr = GetClassAdmin (szContainer, &pIClassAdmin); if (!SUCCEEDED(hr)) return hr; if (fMultiStore) { hr = GetClassAdmin (szContainer2, &pIClassAdmin2); if (!SUCCEEDED(hr)) return hr; } } if (fEmptyTest) { VerbosePrint("... Empty Container Test Started.\n"); hr = EmptyClassStore (pIClassAdmin); VerbosePrint("... Empty Container Test Ended.\n"); if (pIClassAdmin2 != NULL) { VerbosePrint("... Empty Container Test on Second Class Store Started.\n"); hr = EmptyClassStore(pIClassAdmin2); VerbosePrint("... Empty Container Test on Second Class Store Ended.\n"); } if (SUCCEEDED(hr)) printf ("PASSED ---- Empty Container Test Suite.\n"); else printf ("FAILED ---- Empty Container Test Suite. hr = 0x%x.\n", hr); } if (fAdminTest) { ULONG cCount, cPkgCount; VerbosePrint("... Admin Test Started.\n"); hr = DoAdminTest(&cPkgCount); VerbosePrint("... Admin Test Ended. (Added %d Packages).\n", cPkgCount); if (SUCCEEDED(hr)) printf ("PASSED ---- Admin Test Suite.\n"); else printf ("FAILED ---- Admin Test Suite. hr = 0x%x.\n", hr); } if (fCatTest) { ULONG cCount, cPkgCount; VerbosePrint("... Comcat Test Started.\n"); hr = DoCatTests(pIClassAdmin, pIClassAdmin2); VerbosePrint("... Admin Test Ended. \n"); if (SUCCEEDED(hr)) printf ("PASSED ---- Comcat Test Suite.\n"); else printf ("FAILED ---- Comcat Test Suite. hr = 0x%x.\n", hr); } if (fBrowseTest) { VerbosePrint("... Browse Test Started.\n"); hr = DoBrowseTest(pIClassAdmin); VerbosePrint("... Browse Test Ended.\n"); if (pIClassAdmin2 != NULL) { VerbosePrint("... Browse Test on Second Class Store Started.\n"); hr = DoBrowseTest(pIClassAdmin2); VerbosePrint("... Browse Test on Second Class Store Ended.\n"); } if (SUCCEEDED(hr)) printf ("PASSED ---- Browse Test Suite.\n"); else printf ("FAILED ---- Browse Test Suite. hr = 0x%x.\n", hr); } if (fClassInfoTest || fRefreshTest) { // // Get an IClassAccess interface pointer // hr = GetClassAccess (); if (!SUCCEEDED(hr)) return hr; } if (fLogonPerf) { // // Measure the performance during a std. logon // hr = DoLogonPerfTest(fLogonPerfInitialize); } if (fRefreshTest) { VerbosePrint("... Refresh Test Started.\n"); hr = RefreshTest (); VerbosePrint("... Refresh Test Ended.\n"); if (SUCCEEDED(hr)) printf ("PASSED ---- Refresh Test Suite.\n"); else printf ("FAILED ---- Refresh Test Suite. hr = 0x%x.\n", hr); } if (fClassInfoTest) { VerbosePrint("... CoEnumApps Test Started.\n"); hr = DoCoEnumAppsTest(); VerbosePrint("... CoEnumApps Test Ended.\n"); VerbosePrint("... Class Store Lookup Test Started.\n"); hr = DoClassInfoTest(); VerbosePrint("... Class Store Lookup Test Ended.\n"); if (SUCCEEDED(hr)) printf ("PASSED ---- Class Store Lookup Test Suite.\n"); else printf ("FAILED ---- Class Store Lookup Test Suite. hr = 0x%x.\n", hr); } if (fRemoveTest) { ULONG cPkgCount; VerbosePrint("... Remove Test Started.\n"); hr = DoRemoveTest(&cPkgCount); VerbosePrint("... Remove Test Ended.(%d Packages).\n", cPkgCount); if (SUCCEEDED(hr)) printf ("PASSED ---- Remove Test Suite.\n"); else printf ("FAILED ---- Remove Test Suite. hr = 0x%x.\n", hr); } if (fDllTest) { /* BUGBUG. Deleted now. Add later. IClassAdmin *pClassAdmin = NULL; extern Sname TestProgId1, TestClassDesc1; extern GUID TestClsid1; // // Test entry points in csadm.dll // VerbosePrint("... Dll Test Started.\n"); // 1. Create an empty store hr = CsCreateClassStore(szNewContainer, L"CN=DrtClassStore"); // 2. Get an IClassAdmin for it. if (SUCCEEDED(hr)) { VerbosePrint ("...... New Class Store created.\n"); wcscat (szNewContainer, L"/"); wcscat (szNewContainer, L"CN=DRTClassStore"); hr = CsGetClassStore(szNewContainer, (void **)&pClassAdmin); } // 3. Use the IClassAdmin to add a class if (SUCCEEDED(hr)) { VerbosePrint ("...... Connected to New Class Store.\n"); CLASSDETAIL ClassDetail; memset (&ClassDetail, NULL, sizeof (CLASSDETAIL)); memcpy (&ClassDetail.Clsid, &TestClsid1, sizeof (GUID)); ClassDetail.pDefaultProgId = TestProgId1; ClassDetail.pszDesc = TestClassDesc1; hr = pClassAdmin->NewClass(&ClassDetail); if (!SUCCEEDED(hr)) { printf ("ERROR! NewClass() returned 0x%x.\n", hr); return hr; } VerbosePrint ("...... Added a class definition.\n"); // 4. Then delete the class hr = pClassAdmin->DeleteClass(TestClsid1); if (!SUCCEEDED(hr)) { printf ("ERROR! DeleteClass() returned 0x%x.\n", hr); return hr; } VerbosePrint ("...... Deleted a class definition.\n"); // 5. Release the IClassAdmin hr = pClassAdmin->Release(); // 6. Delete the Class Store hr = CsDeleteClassStore(szNewContainer); if (!SUCCEEDED(hr)) { printf ("ERROR! Deleting ClassStore.\n", hr); return hr; } VerbosePrint ("...... Deleted the class store.\n"); } VerbosePrint("... Dll Test Ended.\n"); if (SUCCEEDED(hr)) printf ("PASSED ---- Dll Test Suite.\n"); else printf ("FAILED ---- Dll Test Suite. hr = 0x%x.\n", hr); */ } return hr; } void CleanUp() { if (pIClassAdmin) { pIClassAdmin->Release(); pIClassAdmin = NULL; } if (pIClassAdmin2) { pIClassAdmin2->Release(); pIClassAdmin2 = NULL; } if (pIClassAccess) { pIClassAccess->Release(); pIClassAccess = NULL; } } void _cdecl main( int argc, char ** argv ) { HRESULT hr; INT i; LPWSTR szEnvVar; // // Check run parameters // fBrowseTest = FALSE; fVerbose = FALSE; fAdminTest = FALSE; fClassInfoTest = FALSE; fComprehensive = FALSE; fStress = FALSE; fRemoveTest = FALSE; fRefreshTest = FALSE; fMultiStore = FALSE; fEmptyTest = FALSE; fDllTest = FALSE; fCatTest = FALSE; fLogon = FALSE; fLogonPerf = FALSE; fClassInfoVerify = FALSE; szPassword[0] = NULL; szContainer[0] = NULL; szLookupPackageName[0] = NULL; // // Check if the env variable CLASSSTORE is defined // Get the value of the CLASSSTORE environment variable. // szEnvVar = _wgetenv(L"DRT_CLASSSTORE"); // // if so use that as the default path // if (szEnvVar != NULL) { wcscpy (szContainer, szEnvVar); } BOOL fLoop = FALSE; for (i=1; i < argc; ++i) { if (toupper(*argv[i]) != '-') { printf ("ERROR! Parameters must start with a hyphen.\n"); Usage(); return; } switch (toupper(*(argv[i]+1))) { case 'P': MultiByteToWideChar ( CP_ACP, 0, (argv[i]+2), strlen (argv[i]+2) + 1, szContainer, _MAX_PATH); break; case 'E': fEmptyTest = TRUE; break; case 'B': fBrowseTest = TRUE; break; case 'V': fVerbose = TRUE; break; case 'A': fAdminTest = TRUE; break; case 'O': fOverwritePath = TRUE; break; case 'Q': fCatTest = TRUE; break; case 'G': fClassInfoTest = TRUE; if (*(argv[i]+2) == 'V') fClassInfoVerify = TRUE; break; case 'D': fDllTest = TRUE; break; case 'R': fRefreshTest = TRUE; break; case 'M': fMultiStore = TRUE; break; case 'C': fComprehensive = TRUE; break; case 'S': fStress = TRUE; break; case 'L': cLoops = atoi(argv[i]+2); fLoop = TRUE; break; case 'T': fLogonPerf = TRUE; if (*(argv[i]+2) == 'I') fLogonPerfInitialize = TRUE; break; case 'U': MultiByteToWideChar ( CP_ACP, 0, (argv[i]+2), strlen (argv[i]+2) + 1, szUserName, _MAX_PATH); pszDomain = pszUser = &szUserName[0]; while (*pszUser) { if (*pszUser == L'\\') { *pszUser = NULL; pszUser++; break; } pszUser++; } if (*pszUser == NULL) { printf ("ERROR! Incorrect domain\\user specified.\nAborting ...\n"); return; } fLogon = TRUE; break; case 'W': MultiByteToWideChar ( CP_ACP, 0, (argv[i]+2), strlen (argv[i]+2) + 1, szPassword, _MAX_PATH); break; default: Usage(); return; } } if (szContainer[0] == NULL) { // // No default for container and none specified // printf ("ERROR! Class Container not specified and DRT_CLASSSTORE not set.\nAborting ...\n"); return; } if (fMultiStore) { szEnvVar = _wgetenv(L"DRT_CLASSSTORE2"); if (szEnvVar != NULL) { wcscpy (szContainer2, szEnvVar); } else { printf ("ERROR! DRT_CLASSSTORE2 not set. Aborting ...\n"); return; } } if (fDllTest) { szEnvVar = _wgetenv(L"DRT_NEWOU"); if (szEnvVar != NULL) { wcscpy (szNewContainer, szEnvVar); } else { printf ("ERROR! DRT_NEWOU not set. Aborting ...\n"); return; } } if (!(fStress || fEmptyTest || fComprehensive || fBrowseTest || fClassInfoTest || fAdminTest || fCatTest || fLogonPerf)) { printf ("ERROR! No Tests specified. Aborting ...\n"); return; } if (fStress && (fEmptyTest || fComprehensive || fAdminTest || fMultiStore)) { printf ("ERROR! For 'Stress Test' the only options are -g, -b and -l. \nAborting ...\n"); return; } if ((fLogonPerf || fEmptyTest) && (fComprehensive || fBrowseTest || fClassInfoTest || fAdminTest)) { printf ("ERROR! Cant combine Empty or Logon Tests with any other test. \nAborting ...\n"); return; } if (fComprehensive && (fBrowseTest || fClassInfoTest || fAdminTest)) { printf ("ERROR! Cant combine 'Comprehensive Test Suite' with any other individual tests. \nAborting ...\n"); return; } if (fStress && (!(fBrowseTest || fClassInfoTest ))) { fClassInfoTest = TRUE; } if (fLoop) { if (!fStress) { printf ("ERROR! Loop count applies only to Stress Test. Aborting ...\n"); return; } else { if (cLoops%100 != 0) { printf ("ERROR! Loop count can only be in multiple of 100s. Aborting ...\n"); return; } } } // // If test is to be run for a different user, // do LogonUser // if (fLogon) { HANDLE hToken; BOOLEAN fEnable; NTSTATUS NtStatus; printf( "Will run test as user: %S, domain: %S.\n", pszUser, pszDomain); NtStatus = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, FALSE, &fEnable); if ( NtStatus != STATUS_SUCCESS ) { printf( "ERROR! In RtlAdjustPrivilege. 0x%x. Aborting ...\n", NtStatus); return; } if (!LogonUser( pszUser, // string that specifies the user name pszDomain, // string that specifies the domain or server szPassword, // string that specifies the password LOGON32_LOGON_INTERACTIVE, // specifies the type of logon operation LOGON32_PROVIDER_DEFAULT, // specifies the logon provider &hToken // pointer to variable to receive token handle )) { printf( "ERROR! Invalid username or password - 0x%x. Aborting ...\n", GetLastError()); return; } if (!ImpersonateLoggedOnUser(hToken)) { printf( "ERROR! Impersonation failed. Aborting ...\n"); return; } CloseHandle(hToken); } hr = CoInitialize(NULL); if( FAILED(hr) ) { printf( "ERROR! Client CoInitialize failed Ox%x. Aborting ...\n", hr ); return; } VerbosePrint ("Using Class Store at:\n %S.\n", szContainer); if (fMultiStore) VerbosePrint ("Using Class Store 2 at:\n %S.\n", szContainer2); if (fOverwritePath) { // Flush Class Store Cache and Overwrite Path UpdateClassStoreSettings(szContainer); VerbosePrint("... Overwrote Class Store Path.\n"); } else { GetUserClassStore(szClassStorePath); VerbosePrint ("Profile ClassStore:\n %S.\n", szClassStorePath); // // Verify that the Profile matches the input. // if (NULL == wcsstr(szClassStorePath, szContainer)) { printf( "Warning! Class Store is different from Profile.\n"); } if (NULL == wcsstr(szClassStorePath, szContainer2)) { printf( "Warning! Second Class Store is different from Profile.\n"); } } InitTempNames(); if (fComprehensive) { hr = RunComprehensive(); } else { if (fStress) { fVerbose = FALSE; hr = RunStress(); } else { hr = RunTests(); CleanUp(); } } CoUninitialize(); } // // This routine takes a pathname and binds to a Class container // and returns an IClassAdmin interface pointer // HRESULT GetClassAdmin (LPOLESTR pszPath, IClassAdmin **ppCA) { HRESULT hr; LPOLESTR szPath; *ppCA = NULL; if (wcsncmp (pszPath, L"ADCS:", 5) == 0) { szPath = pszPath + 5; } else szPath = pszPath; hr = CsGetClassStore(szPath, (void **)ppCA); if ( FAILED(hr) ) { printf("ERROR! Could not get IClassAdmin. Error- 0x%x\n", hr); return hr; } return S_OK; } // // This routine binds to a CClassAccess on the desktop and // returns an IClassAccess interface pointer // HRESULT GetClassAccess () { HRESULT hr; pIClassAccess = NULL; hr = CsGetClassAccess (&pIClassAccess); if ( FAILED(hr) ) { printf("ERROR! Could not get IClassAccess. Error- 0x%x\n", hr); return hr; } return S_OK; } void GetDefaultPlatform(CSPLATFORM *pPlatform) { OSVERSIONINFO VersionInformation; VersionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&VersionInformation); pPlatform->dwPlatformId = VersionInformation.dwPlatformId; pPlatform->dwVersionHi = VersionInformation.dwMajorVersion; pPlatform->dwVersionLo = VersionInformation.dwMinorVersion; pPlatform->dwProcessorArch = DEFAULT_ARCHITECTURE; } // // This routine enumerates all classes, packages and // cleans up the entire Class Container by deleting these objects. // HRESULT EmptyClassStore (IClassAdmin *pIClassAdmin) { HRESULT hr; ULONG cCount; hr = EnumPackagesAndDelete(pIClassAdmin, TRUE, &cCount); if (!SUCCEEDED(hr)) return hr; VerbosePrint ("...... Deleted all %d Packages.\n", cCount); return S_OK; } // // This routine enumerates all classes and packages // HRESULT DoBrowseTest (IClassAdmin *pCA) { HRESULT hr; ULONG cCount; hr = EnumPackagesAndDelete(pCA, FALSE, &cCount); if (!SUCCEEDED(hr)) return hr; VerbosePrint ("...... Browsed %d Packages.\n", cCount); return S_OK; } void PrintPackageInfo(PACKAGEDISPINFO *pPackageInfo) { SYSTEMTIME SystemTime; if (fVerbose) { FileTimeToSystemTime( (CONST FILETIME *)(&pPackageInfo->Usn), &SystemTime); VerbosePrint("........ Package: %S \n........ Last Update: %d-%d-%d %d:%d:%d\n", pPackageInfo->pszPackageName, SystemTime.wMonth, SystemTime.wDay, SystemTime.wYear, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond); VerbosePrint("........ Script Size = %d. Path = %S\n", pPackageInfo->cScriptLen, pPackageInfo->pszScriptPath); } } void PrintInstallInfo(INSTALLINFO *pInstallInfo) { SYSTEMTIME SystemTime; FileTimeToSystemTime( (CONST FILETIME *)(&pInstallInfo->Usn), &SystemTime); VerbosePrint("........ Script: %S (Size = %d)\n........ Last Update: %d-%d-%d %d:%d:%d\n", pInstallInfo->pszScriptPath, pInstallInfo->cScriptLen, SystemTime.wMonth, SystemTime.wDay, SystemTime.wYear, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond); } /* void PrintCategoryDetail(CATEGORYINFO *pCatInfo) { VerbosePrint("........ Category Description: %S\n", pCatInfo->szDescription); } */ HRESULT EnumPackagesAndDelete(IClassAdmin *pIClassAdmin, BOOL fDelete, ULONG *pcPackages) { ULONG cFetched; IEnumPackage *pIEnumPackage = NULL; HRESULT hr; PACKAGEDISPINFO PackageInfo; *pcPackages=0; hr = pIClassAdmin->EnumPackages( NULL, NULL, 0, NULL, NULL, &pIEnumPackage); if ( FAILED(hr)) { printf("ERROR! EnumPackages returned 0x%x\n", hr); return hr; } while (TRUE) { memset (&PackageInfo, 0, sizeof(PACKAGEDISPINFO)); hr = pIEnumPackage->Next(1, &PackageInfo, &cFetched); if (FAILED(hr)) { break; } if ((hr == S_FALSE) || (cFetched < 1)) { hr = S_OK; break; } (*pcPackages)++; if (fVerbose && !fDelete) { PrintPackageInfo(&PackageInfo); } if (fDelete) { hr = pIClassAdmin->RemovePackage(PackageInfo.pszPackageName, 0); } ReleasePackageInfo(&PackageInfo); } pIEnumPackage->Release(); if (fVerbose) { if (!SUCCEEDED(hr)) printf("ERROR! 0x%x.\n", hr); } return hr; } /* HRESULT EnumCategoriesAndDelete (IClassAdmin *pIClassAdmin, BOOL fDelete, ULONG *pcCategories) { ULONG cFetched; IEnumCATEGORYINFO *pIEnumCat; HRESULT hr; CATEGORYINFO CatInfo; ICatRegister *pICatReg; ICatInformation *pICatInfo; LCID lcid = 0; *pcCategories = 0; hr = pIClassAdmin->QueryInterface(IID_ICatRegister, (void **)&pICatReg); if (FAILED(hr)) { printf("Error! QI CR hr = 0x%x\n", hr); return hr; } hr = pIClassAccess->QueryInterface(IID_ICatInformation, (void **)&pICatInfo); if (FAILED(hr)) { printf("Error! QI CI hr = 0x%x\n", hr); return hr; } hr = pICatInfo->EnumCategories(lcid, &pIEnumCat); if ( FAILED(hr)) { return hr; } while (TRUE) { hr = pIEnumCat->Next(1, &CatInfo, &cFetched); if (FAILED(hr)) { break; } if ((hr == S_FALSE) || (cFetched < 1)) { hr = S_OK; break; } (*pcCategories)++; if (fVerbose && !fDelete) { PrintCategoryDetail(&CatInfo); } if (fDelete) { hr = pICatReg->UnRegisterCategories(1, &(CatInfo.catid)); if (!SUCCEEDED(hr)) break; } } pIEnumCat->Release(); if (fVerbose) { if (!SUCCEEDED(hr)) printf("ERROR! 0x%x.\n", hr); } pICatReg->Release(); pICatInfo->Release(); return hr; } */ void ReleasePackageDetail(PACKAGEDETAIL *pPackageDetail, BOOL fPartial) { if (pPackageDetail->pActInfo) { CoTaskMemFree(pPackageDetail->pActInfo->prgShellFileExt); CoTaskMemFree(pPackageDetail->pActInfo->prgPriority); CoTaskMemFree(pPackageDetail->pActInfo->prgInterfaceId); CoTaskMemFree(pPackageDetail->pActInfo->prgTlbId); CoTaskMemFree(pPackageDetail->pActInfo); } if (pPackageDetail->pPlatformInfo) { CoTaskMemFree(pPackageDetail->pPlatformInfo->prgPlatform); CoTaskMemFree(pPackageDetail->pPlatformInfo->prgLocale); CoTaskMemFree(pPackageDetail->pPlatformInfo); } if (pPackageDetail->pInstallInfo) { if (!fPartial) ReleaseInstallInfo(pPackageDetail->pInstallInfo); CoTaskMemFree(pPackageDetail->pInstallInfo); } CoTaskMemFree(pPackageDetail->pszSourceList); CoTaskMemFree(pPackageDetail->rpCategory); } void GetUserClassStore(LPWSTR szPath) { LONG lErrorCode; DWORD dwDataLen = 1000; DWORD dwType; HKEY hKey = NULL; HRESULT hr = S_OK; *szPath = NULL; lErrorCode = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\ClassStore", NULL, KEY_ALL_ACCESS, &hKey); if ( lErrorCode != ERROR_SUCCESS) { return; } lErrorCode = RegQueryValueEx(hKey, L"Path", NULL, &dwType, (LPBYTE)szPath, &dwDataLen); RegCloseKey(hKey); return; }