windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/wam/wamreg/mtsconfig.cpp
2020-09-26 16:20:57 +08:00

1800 lines
48 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*===================================================================
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