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

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2001
  5. //
  6. // File: cwebservice.cxx
  7. //
  8. // Contents: Contains methods for CIISWebService object
  9. //
  10. // History: 01-15-2001 BrentMid Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "iisext.hxx"
  14. #include <initguid.h>
  15. #include "iwamreg.h"
  16. #include "sitecreator.h"
  17. #pragma hdrstop
  18. // Class CIISWebService
  19. DEFINE_IPrivateDispatch_Implementation(CIISWebService)
  20. DEFINE_DELEGATING_IDispatch_Implementation(CIISWebService)
  21. DEFINE_CONTAINED_IADs_Implementation(CIISWebService)
  22. DEFINE_IADsExtension_Implementation(CIISWebService)
  23. CIISWebService::CIISWebService():
  24. _pUnkOuter(NULL),
  25. _pADs(NULL),
  26. _pszServerName(NULL),
  27. _pszMetaBasePath(NULL),
  28. _pAdminBase(NULL),
  29. _pDispMgr(NULL),
  30. _fDispInitialized(FALSE)
  31. {
  32. ENLIST_TRACKING(CIISWebService);
  33. }
  34. HRESULT
  35. CIISWebService::CreateWebService(
  36. IUnknown *pUnkOuter,
  37. REFIID riid,
  38. void **ppvObj
  39. )
  40. {
  41. CCredentials Credentials;
  42. CIISWebService FAR * pWebService = NULL;
  43. HRESULT hr = S_OK;
  44. BSTR bstrAdsPath = NULL;
  45. OBJECTINFO ObjectInfo;
  46. POBJECTINFO pObjectInfo = &ObjectInfo;
  47. CLexer * pLexer = NULL;
  48. LPWSTR pszIISPathName = NULL;
  49. hr = AllocateWebServiceObject(pUnkOuter, Credentials, &pWebService);
  50. BAIL_ON_FAILURE(hr);
  51. //
  52. // get ServerName and pszPath
  53. //
  54. hr = pWebService->_pADs->get_ADsPath(&bstrAdsPath);
  55. BAIL_ON_FAILURE(hr);
  56. pLexer = new CLexer();
  57. hr = pLexer->Initialize(bstrAdsPath);
  58. BAIL_ON_FAILURE(hr);
  59. //
  60. // Parse the pathname
  61. //
  62. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  63. hr = ADsObject(pLexer, pObjectInfo);
  64. BAIL_ON_FAILURE(hr);
  65. pszIISPathName = AllocADsStr(bstrAdsPath);
  66. if (!pszIISPathName) {
  67. hr = E_OUTOFMEMORY;
  68. BAIL_ON_FAILURE(hr);
  69. }
  70. *pszIISPathName = L'\0';
  71. hr = BuildIISPathFromADsPath(
  72. pObjectInfo,
  73. pszIISPathName
  74. );
  75. BAIL_ON_FAILURE(hr);
  76. hr = pWebService->InitializeWebServiceObject(
  77. pObjectInfo->TreeName,
  78. pszIISPathName );
  79. BAIL_ON_FAILURE(hr);
  80. //
  81. // pass non-delegating IUnknown back to the aggregator
  82. //
  83. *ppvObj = (INonDelegatingUnknown FAR *) pWebService;
  84. if (bstrAdsPath)
  85. {
  86. ADsFreeString(bstrAdsPath);
  87. }
  88. if (pLexer) {
  89. delete pLexer;
  90. }
  91. if (pszIISPathName ) {
  92. FreeADsStr( pszIISPathName );
  93. }
  94. FreeObjectInfo( &ObjectInfo );
  95. RRETURN(hr);
  96. error:
  97. if (bstrAdsPath) {
  98. ADsFreeString(bstrAdsPath);
  99. }
  100. if (pLexer) {
  101. delete pLexer;
  102. }
  103. if (pszIISPathName ) {
  104. FreeADsStr( pszIISPathName );
  105. }
  106. FreeObjectInfo( &ObjectInfo );
  107. *ppvObj = NULL;
  108. delete pWebService;
  109. RRETURN(hr);
  110. }
  111. CIISWebService::~CIISWebService( )
  112. {
  113. if (_pszServerName) {
  114. FreeADsStr(_pszServerName);
  115. }
  116. if (_pszMetaBasePath) {
  117. FreeADsStr(_pszMetaBasePath);
  118. }
  119. delete _pDispMgr;
  120. }
  121. STDMETHODIMP
  122. CIISWebService::QueryInterface(
  123. REFIID iid,
  124. LPVOID FAR* ppv
  125. )
  126. {
  127. HRESULT hr = S_OK;
  128. hr = _pUnkOuter->QueryInterface(iid,ppv);
  129. RRETURN(hr);
  130. }
  131. HRESULT
  132. CIISWebService::AllocateWebServiceObject(
  133. IUnknown *pUnkOuter,
  134. CCredentials& Credentials,
  135. CIISWebService ** ppWebService
  136. )
  137. {
  138. CIISWebService FAR * pWebService = NULL;
  139. IADs FAR * pADs = NULL;
  140. CAggregateeDispMgr FAR * pDispMgr = NULL;
  141. HRESULT hr = S_OK;
  142. pWebService = new CIISWebService();
  143. if (pWebService == NULL) {
  144. hr = E_OUTOFMEMORY;
  145. }
  146. BAIL_ON_FAILURE(hr);
  147. pDispMgr = new CAggregateeDispMgr;
  148. if (pDispMgr == NULL) {
  149. hr = E_OUTOFMEMORY;
  150. }
  151. BAIL_ON_FAILURE(hr);
  152. hr = pDispMgr->LoadTypeInfoEntry(
  153. LIBID_IISExt,
  154. IID_IISWebService,
  155. (IISWebService *)pWebService,
  156. DISPID_REGULAR
  157. );
  158. BAIL_ON_FAILURE(hr);
  159. //
  160. // Store the IADs Pointer, but again do NOT ref-count
  161. // this pointer - we keep the pointer around, but do
  162. // a release immediately.
  163. //
  164. hr = pUnkOuter->QueryInterface(IID_IADs, (void **)&pADs);
  165. pADs->Release();
  166. pWebService->_pADs = pADs;
  167. //
  168. // Store the pointer to the pUnkOuter object
  169. // AND DO NOT add ref this pointer
  170. //
  171. pWebService->_pUnkOuter = pUnkOuter;
  172. pWebService->_Credentials = Credentials;
  173. pWebService->_pDispMgr = pDispMgr;
  174. *ppWebService = pWebService;
  175. RRETURN(hr);
  176. error:
  177. delete pDispMgr;
  178. delete pWebService;
  179. RRETURN(hr);
  180. }
  181. HRESULT
  182. CIISWebService::InitializeWebServiceObject(
  183. LPWSTR pszServerName,
  184. LPWSTR pszPath
  185. )
  186. {
  187. HRESULT hr = S_OK;
  188. if (pszServerName) {
  189. _pszServerName = AllocADsStr(pszServerName);
  190. if (!_pszServerName) {
  191. hr = E_OUTOFMEMORY;
  192. BAIL_ON_FAILURE(hr);
  193. }
  194. }
  195. if (pszPath) {
  196. _pszMetaBasePath = AllocADsStr(pszPath);
  197. if (!_pszMetaBasePath) {
  198. hr = E_OUTOFMEMORY;
  199. BAIL_ON_FAILURE(hr);
  200. }
  201. }
  202. hr = InitServerInfo(pszServerName, &_pAdminBase);
  203. BAIL_ON_FAILURE(hr);
  204. error:
  205. RRETURN(hr);
  206. }
  207. STDMETHODIMP
  208. CIISWebService::ADSIInitializeDispatchManager(
  209. long dwExtensionId
  210. )
  211. {
  212. HRESULT hr = S_OK;
  213. if (_fDispInitialized) {
  214. RRETURN(E_FAIL);
  215. }
  216. hr = _pDispMgr->InitializeDispMgr(dwExtensionId);
  217. if (SUCCEEDED(hr)) {
  218. _fDispInitialized = TRUE;
  219. }
  220. RRETURN(hr);
  221. }
  222. STDMETHODIMP
  223. CIISWebService::ADSIInitializeObject(
  224. THIS_ BSTR lpszUserName,
  225. BSTR lpszPassword,
  226. long lnReserved
  227. )
  228. {
  229. CCredentials NewCredentials(lpszUserName, lpszPassword, lnReserved);
  230. _Credentials = NewCredentials;
  231. RRETURN(S_OK);
  232. }
  233. STDMETHODIMP
  234. CIISWebService::ADSIReleaseObject()
  235. {
  236. delete this;
  237. RRETURN(S_OK);
  238. }
  239. STDMETHODIMP
  240. CIISWebService::NonDelegatingQueryInterface(
  241. REFIID iid,
  242. LPVOID FAR* ppv
  243. )
  244. {
  245. ASSERT(ppv);
  246. if (IsEqualIID(iid, IID_IISWebService)) {
  247. *ppv = (IADsUser FAR *) this;
  248. } else if (IsEqualIID(iid, IID_IADsExtension)) {
  249. *ppv = (IADsExtension FAR *) this;
  250. } else if (IsEqualIID(iid, IID_IUnknown)) {
  251. //
  252. // probably not needed since our 3rd party extension does not stand
  253. // alone and provider does not ask for this, but to be safe
  254. //
  255. *ppv = (INonDelegatingUnknown FAR *) this;
  256. } else {
  257. *ppv = NULL;
  258. return E_NOINTERFACE;
  259. }
  260. //
  261. // Delegating AddRef to aggregator for IADsExtesnion and IISWebService.
  262. // AddRef on itself for IPrivateUnknown. (both tested.)
  263. //
  264. ((IUnknown *) (*ppv)) -> AddRef();
  265. return S_OK;
  266. }
  267. //
  268. // IADsExtension::Operate()
  269. //
  270. STDMETHODIMP
  271. CIISWebService::Operate(
  272. THIS_ DWORD dwCode,
  273. VARIANT varUserName,
  274. VARIANT varPassword,
  275. VARIANT varFlags
  276. )
  277. {
  278. RRETURN(E_NOTIMPL);
  279. }
  280. STDMETHODIMP
  281. CIISWebService::CreateNewSite(
  282. BSTR bstrServerComment,
  283. VARIANT *pvServerBindings,
  284. BSTR bstrRootVDirPath,
  285. VARIANT vServerID,
  286. VARIANT *pvActualID
  287. )
  288. {
  289. HRESULT hr = S_OK;
  290. DWORD dwSiteID = 0;
  291. DWORD * pdwSiteID = &dwSiteID;
  292. DWORD dwNewSiteID = 0;
  293. IIISApplicationAdmin * pAppAdmin = NULL;
  294. COSERVERINFO csiName;
  295. COSERVERINFO *pcsiParam = &csiName;
  296. IClassFactory * pcsfFactory = NULL;
  297. CSiteCreator SiteCreator(_pAdminBase);
  298. VARIANT vVar;
  299. WCHAR* wszServerBindings = NULL;
  300. WCHAR* pIndex = NULL;
  301. VARIANT * pVarArray = NULL;
  302. DWORD dwNumValues = 0;
  303. memset(pcsiParam, 0, sizeof(COSERVERINFO));
  304. //
  305. // special case to handle "localhost" to work-around ole32 bug
  306. //
  307. if (_pszServerName == NULL || _wcsicmp(_pszServerName,L"localhost") == 0) {
  308. pcsiParam->pwszName = NULL;
  309. }
  310. else {
  311. pcsiParam->pwszName = _pszServerName;
  312. }
  313. csiName.pAuthInfo = NULL;
  314. pcsiParam = &csiName;
  315. if (vServerID.vt == VT_I4) {
  316. *pdwSiteID = vServerID.lVal;
  317. }
  318. else {
  319. pdwSiteID = NULL;
  320. }
  321. hr = CoGetClassObject(
  322. CLSID_WamAdmin,
  323. CLSCTX_SERVER,
  324. pcsiParam,
  325. IID_IClassFactory,
  326. (void**) &pcsfFactory
  327. );
  328. BAIL_ON_FAILURE(hr);
  329. hr = pcsfFactory->CreateInstance(
  330. NULL,
  331. IID_IIISApplicationAdmin,
  332. (void **) &pAppAdmin
  333. );
  334. BAIL_ON_FAILURE(hr);
  335. VariantInit(&vVar);
  336. hr = VariantCopyInd(&vVar, pvServerBindings);
  337. BAIL_ON_FAILURE(hr);
  338. if ( VT_DISPATCH == V_VT(&vVar) ) // JScript Array
  339. {
  340. // Output here is VT_BSTR, of format: "str_1,str_2,str_3, ... str_n\0"
  341. hr = VariantChangeType( &vVar, &vVar, 0, VT_BSTR );
  342. BAIL_ON_FAILURE(hr);
  343. wszServerBindings = new WCHAR [wcslen(vVar.bstrVal) + 2]; // 1 for NULL, 1 for extra NULL
  344. if (!wszServerBindings) {
  345. hr = E_OUTOFMEMORY;
  346. BAIL_ON_FAILURE(hr);
  347. }
  348. wcscpy(wszServerBindings, vVar.bstrVal);
  349. // change VT_BSTR to MULTISZ format: "str_1\0str_2\0str_3\0 ... str_n\0"
  350. pIndex = wszServerBindings;
  351. while ( *pIndex != 0 )
  352. {
  353. if ( *pIndex == L',' )
  354. {
  355. *pIndex = 0;
  356. }
  357. pIndex++;
  358. }
  359. *(++pIndex) = 0;
  360. }
  361. else if ( (VT_ARRAY | VT_VARIANT) == V_VT(&vVar) ) // VBS Array = SafeArray
  362. {
  363. // Allocates wszServerBindings and puts in MULTISZ format
  364. hr = ConvertArrayToMultiSZ( vVar, &wszServerBindings );
  365. BAIL_ON_FAILURE(hr);
  366. }
  367. else
  368. {
  369. hr = E_INVALIDARG;
  370. BAIL_ON_FAILURE(hr);
  371. }
  372. hr = SiteCreator.CreateNewSite2(SC_W3SVC, bstrServerComment, wszServerBindings,
  373. bstrRootVDirPath, pAppAdmin, &dwNewSiteID, pdwSiteID);
  374. BAIL_ON_FAILURE(hr);
  375. VariantInit( pvActualID );
  376. pvActualID->vt = VT_I4;
  377. pvActualID->lVal = dwNewSiteID;
  378. error:
  379. if (pcsfFactory) {
  380. pcsfFactory->Release();
  381. }
  382. if (pAppAdmin) {
  383. pAppAdmin->Release();
  384. }
  385. if (wszServerBindings) {
  386. delete [] wszServerBindings;
  387. }
  388. RRETURN(hr);
  389. }
  390. HRESULT
  391. CIISWebService::ConvertArrayToMultiSZ(
  392. VARIANT varSafeArray,
  393. WCHAR **pszServerBindings
  394. )
  395. {
  396. HRESULT hr = S_OK;
  397. DWORD dwSLBound = 0;
  398. DWORD dwSUBound = 0;
  399. DWORD i = 0;
  400. SAFEARRAY * pArray = NULL;
  401. DWORD dwLen = 0;
  402. DWORD dwNumVariants = 0;
  403. VARIANT * pVarArray = NULL;
  404. VARIANT pElem;
  405. WCHAR* wszServerBindings = NULL;
  406. if(!(V_ISARRAY(&varSafeArray)))
  407. RRETURN(E_FAIL);
  408. //
  409. // This handles by-ref and regular SafeArrays.
  410. //
  411. if (V_VT(&varSafeArray) & VT_BYREF)
  412. pArray = *(V_ARRAYREF(&varSafeArray));
  413. else
  414. pArray = V_ARRAY(&varSafeArray);
  415. //
  416. // Check that there is only one dimension in this array
  417. //
  418. if (pArray && pArray->cDims != 1) {
  419. hr = E_FAIL;
  420. BAIL_ON_FAILURE(hr);
  421. }
  422. //
  423. // Check that there is at least one element in this array
  424. //
  425. if (!pArray ||
  426. ( pArray->rgsabound[0].cElements == 0) ) {
  427. wszServerBindings = new WCHAR [2];
  428. wszServerBindings[0] = 0;
  429. wszServerBindings[1] = 1;
  430. }
  431. else {
  432. //
  433. // We know that this is a valid single dimension array
  434. //
  435. hr = SafeArrayGetLBound(pArray,
  436. 1,
  437. (long FAR *)&dwSLBound
  438. );
  439. BAIL_ON_FAILURE(hr);
  440. hr = SafeArrayGetUBound(pArray,
  441. 1,
  442. (long FAR *)&dwSUBound
  443. );
  444. BAIL_ON_FAILURE(hr);
  445. dwNumVariants = dwSUBound - dwSLBound + 1;
  446. dwLen = 0;
  447. pVarArray = (PVARIANT)AllocADsMem(
  448. sizeof(VARIANT)*dwNumVariants
  449. );
  450. if (!pVarArray) {
  451. hr = E_OUTOFMEMORY;
  452. BAIL_ON_FAILURE(hr);
  453. }
  454. for (i = dwSLBound; i <= dwSUBound; i++) {
  455. VariantInit(&pElem);
  456. hr = SafeArrayGetElement(pArray,
  457. (long FAR *)&i,
  458. &pElem
  459. );
  460. BAIL_ON_FAILURE(hr);
  461. hr = VariantChangeType(&pElem, &pElem, 0, VT_BSTR);
  462. BAIL_ON_FAILURE(hr);
  463. dwLen = dwLen + wcslen(pElem.bstrVal) + 1;
  464. pVarArray[i] = pElem;
  465. }
  466. wszServerBindings = new WCHAR [dwLen + 1];
  467. WCHAR * pServerBindings = wszServerBindings;
  468. for (i = dwSLBound; i <= dwSUBound; i++) {
  469. wcscpy(pServerBindings, pVarArray[i].bstrVal);
  470. while (*pServerBindings != 0) {
  471. pServerBindings++;
  472. }
  473. pServerBindings++;
  474. }
  475. *pServerBindings = 0;
  476. }
  477. *pszServerBindings = wszServerBindings;
  478. error:
  479. if (pVarArray) {
  480. FreeADsMem(pVarArray);
  481. }
  482. RRETURN(hr);
  483. }
  484. STDMETHODIMP
  485. CIISWebService::GetCurrentMode(
  486. VARIANT FAR* pvServerMode
  487. )
  488. {
  489. HRESULT hr = S_OK;
  490. DWORD dwServerMode = 0;
  491. COSERVERINFO csiName;
  492. COSERVERINFO *pcsiParam = &csiName;
  493. IClassFactory * pcsfFactory = NULL;
  494. IWamAdmin * pWamAdmin = NULL;
  495. IIISApplicationAdmin * pAppAdmin = NULL;
  496. memset(pcsiParam, 0, sizeof(COSERVERINFO));
  497. //
  498. // special case to handle "localhost" to work-around ole32 bug
  499. //
  500. if (_pszServerName == NULL || _wcsicmp(_pszServerName,L"localhost") == 0) {
  501. pcsiParam->pwszName = NULL;
  502. }
  503. else {
  504. pcsiParam->pwszName = _pszServerName;
  505. }
  506. csiName.pAuthInfo = NULL;
  507. pcsiParam = &csiName;
  508. hr = CoGetClassObject(
  509. CLSID_WamAdmin,
  510. CLSCTX_SERVER,
  511. pcsiParam,
  512. IID_IClassFactory,
  513. (void**) &pcsfFactory
  514. );
  515. BAIL_ON_FAILURE(hr);
  516. hr = pcsfFactory->CreateInstance(
  517. NULL,
  518. IID_IWamAdmin,
  519. (void **) &pWamAdmin
  520. );
  521. BAIL_ON_FAILURE(hr);
  522. // test here for 5.1 compat
  523. hr = pWamAdmin->QueryInterface(
  524. IID_IIISApplicationAdmin,
  525. (void **)&pAppAdmin
  526. );
  527. BAIL_ON_FAILURE(hr);
  528. // Call GetProcessMode - it's returning GetCurrentMode
  529. // after it checks to make sure the W3SVC is running.
  530. hr = pAppAdmin->GetProcessMode( &dwServerMode );
  531. BAIL_ON_FAILURE(hr);
  532. VariantInit( pvServerMode );
  533. pvServerMode->vt = VT_I4;
  534. pvServerMode->lVal = dwServerMode;
  535. error:
  536. if (pcsfFactory) {
  537. pcsfFactory->Release();
  538. }
  539. if (pWamAdmin) {
  540. pWamAdmin->Release();
  541. }
  542. if (pAppAdmin) {
  543. pAppAdmin->Release();
  544. }
  545. RRETURN(hr);
  546. }