|
|
/*===================================================================
Microsoft IIS
Microsoft Confidential. Copyright 1997 Microsoft Corporation. All Rights Reserved.
Component: WAMREG
File: mtsconfig.cpp
implementation of supporting functions for WAMREG, including
interface to Add/Remove Component from a MTS package,
History: LeiJin created on 9/24/1997
Note:
===================================================================*/ #include "common.h"
#include "auxfunc.h"
#include "comadmii.c"
#include "dbgutil.h"
#include "export.h"
/*===================================================================
Define the global variables and types ======================================================================*/
//
// Following is a list of all the WAMREG/MTS properties for Package creation
// Format:
// (prop-symbolic-name, property-name-string)
//
// WAMREG_MTS_PROPERTY() -> means property for NT & Win9x
// WAMREG_MTS_NTPROPERTY() -> means property for NT only
//
# define ALL_WAMREG_MTS_PROPERTY() \
WAMREG_MTS_PROPERTY( WM_ID, L"ID") \ WAMREG_MTS_PROPERTY( WM_NAME, L"Name") \ WAMREG_MTS_PROPERTY( WM_CREATED_BY, L"CreatedBy") \ WAMREG_MTS_PROPERTY( WM_RUN_FOREVER, L"RunForever") \ WAMREG_MTS_NTPROPERTY( WM_IDENTITY, L"Identity") \ WAMREG_MTS_NTPROPERTY( WM_PASSWORD, L"Password") \ WAMREG_MTS_PROPERTY( WM_ACTIVATION, L"Activation") \ WAMREG_MTS_PROPERTY( WM_CHANGEABLE, L"Changeable") \ WAMREG_MTS_PROPERTY( WM_DELETABLE, L"Deleteable") \ WAMREG_MTS_PROPERTY( WM_SECSUPP, L"AccessChecksLevel") \
//
// Let us expand the macros here for defining the symbolic-name
//
//
# define WAMREG_MTS_PROPERTY( symName, pwsz) symName,
# define WAMREG_MTS_NTPROPERTY( symName, pwsz) symName,
enum WAMREG_MTS_PROP_NAMES { ALL_WAMREG_MTS_PROPERTY() MAX_WAMREG_MTS_PROP_NAMES // sentinel element
};
# undef WAMREG_MTS_PROPERTY
# undef WAMREG_MTS_NTPROPERTY
struct MtsProperty { LPCWSTR m_pszPropName; BOOL m_fWinNTOnly; };
//
// Let us expand the macros here for defining the property strings
//
//
# define WAMREG_MTS_PROPERTY( symName, pwsz) { pwsz, FALSE },
# define WAMREG_MTS_NTPROPERTY( symName, pwsz) { pwsz, TRUE },
static const MtsProperty g_rgWamRegMtsProperties[]= { ALL_WAMREG_MTS_PROPERTY() { NULL, FALSE} // sentinel element
};
# define NUM_WAMREG_MTS_PROPERTIES \
((sizeof(g_rgWamRegMtsProperties)/sizeof(g_rgWamRegMtsProperties[0])) - 1)
# undef WAMREG_MTS_PROPERTY
# undef WAMREG_MTS_NTPROPERTY
/*===================================================================
WamRegPackageConfig
Constructor.
Parameter: NONE; ===================================================================*/ WamRegPackageConfig::WamRegPackageConfig() : m_pCatalog(NULL), m_pPkgCollection(NULL), m_pCompCollection(NULL), m_pPackage(NULL) {
}
/*===================================================================
~WamRegPackageConfig
Destructor. By the time the object gets destructed, all resources should be freed. We do most of the cleanup inside WamReqPackageConfig::Cleanup() so that callers call that function separately to cleanup state especially if the caller also calls CoUninitialize(). WamRegPackageConfig should be cleaned up before CoUninitialize()
Parameter: NONE; ===================================================================*/ WamRegPackageConfig::~WamRegPackageConfig() { Cleanup();
// insane checks to ensure everything is happy here
DBG_ASSERT(m_pCatalog == NULL); DBG_ASSERT(m_pPkgCollection == NULL); DBG_ASSERT(m_pCompCollection == NULL); DBG_ASSERT(m_pPackage == NULL); }
VOID WamRegPackageConfig::Cleanup(VOID) { if (m_pPackage != NULL ) { RELEASE( m_pPackage); m_pPackage = NULL; } if (m_pCompCollection != NULL) { RELEASE (m_pCompCollection); m_pCompCollection = NULL; }
if (m_pPkgCollection != NULL ) { RELEASE(m_pPkgCollection); m_pPkgCollection = NULL; }
if (m_pCatalog != NULL ) { RELEASE(m_pCatalog); m_pCatalog = NULL; }
} // WamPackageConfig::Cleanup()
/*===================================================================
ReleaseAll
Release all resources.
Parameter: NONE; ===================================================================*/ VOID WamRegPackageConfig::ReleaseAll ( ) { RELEASE(m_pPackage); RELEASE(m_pCompCollection);
//
// NOTE: I am not releasing m_pCatalog, m_pPkgCollection
// These will be released by the Cleanup().
//
}
/*===================================================================
CreateCatalog
CoCreateObject of an MTS Catalog object if the Catalog object has not been created.
Parameter: NONE; ===================================================================*/ HRESULT WamRegPackageConfig::CreateCatalog ( VOID ) { HRESULT hr = NOERROR;
DBG_ASSERT(m_pCatalog == NULL); DBG_ASSERT(m_pPkgCollection == NULL);
// Create instance of the catalog object
hr = CoCreateInstance(CLSID_COMAdminCatalog , NULL , CLSCTX_SERVER , IID_ICOMAdminCatalog , (void**)&m_pCatalog);
if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to CoCreateInstance of Catalog Object.,hr = %08x\n", hr)); } else { DBG_ASSERT(m_pCatalog != NULL);
BSTR bstr; //
// Get the Packages collection
//
bstr = SysAllocString(L"Applications"); hr = m_pCatalog->GetCollection(bstr, (IDispatch**)&m_pPkgCollection); FREEBSTR(bstr); if (FAILED(hr)) {
DBGPRINTF((DBG_CONTEXT, "m_pCatalog(%08x)->GetCollection() failed, hr = %08x\n", m_pCatalog, hr)); } else { DBG_ASSERT( m_pPkgCollection != NULL); } }
return hr; } // WamRegPackageConfig::CreateCatalog()
/*===================================================================
SetCatalogObjectProperty
Get a SafeArray contains one ComponentCLSID
Parameter: szComponentCLSID the CLSID need to be put in the safe array paCLSIDs pointer to a pointer of safe array(safe array provided by caller).
Return: HRESULT Side Affect:
Note: ===================================================================*/ HRESULT WamRegPackageConfig::GetSafeArrayOfCLSIDs ( IN LPCWSTR szComponentCLSID, OUT SAFEARRAY** paCLSIDs ) { SAFEARRAY* aCLSIDs = NULL; SAFEARRAYBOUND rgsaBound[1]; LONG Indices[1]; VARIANT varT; HRESULT hr = NOERROR;
DBG_ASSERT(szComponentCLSID && paCLSIDs); DBG_ASSERT(*paCLSIDs == NULL); // PopulateByKey is expecting a SAFEARRAY parameter input,
// Create a one element SAFEARRAY, the one element of the SAFEARRAY contains
// the packageID.
rgsaBound[0].cElements = 1; rgsaBound[0].lLbound = 0; aCLSIDs = SafeArrayCreate(VT_VARIANT, 1, rgsaBound);
if (aCLSIDs) { Indices[0] = 0;
VariantInit(&varT); varT.vt = VT_BSTR; varT.bstrVal = SysAllocString(szComponentCLSID); hr = SafeArrayPutElement(aCLSIDs, Indices, &varT); VariantClear(&varT);
if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to call SafeArrayPutElement, CLSID is %S, hr %08x\n", szComponentCLSID, hr)); if (aCLSIDs != NULL) { HRESULT hrT = SafeArrayDestroy(aCLSIDs); if (FAILED(hrT)) { DBGPRINTF((DBG_CONTEXT, "Failed to call SafeArrayDestroy(aCLSIDs), hr = %08x\n", hr)); } aCLSIDs = NULL; } } } else { hr = HRESULT_FROM_WIN32(GetLastError()); DBGPRINTF((DBG_CONTEXT, "Failed to call SafeArrayCreate, hr %08x\n", hr)); }
*paCLSIDs = aCLSIDs; return hr; }
/*===================================================================
SetComponentObjectProperty
Set component level property.
Parameter: pComponent - pointer to the ICatalogObject(MTS) used to update property szPropertyName - Name of the property szPropertyValue- Value of the property fPropertyValue - If szPropertyValue is NULL, use fPropertyValue
Return: HRESULT Side Affect:
Note: ===================================================================*/ HRESULT WamRegPackageConfig::SetComponentObjectProperty ( IN ICatalogObject * pComponent, IN LPCWSTR szPropertyName, IN LPCWSTR szPropertyValue, BOOL fPropertyValue ) { BSTR bstr = NULL; HRESULT hr = NOERROR; VARIANT varT; VariantInit(&varT); bstr = SysAllocString(szPropertyName);
if (szPropertyValue != NULL) { varT.vt = VT_BSTR; varT.bstrVal = SysAllocString(szPropertyValue); } else { //
// COM+ regcongize -1 as TRUE, and 0 as FALSE. I believe the root is from VB.
//
varT.vt = VT_BOOL; varT.boolVal = (fPropertyValue) ? -1 : 0; } hr = pComponent->put_Value(bstr, varT); FREEBSTR(bstr); VariantClear(&varT);
if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "MTS-Component(%08x)::SetProperty(%S => %S) failed;" " hr %08x\n", pComponent, szPropertyName, szPropertyValue, hr)); } return hr; }
/*===================================================================
WamRegPackageConfig::SetComponentObjectProperties()
Sets the componnet properties for newly created component that houses the WAM unit
Parameter: szComponentCLSID - CLSID for the component that is newly created
Return: HRESULT
Side Affect: If there is a failure all the previously set values are not cleared. The caller should make sure that the proper cleanup of package happens on partial errors.
Note: ===================================================================*/ HRESULT WamRegPackageConfig::SetComponentObjectProperties( IN LPCWSTR szComponentCLSID ) { HRESULT hr; SAFEARRAY* aCLSIDs = NULL; long lCompCount = 0; ICatalogObject* pComponent = NULL; BOOL fFound;
DBG_ASSERT( m_pCompCollection != NULL);
//
// Create the array containing the CLSIDs from the component name
// this will be used to find our object in MTS and set properties
// on the same
//
hr = GetSafeArrayOfCLSIDs(szComponentCLSID, &aCLSIDs); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed in GetSafeArrayOfCLSIDs(%S). hr=%08x\n", szComponentCLSID, hr)); goto LErrExit; } hr = m_pCompCollection->PopulateByKey(aCLSIDs); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to call PopulateByKey(), hr = %08x\n", hr)); goto LErrExit; }
// Find our component in the list (should be the only one)
hr = m_pCompCollection->get_Count(&lCompCount); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed in CompCollection(%08x)::get_Count(). hr = %08x\n", m_pCompCollection, hr)); goto LErrExit; }
//
// Load the component object so that we can set properties
//
fFound = FALSE; if (SUCCEEDED(hr) && lCompCount == 1) { hr = m_pCompCollection->get_Item(0, (IDispatch**)&pComponent); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed in CompCollection(%08x)::get component() hr=%08x\n", m_pCompCollection, hr)); goto LErrExit; } else {
// Found it
DBG_ASSERT(pComponent); fFound = TRUE; } } if (fFound) {
//
// Component Properties InProc OutOfProc
// --------------------- -------- ----------
// Synchronization 0 same
// Transaction "Not Supported" same
// JustInTimeActivation N same
// IISIntrinsics N same
// COMTIIntrinsics N same
// ComponentAccessChecksEnabled 0 same
hr = SetComponentObjectProperty( pComponent, L"Synchronization", L"0"); if (FAILED(hr)) { goto LErrExit; } hr = SetComponentObjectProperty( pComponent, L"ComponentAccessChecksEnabled", L"0"); if (FAILED(hr)) { goto LErrExit; } hr = SetComponentObjectProperty( pComponent, L"Transaction", L"0"); if (FAILED(hr)) { goto LErrExit; } hr = SetComponentObjectProperty( pComponent, L"JustInTimeActivation",NULL,FALSE); if (FAILED(hr)) { goto LErrExit; }
hr = SetComponentObjectProperty( pComponent, L"IISIntrinsics", NULL, FALSE); if (FAILED(hr)) { goto LErrExit; }
hr = SetComponentObjectProperty( pComponent, L"COMTIIntrinsics", NULL, FALSE); if (FAILED(hr)) { goto LErrExit; } hr = SetComponentObjectProperty(pComponent, L"EventTrackingEnabled", L"N"); if (FAILED(hr)) { goto LErrExit; } } else {
DBGPRINTF((DBG_CONTEXT, "Unable to find newly create WAM component in package\n")); DBG_ASSERT(FALSE); }
LErrExit: RELEASE(pComponent); if (aCLSIDs != NULL) {
HRESULT hrT = SafeArrayDestroy(aCLSIDs); if (FAILED(hrT)) { DBGPRINTF((DBG_CONTEXT, "Failed to call SafeArrayDestroy(aCLSIDs=%08x)," " hr = %08x\n", aCLSIDs, hr)); } aCLSIDs = NULL; } return ( hr); } // // WamRegPackageConfig::SetComponentObjectProperties()
/*===================================================================
SetPackageObjectProperty
Set package level property.
Parameter: szPropertyName Name of the property szPropertyValue Value of the property
Return: HRESULT Side Affect:
Note: ===================================================================*/ HRESULT WamRegPackageConfig::SetPackageObjectProperty ( IN LPCWSTR szPropertyName, IN LPCWSTR szPropertyValue ) { BSTR bstr = NULL; HRESULT hr = NOERROR; VARIANT varT;
VariantInit(&varT); bstr = SysAllocString(szPropertyName); varT.vt = VT_BSTR; varT.bstrVal = SysAllocString(szPropertyValue); DBG_ASSERT(m_pPackage != NULL); hr = m_pPackage->put_Value(bstr, varT); FREEBSTR(bstr); VariantClear(&varT);
if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Set Catalog Object Property failed, " "Component is %S, hr %08x\n", szPropertyName, hr)); } return hr; } // WamRegPackageConfig::SetPackageObjectProperty()
/*===================================================================
WamRegPackageConfig::SetPackageProperties()
Sets package properties for all WAMREG properties.
Parameter: rgpszValues: An array containing pointers to string values to be used for setting up the WAMREG related properites for MTS catalog.
Return: HRESULT Side Affect: If there is a failure all the previously set values are not cleared. The caller should make sure that the proper cleanup of package happens on partial errors.
Note: ===================================================================*/ HRESULT WamRegPackageConfig::SetPackageProperties ( IN LPCWSTR * rgpszValues ) { HRESULT hr = NOERROR;
DBG_ASSERT( m_pPackage);
//
// Loop through all properties and set the values for these
// properties using the passed in array of strings.
// UGLY: MTS likes to have string properties which need to be
// fed in as BSTRs => very inefficient.
//
for (DWORD i = 0; i < NUM_WAMREG_MTS_PROPERTIES; i++) {
if ( (TsIsWindows95() && g_rgWamRegMtsProperties[i].m_fWinNTOnly) || (rgpszValues[i] == NULL) ) { //
// This parameter is for Win95 only
// Or this parameter is required only for certain cases.
// Skip this parameter.
//
continue; }
DBG_ASSERT( rgpszValues[i] != NULL);
IF_DEBUG( WAMREG_MTS) { DBGPRINTF(( DBG_CONTEXT, "In Package(%08x) setting property %S to value %S\n", m_pPackage, g_rgWamRegMtsProperties[i].m_pszPropName, rgpszValues[i] )); }
//
// Now let us set up the property in the MTS package
//
hr = SetPackageObjectProperty(g_rgWamRegMtsProperties[i].m_pszPropName, rgpszValues[i]); if ( FAILED (hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to set property %S, value is %S\n", g_rgWamRegMtsProperties[i].m_pszPropName, rgpszValues[i])); break; } } // for all properties
return (hr); } // WamRegPackageConfig::SetPackageProperties()
BOOL WamRegPackageConfig::IsPackageInstalled ( IN LPCWSTR szPackageID, IN LPCWSTR szComponentCLSID ) /*++
Routine Description:
Determine if the WAM package is installed and is valid. Currently this is only called by setup.
Parameters
IN LPCWSTR szPackageID - Package ID IN LPCWSTR szComponentCLSID - Component CLSID
Return Value
BOOL - True if package contains the component. False otherwise.
--*/ { HRESULT hr; SAFEARRAY* aCLSIDs = NULL; SAFEARRAY* aCLSIDsComponent = NULL;
DBG_ASSERT( m_pCatalog != NULL); DBG_ASSERT( m_pPkgCollection != NULL);
long lPkgCount; BOOL fFound = FALSE; ICatalogCollection* pCompCollection = NULL; // Only use the trace macro here, even for error conditions.
// This routine may fail in a variety of ways, but we expect
// to be able to fix any of them, only report an error if
// the failure is likely to impair the functionality of the
// server.
SETUP_TRACE(( DBG_CONTEXT, "CALL - IsPackageInstalled, Package(%S) Component(%S)\n", szPackageID, szComponentCLSID ));
//
// Get the package
//
hr = GetSafeArrayOfCLSIDs(szPackageID, &aCLSIDs); if (FAILED(hr)) { SETUP_TRACE(( DBG_CONTEXT, "Failed to GetSafeArrayOfCLSIDs for %S, hr = %08x\n", szPackageID, hr )); goto LErrExit; }
hr = m_pPkgCollection->PopulateByKey(aCLSIDs); if (FAILED(hr)) { SETUP_TRACE(( DBG_CONTEXT, "Failed in m_pPkgCollection(%p)->PopulateByKey(), hr = %08x\n", m_pPkgCollection, hr )); goto LErrExit; } hr = m_pPkgCollection->get_Count(&lPkgCount); if (SUCCEEDED(hr) && lPkgCount == 1) { //
// We found the package. Now verify that it contains our component.
//
SETUP_TRACE(( DBG_CONTEXT, "Successfully retrieved package (%S).\n", szPackageID ));
VARIANT varKey; BSTR bstrComponentCollection;
VariantInit(&varKey); varKey.vt = VT_BSTR; varKey.bstrVal = SysAllocString(szPackageID);
// Get the "ComponentsInPackage" collection.
bstrComponentCollection = SysAllocString(L"Components"); hr = m_pPkgCollection->GetCollection( bstrComponentCollection, varKey, (IDispatch**)&pCompCollection ); FREEBSTR(bstrComponentCollection); VariantClear(&varKey); if (FAILED(hr)) { SETUP_TRACE(( DBG_CONTEXT, "Failed in m_pPkgCollection(%p)->GetCollection(), hr = %08x\n", m_pPkgCollection, hr )); goto LErrExit; }
hr = GetSafeArrayOfCLSIDs(szComponentCLSID, &aCLSIDsComponent); if (FAILED(hr)) { SETUP_TRACE(( DBG_CONTEXT, "Failed to GetSafeArrayOfCLSIDs for %S, hr = %08x\n", szComponentCLSID, hr )); goto LErrExit; }
hr = pCompCollection->PopulateByKey( aCLSIDsComponent ); if( FAILED(hr) ) { SETUP_TRACE(( DBG_CONTEXT, "Failed in pCompCollection(%p)->PopulateByKey, hr = %08x\n", pCompCollection, hr )); goto LErrExit; }
hr = pCompCollection->get_Count( &lPkgCount ); if( SUCCEEDED(hr) && lPkgCount == 1 ) { // Success! We found the package and it contains the
// correct component.
SETUP_TRACE(( DBG_CONTEXT, "Successfully retrieved component (%S) from package (%S).\n", szComponentCLSID, szPackageID ));
fFound = TRUE; } }
LErrExit: if (aCLSIDs != NULL) { SafeArrayDestroy(aCLSIDs); aCLSIDs = NULL; }
if( aCLSIDsComponent != NULL ) { SafeArrayDestroy(aCLSIDsComponent); aCLSIDsComponent = NULL; } RELEASE( pCompCollection );
SETUP_TRACE(( DBG_CONTEXT, "RETURN - IsPackageInstalled, hr=%08x\n", hr )); return fFound; } /*===================================================================
RemovePackage
Remove a Viper Package.
Parameter: szPackageID: an MTS package ID.
Return: HRESULT Side Affect:
Note: Remove an IIS package from MTS. So far, only been called from RemoveIISPackage. RemoveComponentFromPackage() also removes a IIS package sometimes. Refer to that function header for info. ===================================================================*/ HRESULT WamRegPackageConfig::RemovePackage ( IN LPCWSTR szPackageID ) { HRESULT hr = NOERROR; long lPkgCount = 0; long lChanges; SAFEARRAY* aCLSIDs = NULL; DBG_ASSERT(szPackageID); DBG_ASSERT( m_pCatalog != NULL); DBG_ASSERT( m_pPkgCollection != NULL);
hr = GetSafeArrayOfCLSIDs(szPackageID, &aCLSIDs); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to get SafeArrayofCLSIDs, szPackageID is %S, hr %08x", szPackageID, hr)); goto LErrExit; } //
// Populate it
//
hr = m_pPkgCollection->PopulateByKey(aCLSIDs); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to call PopulateByKey(), hr = %08x\n", hr)); goto LErrExit; } hr = m_pPkgCollection->get_Count(&lPkgCount); if (FAILED(hr)) { IF_DEBUG(ERROR) { DBGPRINTF((DBG_CONTEXT, "pPkgCollection->Populate() failed, hr = %08x\n", hr)); } goto LErrExit; } if (SUCCEEDED(hr) && lPkgCount == 1) { hr = m_pPkgCollection->get_Item(0, (IDispatch**)&m_pPackage); if (FAILED(hr)) { goto LErrExit; } // Found it - remove it and call Save Changes
// First, Set Deleteable = Y property on package
hr = SetPackageObjectProperty(L"Deleteable", L"Y"); if (FAILED(hr)) { goto LErrExit; }
RELEASE(m_pPackage); // Let save the Deletable settings
hr = m_pPkgCollection->SaveChanges(&lChanges); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Save the Deletable settings failed, hr = %08x\n", hr)); goto LErrExit; } // Now we can delete
hr = m_pPkgCollection->Remove(0); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Remove the Component from package failed, hr = %08x\n", hr)); goto LErrExit; }
// Aha, we should be able to delete now.
hr = m_pPkgCollection->SaveChanges(&lChanges); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Save changes failed, hr = %08x\n", hr)); goto LErrExit; } }
LErrExit: if (aCLSIDs != NULL) { HRESULT hrT = SafeArrayDestroy(aCLSIDs); if (FAILED(hrT)) { DBGPRINTF((DBG_CONTEXT, "Failed to call SafeArrayDestroy(aCLSIDs), hr = %08x\n", hr)); } aCLSIDs = NULL; } ReleaseAll(); return hr; }
/*===================================================================
CreatePackage
Create a viper package.
Parameter: szPackageID: [in] Viper Package ID. szPackageName: [in] the name of the package. szIdentity: [in] Pakcage identity szIdPassword: [in] Package idneitty password fInProc: [in] Inproc or outproc package
Return: HRESULT Side Affect: NONE.
===================================================================*/ HRESULT WamRegPackageConfig::CreatePackage ( IN LPCWSTR szPackageID, IN LPCWSTR szPackageName, IN LPCWSTR szIdentity, IN LPCWSTR szIdPassword, IN BOOL fInProc ) { HRESULT hr; SAFEARRAY* aCLSIDs = NULL;
DBG_ASSERT( m_pCatalog != NULL); DBG_ASSERT( m_pPkgCollection != NULL);
long lPkgCount; BOOL fFound = FALSE;
SETUP_TRACE(( DBG_CONTEXT, "CALL - CreatePackage ID(%S) Name(%S)\n", szPackageID, szPackageName )); //
// Try to get the package.
//
SETUP_TRACE(( DBG_CONTEXT, "Checking to see if package ID(%S) Name(%S) exists.\n", szPackageID, szPackageName ));
hr = GetSafeArrayOfCLSIDs(szPackageID, &aCLSIDs); if (FAILED(hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed to GetSafeArrayOfCLSIDs for %S, hr = %08x\n", szPackageID, hr )); goto LErrExit; }
hr = m_pPkgCollection->PopulateByKey(aCLSIDs); if (FAILED(hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed in m_pPkgCollection(%p)->PopulateByKey(), hr = %08x\n", m_pPkgCollection, hr )); goto LErrExit; } hr = m_pPkgCollection->get_Count(&lPkgCount); if (SUCCEEDED(hr) && lPkgCount == 1) { //
// Found the CLSID in PopulateByKey().
//
hr = m_pPkgCollection->get_Item(0, (IDispatch**)&m_pPackage); if (FAILED(hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed in m_pPkgCollection(%p)->get_Item(). Err=%08x\n", m_pPkgCollection, hr )); goto LErrExit; } else { SETUP_TRACE(( DBG_CONTEXT, "CreatePackage - Package already exists, ID(%S), Name(%S)\n", szPackageID, szPackageName )); DBG_ASSERT(m_pPackage); fFound = TRUE; } }
if ( SUCCEEDED(hr) ) {
if( !fFound ) { SETUP_TRACE(( DBG_CONTEXT, "Package ID(%S) Name(%S) does not exist. Attempting to create it.\n", szPackageID, szPackageName )); //
// The package does not already exist, we need to call Add() to
// add this package and then set it's properties.
//
hr = m_pPkgCollection->Add((IDispatch**)&m_pPackage); if ( FAILED(hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed in m_pPkgCollection(%p)->Add(). Err=%08x\n", m_pPkgCollection, hr )); goto LErrExit; } } DBG_ASSERT( SUCCEEDED( hr)); DBG_ASSERT( m_pPackage != NULL);
if( SUCCEEDED(hr) && m_pPackage != NULL ) { //
// Set the Package properties
// first by initializing the array of values and then
// calling SetPackageProperties()
//
LPCWSTR rgpszValues[ MAX_WAMREG_MTS_PROP_NAMES];
ZeroMemory( rgpszValues, sizeof( rgpszValues));
if( fFound ) { // For an existing package, we don't want to set the ID
rgpszValues[ WM_ID] = NULL; } else { rgpszValues[ WM_ID] = szPackageID; }
rgpszValues[ WM_NAME] = szPackageName; rgpszValues[ WM_CREATED_BY] = L"Microsoft Internet Information Services";
rgpszValues[ WM_RUN_FOREVER] = L"Y";
rgpszValues[ WM_IDENTITY] = szIdentity; rgpszValues[ WM_PASSWORD] = szIdPassword; rgpszValues[ WM_ACTIVATION] = ((fInProc) ? L"InProc" : L"Local"); rgpszValues[ WM_CHANGEABLE] = L"Y"; rgpszValues[ WM_DELETABLE] = L"N"; rgpszValues[ WM_SECSUPP] = L"0"; //
// Now that we have the properties setup, let us
// now set the properties in the MTS using catalog
// object
//
hr = SetPackageProperties( rgpszValues); if ( FAILED( hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed to set properties for package %p. Err=%08x\n", m_pPackage, hr )); goto LErrExit; }
long lChanges; hr = m_pPkgCollection->SaveChanges(&lChanges); if (FAILED(hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed in m_pPkgCollection(%p)->SaveChanges. error = %08x\n", m_pPkgCollection, hr )); goto LErrExit; } } } LErrExit:
if (aCLSIDs != NULL) { SafeArrayDestroy(aCLSIDs); aCLSIDs = NULL; } if (FAILED(hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed to Create Package. Package Name = %S, Package ID = %S, error = %08x\n", szPackageName, szPackageID, hr )); } SETUP_TRACE_ASSERT(SUCCEEDED(hr));
ReleaseAll(); SETUP_TRACE(( DBG_CONTEXT, "RETURN - CreatePackage ID(%S) Name(%S)\n", szPackageID, szPackageName ));
return hr; }
/*===================================================================
AddComponentFromPackage
Add a Component (a WAM CLSID) from a Viper Package. Assume the package is already existed.
Parameter: szPackageID: [in] Viper Package ID. szComponentCLSID: [in] Component CLSID. fInProc: [in] if TRUE, we set certain property on the Component.
Return: HRESULT Side Affect: NONE.
===================================================================*/ HRESULT WamRegPackageConfig::AddComponentToPackage ( IN LPCWSTR szPackageID, IN LPCWSTR szComponentCLSID ) { HRESULT hr; BSTR bstrGUID = NULL; BSTR bstr = NULL; VARIANT varKey; long lChanges; BOOL fFound; long lPkgCount; BOOL fImported = FALSE; SETUP_TRACE(( DBG_CONTEXT, "CALL - AddComponentToPackage, Package(%S) Component(%S)\n", szPackageID, szComponentCLSID ));
DBG_ASSERT(szPackageID); DBG_ASSERT(szComponentCLSID); VariantInit(&varKey); VariantClear(&varKey);
DBG_ASSERT( m_pCatalog != NULL); DBG_ASSERT( m_pPkgCollection != NULL);
varKey.vt = VT_BSTR; varKey.bstrVal = SysAllocString(szPackageID); bstr = SysAllocString(szPackageID); bstrGUID = SysAllocString(szComponentCLSID); hr = m_pCatalog->ImportComponent(bstr, bstrGUID); FREEBSTR(bstr); FREEBSTR(bstrGUID); if (FAILED(hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed in m_pCatalog(%p)->ImportComponent(). error %08x\n", m_pCatalog, hr )); goto LErrExit; } else { fImported = TRUE; }
// Get the "ComponentsInPackage" collection.
bstr = SysAllocString(L"Components"); hr = m_pPkgCollection->GetCollection(bstr, varKey, (IDispatch**)&m_pCompCollection); FREEBSTR(bstr); VariantClear(&varKey); if (FAILED(hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed in m_pPkgCollection(%p)->GetCollection(). error %08x\n", m_pPkgCollection, hr )); goto LErrExit; }
//
// Find and Set properties on the component object
//
hr = SetComponentObjectProperties( szComponentCLSID); if ( FAILED(hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed to SetComponentObjectProperties. error %08x\n", hr )); goto LErrExit; } LErrExit: // Save changes
if (SUCCEEDED(hr)) { hr = m_pCompCollection->SaveChanges(&lChanges); if (FAILED(hr)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed in m_pCompCollection(%p)->SaveChanges(), error = %08x\n", m_pCompCollection, hr )); } } else { // CODEWORK - This seems like a bad idea. The release should drop any
// changes we made, so this cleanup code seems to be asking for trouble.
// Need to remove component from the package
if (fImported && m_pCompCollection ) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed in AddComponentToPackage, removing the component, error = %08x\n", hr ));
HRESULT hrT; long lCompCount;
// Find our component in the list (should be the only one)
hrT = m_pCompCollection->get_Count(&lCompCount); if (SUCCEEDED(hrT)) { fFound = FALSE; if (SUCCEEDED(hrT) && lCompCount == 1) { // Found it
fFound = TRUE; hrT = m_pCompCollection->Remove(0); if (SUCCEEDED(hrT)) { hrT = m_pCompCollection->SaveChanges(&lChanges); if (FAILED(hrT)) { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed in m_pCompCollection->SaveChanges() during cleanup, error = %08x\n", hrT )); }
} else { SETUP_TRACE_ERROR(( DBG_CONTEXT, "Failed in m_pCompCollection->Remove() during cleanup, hr = %08x\n", hrT )); } } } } } FREEBSTR(bstr); VariantClear(&varKey); ReleaseAll();
SETUP_TRACE(( DBG_CONTEXT, "RETURN - AddComponentToPackage, Package(%S) Component(%S), hr=%08x\n", szPackageID, szComponentCLSID, hr )); return hr; }
/*===================================================================
RemoveComponentFromPackage
Remove a Component (a WAM CLSID) from a Viper Package.
Parameter: szPackageID: [in] Viper Package ID. szComponentCLSID: [in] Component CLSID. fDeletePackage: [in] if TRUE, we delete the package always. (be very careful, with in-proc package).
Return: HRESULT Side Affect: After remove the component from the package, if the component count in the package is 0, then delete the whole package.
===================================================================*/ HRESULT WamRegPackageConfig::RemoveComponentFromPackage ( IN LPCWSTR szPackageID, IN LPCWSTR szComponentCLSID, IN DWORD dwAppIsolated ) { HRESULT hr; BSTR bstr = NULL; BSTR bstrGUID = NULL; VARIANT varKey; VARIANT varT; SAFEARRAY* aCLSIDs = NULL; LONG Indices[1]; long lPkgCount, lCompCount, lChanges; long lPkgIndex = 0; BOOL fFound; VariantInit(&varKey); VariantClear(&varKey); VariantInit(&varT); VariantClear(&varT);
DBG_ASSERT( m_pCatalog != NULL); DBG_ASSERT( m_pPkgCollection != NULL);
hr = GetSafeArrayOfCLSIDs(szPackageID, &aCLSIDs); //
// Populate it
//
hr = m_pPkgCollection->PopulateByKey(aCLSIDs); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to call PopulateByKey(), hr = %08x\n", hr)); goto LErrExit; }
// Find our component in the list (should be the only one)
hr = m_pPkgCollection->get_Count(&lPkgCount); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to call MTS Admin API. error %08x\n", hr)); goto LErrExit; }
fFound = FALSE; if (SUCCEEDED(hr) && lPkgCount == 1) { hr = m_pPkgCollection->get_Item(0, (IDispatch**)&m_pPackage); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to call MTS Admin API. error %08x\n", hr)); goto LErrExit; } hr = m_pPackage->get_Key(&varKey); if (SUCCEEDED(hr)) { // Found it
DBG_ASSERT(m_pPackage); fFound = TRUE; } }
// Get the "Components" collection.
bstr = SysAllocString(L"Components"); hr = m_pPkgCollection->GetCollection(bstr, varKey, (IDispatch**)&m_pCompCollection); FREEBSTR(bstr); VariantClear(&varKey); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to Call MTS Admin API, hr = %08x\n", hr)); goto LErrExit; } // Repopulate the collection so we can find our object and set properties on it
Indices[0] = 0; VariantInit(&varT); varT.vt = VT_BSTR; varT.bstrVal = SysAllocString(szComponentCLSID); hr = SafeArrayPutElement(aCLSIDs, Indices, &varT); VariantClear(&varT); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to call SafeArrayDestroy(aCLSIDs), hr = %08x\n", hr)); } //
// Populate it
//
hr = m_pCompCollection->PopulateByKey(aCLSIDs); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to call PopulateByKey(), hr = %08x\n", hr)); goto LErrExit; }
// Find our component in the list (should be the only one)
hr = m_pCompCollection->get_Count(&lCompCount); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to call MTS Admin API. error %08x\n", hr)); goto LErrExit; }
fFound = FALSE; if (SUCCEEDED(hr) && lCompCount == 1) { // Found it
fFound = TRUE; hr = m_pCompCollection->Remove(0); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to Call MTS Admin API, hr = %08x\n", hr)); goto LErrExit; } } DBG_ASSERT(fFound);
// Save changes
hr = m_pCompCollection->SaveChanges(&lChanges); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to Call MTS Admin API, hr = %08x\n", hr)); goto LErrExit; }
//
// Need to populate again to get the Component count after remove the component from
// the package. The populatebykey only populate 1 component a time.
// However, if this package is the default package hosting all in-proc WAM components,
// we know that there is at least one component W3SVC always in this package, therefore
// we skip the GetComponentCount call here.
// The component count for the default package must be at least one,
//
// Set lCompCount = 1, so that the only case that lCompCount becomes 0 is the OutProc
// Islated package has 0 components.
lCompCount = 1; if (dwAppIsolated == static_cast<DWORD>(eAppRunOutProcIsolated)) { hr = m_pCompCollection->Populate(); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to Call MTS Admin API, hr = %08x\n", hr)); goto LErrExit; } // Find our component in the list (should be the only one)
hr = m_pCompCollection->get_Count(&lCompCount); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to Call MTS Admin API, hr = %08x\n", hr)); goto LErrExit; }
// Component count is 0, remove the package.
if (lCompCount == 0) { // Found it - remove it and call Save Changes
// First, Set Deleteable = Y property on package
hr = SetPackageObjectProperty(L"Deleteable", L"Y"); if (FAILED(hr)) { goto LErrExit; }
RELEASE(m_pPackage); // Let save the Deletable settings
hr = m_pPkgCollection->SaveChanges(&lChanges); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to Call MTS Admin API, hr = %08x\n", hr)); goto LErrExit; } hr = m_pPkgCollection->Remove(0); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to Call MTS Admin API, hr = %08x\n", hr)); goto LErrExit; } } else { // Set Attribute Deleteable = "Y"
hr = SetPackageObjectProperty(L"Deleteable", L"Y"); if (FAILED(hr)) { goto LErrExit; }
// Set CreatedBy = ""
hr = SetPackageObjectProperty(L"CreatedBy", L""); if (FAILED(hr)) { goto LErrExit; }
// Set Identity to Interactive User. MTS might use that package with "Interactive User"
// as the indentity.
hr = SetPackageObjectProperty(L"Identity", L"Interactive User"); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to Call MTS Admin API, hr = %08x\n", hr)); goto LErrExit; }
RELEASE(m_pPackage); } hr = m_pPkgCollection->SaveChanges(&lChanges); if (FAILED(hr)) { DBGPRINTF((DBG_CONTEXT, "Failed to Call MTS Admin API, hr = %08x\n", hr)); goto LErrExit; } } LErrExit:
if (aCLSIDs != NULL) { HRESULT hrT; hrT = SafeArrayDestroy(aCLSIDs);
if (FAILED(hrT)) { DBGPRINTF((DBG_CONTEXT, "Failed to call SafeArrayDestroy(aCLSIDs), hr = %08x\n", hr)); }
aCLSIDs = NULL; }
FREEBSTR(bstr); VariantClear(&varKey); VariantClear(&varT);
ReleaseAll(); return hr;
}
#if 0
// OBSOLETE - This fix (335422) was implemented in script but
// some of the code is general enough that it might be worth
// keeping around for a while.
HRESULT WamRegPackageConfig::ResetPackageActivation ( IN LPCWSTR wszPackageID, IN LPCWSTR wszIWamUser, IN LPCWSTR wszIWamPass ) /*+
Routine Description:
Retrieve the specified package and reset its activation identity. This is really a crummy method, but this whole class is not really designed to provide a wrapper for the com admin api, so it's much safer just to make this a specific method.
Arguments:
IN LPCWSTR wszPackageID - the package to reset IN LPCWSTR wszIWamUser - IWAM_* IN LPCWSTR wszIWamPass - password for IWAM_*
Returns: HRESULT -*/ { HRESULT hr = NOERROR; LONG nChanges = 0;
DBG_ASSERT( m_pCatalog != NULL); DBG_ASSERT( m_pPkgCollection != NULL); DBG_ASSERT( m_pPackage == NULL );
hr = LoadPackage( wszPackageID );
if( SUCCEEDED(hr) ) { DBG_ASSERT( m_pPackage != NULL );
LPCWSTR rgpszValues[ MAX_WAMREG_MTS_PROP_NAMES ];
ZeroMemory( rgpszValues, sizeof(rgpszValues) );
rgpszValues[WM_IDENTITY] = wszIWamUser; rgpszValues[WM_PASSWORD] = wszIWamPass;
hr = SetPackageProperties( rgpszValues );
if( SUCCEEDED(hr) ) { hr = m_pPkgCollection->SaveChanges( &nChanges ); } }
ReleaseAll(); return hr; }
HRESULT WamRegPackageConfig::LoadPackage ( IN LPCWSTR wszPackageID ) /*+
Routine Description:
Retrieve the specified package into m_pPackage
TODO - Use this when creating as well. Need to add the necessary debug/setuplog traces.
Arguments:
IN LPCWSTR wszPackageID - the package to load
Returns: HRESULT -*/ { HRESULT hr = NOERROR; SAFEARRAY* psaPackageClsid = NULL;
DBG_ASSERT( m_pCatalog != NULL); DBG_ASSERT( m_pPkgCollection != NULL); DBG_ASSERT( m_pPackage == NULL );
hr = GetSafeArrayOfCLSIDs( wszPackageID, &psaPackageClsid ); if( SUCCEEDED(hr) ) { hr = m_pPkgCollection->PopulateByKey( psaPackageClsid );
DBG_CODE( if( SUCCEEDED(hr) ) { LONG nPackages; hr = m_pPkgCollection->get_Count( &nPackages );
DBG_ASSERT( SUCCEEDED(hr) ); DBG_ASSERT( nPackages == 1 ); } );
if( SUCCEEDED(hr) ) { hr = m_pPkgCollection->get_Item( 0, (IDispatch **)&m_pPackage ); } }
if( psaPackageClsid ) SafeArrayDestroy( psaPackageClsid );
return hr; }
// OBSOLETE
#endif
|