Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

705 lines
15 KiB

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 2001
//
// File: cwebservice.cxx
//
// Contents: Contains methods for CIISWebService object
//
// History: 01-15-2001 BrentMid Created.
//
//----------------------------------------------------------------------------
#include "iisext.hxx"
#include <initguid.h>
#include "iwamreg.h"
#include "sitecreator.h"
#pragma hdrstop
// Class CIISWebService
DEFINE_IPrivateDispatch_Implementation(CIISWebService)
DEFINE_DELEGATING_IDispatch_Implementation(CIISWebService)
DEFINE_CONTAINED_IADs_Implementation(CIISWebService)
DEFINE_IADsExtension_Implementation(CIISWebService)
CIISWebService::CIISWebService():
_pUnkOuter(NULL),
_pADs(NULL),
_pszServerName(NULL),
_pszMetaBasePath(NULL),
_pAdminBase(NULL),
_pDispMgr(NULL),
_fDispInitialized(FALSE)
{
ENLIST_TRACKING(CIISWebService);
}
HRESULT
CIISWebService::CreateWebService(
IUnknown *pUnkOuter,
REFIID riid,
void **ppvObj
)
{
CCredentials Credentials;
CIISWebService FAR * pWebService = NULL;
HRESULT hr = S_OK;
BSTR bstrAdsPath = NULL;
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
CLexer * pLexer = NULL;
LPWSTR pszIISPathName = NULL;
hr = AllocateWebServiceObject(pUnkOuter, Credentials, &pWebService);
BAIL_ON_FAILURE(hr);
//
// get ServerName and pszPath
//
hr = pWebService->_pADs->get_ADsPath(&bstrAdsPath);
BAIL_ON_FAILURE(hr);
pLexer = new CLexer();
hr = pLexer->Initialize(bstrAdsPath);
BAIL_ON_FAILURE(hr);
//
// Parse the pathname
//
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = ADsObject(pLexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
pszIISPathName = AllocADsStr(bstrAdsPath);
if (!pszIISPathName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
*pszIISPathName = L'\0';
hr = BuildIISPathFromADsPath(
pObjectInfo,
pszIISPathName
);
BAIL_ON_FAILURE(hr);
hr = pWebService->InitializeWebServiceObject(
pObjectInfo->TreeName,
pszIISPathName );
BAIL_ON_FAILURE(hr);
//
// pass non-delegating IUnknown back to the aggregator
//
*ppvObj = (INonDelegatingUnknown FAR *) pWebService;
if (bstrAdsPath)
{
ADsFreeString(bstrAdsPath);
}
if (pLexer) {
delete pLexer;
}
if (pszIISPathName ) {
FreeADsStr( pszIISPathName );
}
FreeObjectInfo( &ObjectInfo );
RRETURN(hr);
error:
if (bstrAdsPath) {
ADsFreeString(bstrAdsPath);
}
if (pLexer) {
delete pLexer;
}
if (pszIISPathName ) {
FreeADsStr( pszIISPathName );
}
FreeObjectInfo( &ObjectInfo );
*ppvObj = NULL;
delete pWebService;
RRETURN(hr);
}
CIISWebService::~CIISWebService( )
{
if (_pszServerName) {
FreeADsStr(_pszServerName);
}
if (_pszMetaBasePath) {
FreeADsStr(_pszMetaBasePath);
}
delete _pDispMgr;
}
STDMETHODIMP
CIISWebService::QueryInterface(
REFIID iid,
LPVOID FAR* ppv
)
{
HRESULT hr = S_OK;
hr = _pUnkOuter->QueryInterface(iid,ppv);
RRETURN(hr);
}
HRESULT
CIISWebService::AllocateWebServiceObject(
IUnknown *pUnkOuter,
CCredentials& Credentials,
CIISWebService ** ppWebService
)
{
CIISWebService FAR * pWebService = NULL;
IADs FAR * pADs = NULL;
CAggregateeDispMgr FAR * pDispMgr = NULL;
HRESULT hr = S_OK;
pWebService = new CIISWebService();
if (pWebService == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
pDispMgr = new CAggregateeDispMgr;
if (pDispMgr == NULL) {
hr = E_OUTOFMEMORY;
}
BAIL_ON_FAILURE(hr);
hr = pDispMgr->LoadTypeInfoEntry(
LIBID_IISExt,
IID_IISWebService,
(IISWebService *)pWebService,
DISPID_REGULAR
);
BAIL_ON_FAILURE(hr);
//
// Store the IADs Pointer, but again do NOT ref-count
// this pointer - we keep the pointer around, but do
// a release immediately.
//
hr = pUnkOuter->QueryInterface(IID_IADs, (void **)&pADs);
pADs->Release();
pWebService->_pADs = pADs;
//
// Store the pointer to the pUnkOuter object
// AND DO NOT add ref this pointer
//
pWebService->_pUnkOuter = pUnkOuter;
pWebService->_Credentials = Credentials;
pWebService->_pDispMgr = pDispMgr;
*ppWebService = pWebService;
RRETURN(hr);
error:
delete pDispMgr;
delete pWebService;
RRETURN(hr);
}
HRESULT
CIISWebService::InitializeWebServiceObject(
LPWSTR pszServerName,
LPWSTR pszPath
)
{
HRESULT hr = S_OK;
if (pszServerName) {
_pszServerName = AllocADsStr(pszServerName);
if (!_pszServerName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
}
if (pszPath) {
_pszMetaBasePath = AllocADsStr(pszPath);
if (!_pszMetaBasePath) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
}
hr = InitServerInfo(pszServerName, &_pAdminBase);
BAIL_ON_FAILURE(hr);
error:
RRETURN(hr);
}
STDMETHODIMP
CIISWebService::ADSIInitializeDispatchManager(
long dwExtensionId
)
{
HRESULT hr = S_OK;
if (_fDispInitialized) {
RRETURN(E_FAIL);
}
hr = _pDispMgr->InitializeDispMgr(dwExtensionId);
if (SUCCEEDED(hr)) {
_fDispInitialized = TRUE;
}
RRETURN(hr);
}
STDMETHODIMP
CIISWebService::ADSIInitializeObject(
THIS_ BSTR lpszUserName,
BSTR lpszPassword,
long lnReserved
)
{
CCredentials NewCredentials(lpszUserName, lpszPassword, lnReserved);
_Credentials = NewCredentials;
RRETURN(S_OK);
}
STDMETHODIMP
CIISWebService::ADSIReleaseObject()
{
delete this;
RRETURN(S_OK);
}
STDMETHODIMP
CIISWebService::NonDelegatingQueryInterface(
REFIID iid,
LPVOID FAR* ppv
)
{
ASSERT(ppv);
if (IsEqualIID(iid, IID_IISWebService)) {
*ppv = (IADsUser FAR *) this;
} else if (IsEqualIID(iid, IID_IADsExtension)) {
*ppv = (IADsExtension FAR *) this;
} else if (IsEqualIID(iid, IID_IUnknown)) {
//
// probably not needed since our 3rd party extension does not stand
// alone and provider does not ask for this, but to be safe
//
*ppv = (INonDelegatingUnknown FAR *) this;
} else {
*ppv = NULL;
return E_NOINTERFACE;
}
//
// Delegating AddRef to aggregator for IADsExtesnion and IISWebService.
// AddRef on itself for IPrivateUnknown. (both tested.)
//
((IUnknown *) (*ppv)) -> AddRef();
return S_OK;
}
//
// IADsExtension::Operate()
//
STDMETHODIMP
CIISWebService::Operate(
THIS_ DWORD dwCode,
VARIANT varUserName,
VARIANT varPassword,
VARIANT varFlags
)
{
RRETURN(E_NOTIMPL);
}
STDMETHODIMP
CIISWebService::CreateNewSite(
BSTR bstrServerComment,
VARIANT *pvServerBindings,
BSTR bstrRootVDirPath,
VARIANT vServerID,
VARIANT *pvActualID
)
{
HRESULT hr = S_OK;
DWORD dwSiteID = 0;
DWORD * pdwSiteID = &dwSiteID;
DWORD dwNewSiteID = 0;
IIISApplicationAdmin * pAppAdmin = NULL;
COSERVERINFO csiName;
COSERVERINFO *pcsiParam = &csiName;
IClassFactory * pcsfFactory = NULL;
CSiteCreator SiteCreator(_pAdminBase);
VARIANT vVar;
WCHAR* wszServerBindings = NULL;
WCHAR* pIndex = NULL;
VARIANT * pVarArray = NULL;
DWORD dwNumValues = 0;
memset(pcsiParam, 0, sizeof(COSERVERINFO));
//
// special case to handle "localhost" to work-around ole32 bug
//
if (_pszServerName == NULL || _wcsicmp(_pszServerName,L"localhost") == 0) {
pcsiParam->pwszName = NULL;
}
else {
pcsiParam->pwszName = _pszServerName;
}
csiName.pAuthInfo = NULL;
pcsiParam = &csiName;
if (vServerID.vt == VT_I4) {
*pdwSiteID = vServerID.lVal;
}
else {
pdwSiteID = NULL;
}
hr = CoGetClassObject(
CLSID_WamAdmin,
CLSCTX_SERVER,
pcsiParam,
IID_IClassFactory,
(void**) &pcsfFactory
);
BAIL_ON_FAILURE(hr);
hr = pcsfFactory->CreateInstance(
NULL,
IID_IIISApplicationAdmin,
(void **) &pAppAdmin
);
BAIL_ON_FAILURE(hr);
VariantInit(&vVar);
hr = VariantCopyInd(&vVar, pvServerBindings);
BAIL_ON_FAILURE(hr);
if ( VT_DISPATCH == V_VT(&vVar) ) // JScript Array
{
// Output here is VT_BSTR, of format: "str_1,str_2,str_3, ... str_n\0"
hr = VariantChangeType( &vVar, &vVar, 0, VT_BSTR );
BAIL_ON_FAILURE(hr);
wszServerBindings = new WCHAR [wcslen(vVar.bstrVal) + 2]; // 1 for NULL, 1 for extra NULL
if (!wszServerBindings) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
wcscpy(wszServerBindings, vVar.bstrVal);
// change VT_BSTR to MULTISZ format: "str_1\0str_2\0str_3\0 ... str_n\0"
pIndex = wszServerBindings;
while ( *pIndex != 0 )
{
if ( *pIndex == L',' )
{
*pIndex = 0;
}
pIndex++;
}
*(++pIndex) = 0;
}
else if ( (VT_ARRAY | VT_VARIANT) == V_VT(&vVar) ) // VBS Array = SafeArray
{
// Allocates wszServerBindings and puts in MULTISZ format
hr = ConvertArrayToMultiSZ( vVar, &wszServerBindings );
BAIL_ON_FAILURE(hr);
}
else
{
hr = E_INVALIDARG;
BAIL_ON_FAILURE(hr);
}
hr = SiteCreator.CreateNewSite2(SC_W3SVC, bstrServerComment, wszServerBindings,
bstrRootVDirPath, pAppAdmin, &dwNewSiteID, pdwSiteID);
BAIL_ON_FAILURE(hr);
VariantInit( pvActualID );
pvActualID->vt = VT_I4;
pvActualID->lVal = dwNewSiteID;
error:
if (pcsfFactory) {
pcsfFactory->Release();
}
if (pAppAdmin) {
pAppAdmin->Release();
}
if (wszServerBindings) {
delete [] wszServerBindings;
}
RRETURN(hr);
}
HRESULT
CIISWebService::ConvertArrayToMultiSZ(
VARIANT varSafeArray,
WCHAR **pszServerBindings
)
{
HRESULT hr = S_OK;
DWORD dwSLBound = 0;
DWORD dwSUBound = 0;
DWORD i = 0;
SAFEARRAY * pArray = NULL;
DWORD dwLen = 0;
DWORD dwNumVariants = 0;
VARIANT * pVarArray = NULL;
VARIANT pElem;
WCHAR* wszServerBindings = NULL;
if(!(V_ISARRAY(&varSafeArray)))
RRETURN(E_FAIL);
//
// This handles by-ref and regular SafeArrays.
//
if (V_VT(&varSafeArray) & VT_BYREF)
pArray = *(V_ARRAYREF(&varSafeArray));
else
pArray = V_ARRAY(&varSafeArray);
//
// Check that there is only one dimension in this array
//
if (pArray && pArray->cDims != 1) {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
//
// Check that there is at least one element in this array
//
if (!pArray ||
( pArray->rgsabound[0].cElements == 0) ) {
wszServerBindings = new WCHAR [2];
wszServerBindings[0] = 0;
wszServerBindings[1] = 1;
}
else {
//
// We know that this is a valid single dimension array
//
hr = SafeArrayGetLBound(pArray,
1,
(long FAR *)&dwSLBound
);
BAIL_ON_FAILURE(hr);
hr = SafeArrayGetUBound(pArray,
1,
(long FAR *)&dwSUBound
);
BAIL_ON_FAILURE(hr);
dwNumVariants = dwSUBound - dwSLBound + 1;
dwLen = 0;
pVarArray = (PVARIANT)AllocADsMem(
sizeof(VARIANT)*dwNumVariants
);
if (!pVarArray) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
for (i = dwSLBound; i <= dwSUBound; i++) {
VariantInit(&pElem);
hr = SafeArrayGetElement(pArray,
(long FAR *)&i,
&pElem
);
BAIL_ON_FAILURE(hr);
hr = VariantChangeType(&pElem, &pElem, 0, VT_BSTR);
BAIL_ON_FAILURE(hr);
dwLen = dwLen + wcslen(pElem.bstrVal) + 1;
pVarArray[i] = pElem;
}
wszServerBindings = new WCHAR [dwLen + 1];
WCHAR * pServerBindings = wszServerBindings;
for (i = dwSLBound; i <= dwSUBound; i++) {
wcscpy(pServerBindings, pVarArray[i].bstrVal);
while (*pServerBindings != 0) {
pServerBindings++;
}
pServerBindings++;
}
*pServerBindings = 0;
}
*pszServerBindings = wszServerBindings;
error:
if (pVarArray) {
FreeADsMem(pVarArray);
}
RRETURN(hr);
}
STDMETHODIMP
CIISWebService::GetCurrentMode(
VARIANT FAR* pvServerMode
)
{
HRESULT hr = S_OK;
DWORD dwServerMode = 0;
COSERVERINFO csiName;
COSERVERINFO *pcsiParam = &csiName;
IClassFactory * pcsfFactory = NULL;
IWamAdmin * pWamAdmin = NULL;
IIISApplicationAdmin * pAppAdmin = NULL;
memset(pcsiParam, 0, sizeof(COSERVERINFO));
//
// special case to handle "localhost" to work-around ole32 bug
//
if (_pszServerName == NULL || _wcsicmp(_pszServerName,L"localhost") == 0) {
pcsiParam->pwszName = NULL;
}
else {
pcsiParam->pwszName = _pszServerName;
}
csiName.pAuthInfo = NULL;
pcsiParam = &csiName;
hr = CoGetClassObject(
CLSID_WamAdmin,
CLSCTX_SERVER,
pcsiParam,
IID_IClassFactory,
(void**) &pcsfFactory
);
BAIL_ON_FAILURE(hr);
hr = pcsfFactory->CreateInstance(
NULL,
IID_IWamAdmin,
(void **) &pWamAdmin
);
BAIL_ON_FAILURE(hr);
// test here for 5.1 compat
hr = pWamAdmin->QueryInterface(
IID_IIISApplicationAdmin,
(void **)&pAppAdmin
);
BAIL_ON_FAILURE(hr);
// Call GetProcessMode - it's returning GetCurrentMode
// after it checks to make sure the W3SVC is running.
hr = pAppAdmin->GetProcessMode( &dwServerMode );
BAIL_ON_FAILURE(hr);
VariantInit( pvServerMode );
pvServerMode->vt = VT_I4;
pvServerMode->lVal = dwServerMode;
error:
if (pcsfFactory) {
pcsfFactory->Release();
}
if (pWamAdmin) {
pWamAdmin->Release();
}
if (pAppAdmin) {
pAppAdmin->Release();
}
RRETURN(hr);
}