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.

2332 lines
52 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997
  5. //
  6. // File: cgenobj.cxx
  7. //
  8. // Contents: Microsoft ADs IIS Provider Generic Object
  9. //
  10. //
  11. // History: 28-Feb-97 SophiaC Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "iis.hxx"
  15. #pragma hdrstop
  16. // Class CIISGenObject
  17. DEFINE_IDispatch_ExtMgr_Implementation(CIISGenObject)
  18. DEFINE_IADs_Implementation(CIISGenObject)
  19. CIISGenObject::CIISGenObject():
  20. _pExtMgr(NULL),
  21. _pPropertyCache(NULL),
  22. _pszServerName(NULL),
  23. _pszMetaBasePath(NULL),
  24. _pAdminBase(NULL),
  25. _pSchema(NULL)
  26. {
  27. VariantInit(&_vFilter);
  28. ENLIST_TRACKING(CIISGenObject);
  29. }
  30. HRESULT
  31. CIISGenObject::CreateGenericObject(
  32. BSTR bstrADsPath,
  33. BSTR ClassName,
  34. CCredentials& Credentials,
  35. DWORD dwObjectState,
  36. REFIID riid,
  37. void **ppvObj
  38. )
  39. {
  40. HRESULT hr = S_OK;
  41. LPWSTR pszADsParent = NULL;
  42. WCHAR szCommonName[MAX_PATH+MAX_PROVIDER_TOKEN_LENGTH];
  43. pszADsParent = AllocADsStr((LPWSTR)bstrADsPath);
  44. if (!pszADsParent) {
  45. hr = E_OUTOFMEMORY;
  46. BAIL_ON_FAILURE(hr);
  47. }
  48. *pszADsParent = L'\0';
  49. //
  50. // Determine the parent and rdn name
  51. //
  52. hr = BuildADsParentPath(
  53. bstrADsPath,
  54. pszADsParent,
  55. szCommonName
  56. );
  57. //
  58. // call the helper function
  59. //
  60. hr = CIISGenObject::CreateGenericObject(
  61. pszADsParent,
  62. szCommonName,
  63. ClassName,
  64. Credentials,
  65. dwObjectState,
  66. riid,
  67. ppvObj
  68. );
  69. error:
  70. if (pszADsParent) {
  71. FreeADsStr(pszADsParent);
  72. }
  73. RRETURN(hr);
  74. }
  75. HRESULT
  76. CIISGenObject::CreateGenericObject(
  77. BSTR Parent,
  78. BSTR CommonName,
  79. BSTR ClassName,
  80. CCredentials& Credentials,
  81. DWORD dwObjectState,
  82. REFIID riid,
  83. void **ppvObj
  84. )
  85. {
  86. CIISGenObject FAR * pGenObject = NULL;
  87. CADsExtMgr FAR * pExtensionMgr = NULL;
  88. HRESULT hr = S_OK;
  89. LPWSTR pszClassName = ClassName;
  90. hr = AllocateGenObject(ClassName, Credentials, &pGenObject);
  91. BAIL_ON_FAILURE(hr);
  92. hr = pGenObject->InitializeCoreObject(
  93. Parent,
  94. CommonName,
  95. ClassName,
  96. L"",
  97. CLSID_IISGenObject,
  98. dwObjectState
  99. );
  100. BAIL_ON_FAILURE(hr);
  101. hr = pGenObject->CacheMetaDataPath();
  102. BAIL_ON_FAILURE(hr);
  103. hr = pGenObject->_pPropertyCache->InitializePropertyCache(
  104. pGenObject->_pszServerName
  105. );
  106. BAIL_ON_FAILURE(hr);
  107. //
  108. // To maintain compatibility with IIS4 we want to fail when
  109. // creating a new object if the metabase path already exists.
  110. //
  111. if( ADS_OBJECT_UNBOUND == pGenObject->_dwObjectState )
  112. {
  113. hr = ::MetaBaseDetectKey( pGenObject->_pAdminBase,
  114. pGenObject->_pszMetaBasePath
  115. );
  116. if( SUCCEEDED(hr) )
  117. {
  118. hr = HRESULT_FROM_WIN32( ERROR_ALREADY_EXISTS );
  119. }
  120. else if( ERROR_PATH_NOT_FOUND == HRESULT_CODE(hr) )
  121. {
  122. hr = S_OK;
  123. }
  124. BAIL_ON_FAILURE(hr);
  125. }
  126. if ( !_wcsicmp(ClassName, L"IIsFtpServer") ||
  127. !_wcsicmp(ClassName, L"IIsWebServer") ||
  128. !_wcsicmp(ClassName, L"IIsNntpServer") ||
  129. !_wcsicmp(ClassName, L"IIsSmtpServer") ||
  130. !_wcsicmp(ClassName, L"IIsPop3Server") ||
  131. !_wcsicmp(ClassName, L"IIsImapServer")
  132. )
  133. {
  134. pszClassName = L"IIsServer";
  135. }
  136. else if ( !_wcsicmp(ClassName, L"IIsWebDirectory") ||
  137. !_wcsicmp(ClassName, L"IIsWebVirtualDir"))
  138. {
  139. pszClassName = L"IIsApp";
  140. }
  141. hr = ADSILoadExtensionManager(
  142. pszClassName,
  143. (IADs *)pGenObject,
  144. Credentials,
  145. pGenObject->_pDispMgr,
  146. &pExtensionMgr
  147. );
  148. BAIL_ON_FAILURE(hr);
  149. pGenObject->_pExtMgr = pExtensionMgr;
  150. hr = pGenObject->QueryInterface(riid, ppvObj);
  151. BAIL_ON_FAILURE(hr);
  152. pGenObject->Release();
  153. RRETURN(hr);
  154. error:
  155. delete pGenObject;
  156. RRETURN(hr);
  157. }
  158. CIISGenObject::~CIISGenObject( )
  159. {
  160. delete _pExtMgr;
  161. VariantClear(&_vFilter);
  162. delete _pDispMgr;
  163. delete _pPropertyCache;
  164. if (_pszServerName) {
  165. FreeADsStr(_pszServerName);
  166. }
  167. if (_pszMetaBasePath){
  168. FreeADsStr(_pszMetaBasePath);
  169. }
  170. }
  171. STDMETHODIMP
  172. CIISGenObject::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  173. {
  174. if (ppv == NULL) {
  175. RRETURN(E_POINTER);
  176. }
  177. if (IsEqualIID(iid, IID_IUnknown))
  178. {
  179. *ppv = (IADs FAR *) this;
  180. }
  181. else if (IsEqualIID(iid, IID_IADsContainer))
  182. {
  183. *ppv = (IADsContainer FAR *) this;
  184. }
  185. else if (IsEqualIID(iid, IID_IADs))
  186. {
  187. *ppv = (IADs FAR *) this;
  188. }
  189. else if (IsEqualIID(iid, IID_IISBaseObject))
  190. {
  191. *ppv = (IISBaseObject FAR *) this;
  192. }
  193. else if (IsEqualIID(iid, IID_IDispatch))
  194. {
  195. *ppv = (IADs FAR *) this;
  196. }
  197. else if (_pExtMgr)
  198. {
  199. RRETURN(_pExtMgr->QueryInterface(iid,ppv));
  200. }
  201. else
  202. {
  203. *ppv = NULL;
  204. return E_NOINTERFACE;
  205. }
  206. AddRef();
  207. return NOERROR;
  208. }
  209. HRESULT
  210. CIISGenObject::SetInfo()
  211. {
  212. HRESULT hr = S_OK;
  213. COSERVERINFO csiName;
  214. COSERVERINFO *pcsiParam = &csiName;
  215. IClassFactory * pcsfFactory = NULL;
  216. IIISApplicationAdmin * pAppAdmin = NULL;
  217. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  218. // Check to see if we're creating an IIsApplicationPool
  219. // If so, use the IISApplicationAdmin interface
  220. if ( !_wcsicmp(_ADsClass, L"IIsApplicationPool"))
  221. {
  222. memset(pcsiParam, 0, sizeof(COSERVERINFO));
  223. //
  224. // special case to handle "localhost" to work-around ole32 bug
  225. //
  226. if (_pszServerName == NULL || _wcsicmp(_pszServerName,L"localhost") == 0) {
  227. pcsiParam->pwszName = NULL;
  228. }
  229. else {
  230. pcsiParam->pwszName = _pszServerName;
  231. }
  232. hr = CoGetClassObject(
  233. CLSID_WamAdmin,
  234. CLSCTX_SERVER,
  235. pcsiParam,
  236. IID_IClassFactory,
  237. (void**) &pcsfFactory
  238. );
  239. BAIL_ON_FAILURE(hr);
  240. hr = pcsfFactory->CreateInstance(
  241. NULL,
  242. IID_IIISApplicationAdmin,
  243. (void **) &pAppAdmin
  244. );
  245. BAIL_ON_FAILURE(hr);
  246. hr = pAppAdmin->CreateApplicationPool( _Name );
  247. // Don't BAIL_ON_FAILURE here! Check the HR below first...
  248. }
  249. // Otherwise do the creation the old fashioned way
  250. else {
  251. hr = IISCreateObject();
  252. }
  253. //
  254. // Since methods that we aggregate like IIsApp::AppCreate may
  255. // persist our path in the metabase we don't want to fail just
  256. // because the path exists. This is done to maintain backward
  257. // compatibility with IIS4.
  258. //
  259. if( ERROR_ALREADY_EXISTS != HRESULT_CODE(hr) )
  260. {
  261. BAIL_ON_FAILURE(hr);
  262. }
  263. //
  264. // If the create succeded, set the object type to bound
  265. //
  266. SetObjectState(ADS_OBJECT_BOUND);
  267. }
  268. hr = IISSetObject();
  269. BAIL_ON_FAILURE(hr);
  270. error:
  271. if (pcsfFactory) {
  272. pcsfFactory->Release();
  273. }
  274. if (pAppAdmin) {
  275. pAppAdmin->Release();
  276. }
  277. RRETURN(hr);
  278. }
  279. HRESULT
  280. CIISGenObject::IISSetObject()
  281. {
  282. HRESULT hr = S_OK;
  283. METADATA_HANDLE hObjHandle = NULL;
  284. PMETADATA_RECORD pMetaDataArray = NULL;
  285. DWORD dwMDNumDataEntries = 0;
  286. //
  287. // Add SetObject functionality : sophiac
  288. //
  289. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  290. hr = E_ADS_OBJECT_UNBOUND;
  291. BAIL_ON_FAILURE(hr);
  292. }
  293. hr = OpenAdminBaseKey(
  294. _pszServerName,
  295. (LPWSTR) _pszMetaBasePath,
  296. METADATA_PERMISSION_WRITE,
  297. &_pAdminBase,
  298. &hObjHandle
  299. );
  300. BAIL_ON_FAILURE(hr);
  301. hr = _pPropertyCache->IISMarshallProperties(
  302. &pMetaDataArray,
  303. &dwMDNumDataEntries
  304. );
  305. BAIL_ON_FAILURE(hr);
  306. hr = MetaBaseSetAllData(
  307. _pAdminBase,
  308. hObjHandle,
  309. L"",
  310. (PMETADATA_RECORD)pMetaDataArray,
  311. dwMDNumDataEntries
  312. );
  313. BAIL_ON_FAILURE(hr);
  314. error:
  315. if (pMetaDataArray) {
  316. FreeMetaDataRecordArray(pMetaDataArray, dwMDNumDataEntries);
  317. }
  318. if (_pAdminBase && hObjHandle) {
  319. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  320. }
  321. RRETURN(hr);
  322. }
  323. HRESULT
  324. CIISGenObject::IISCreateObject()
  325. {
  326. HRESULT hr = S_OK;
  327. METADATA_HANDLE hObjHandle = NULL;
  328. METADATA_RECORD mdrData;
  329. WCHAR DataBuf[MAX_PATH];
  330. //
  331. // Add CreateObject functionality : sophiac
  332. //
  333. hr = OpenAdminBaseKey(
  334. _pszServerName,
  335. L"",
  336. METADATA_PERMISSION_WRITE,
  337. &_pAdminBase,
  338. &hObjHandle
  339. );
  340. BAIL_ON_FAILURE(hr);
  341. //
  342. // Pass in full path
  343. //
  344. hr = MetaBaseCreateObject(
  345. _pAdminBase,
  346. hObjHandle,
  347. _pszMetaBasePath
  348. );
  349. if( ERROR_ALREADY_EXISTS != HRESULT_CODE(hr) )
  350. {
  351. BAIL_ON_FAILURE(hr);
  352. }
  353. //
  354. // Set KeyType
  355. //
  356. wcscpy((LPWSTR)DataBuf, _ADsClass);
  357. mdrData.dwMDIdentifier = MD_KEY_TYPE;
  358. mdrData.dwMDDataType = STRING_METADATA;
  359. mdrData.dwMDUserType = IIS_MD_UT_SERVER;
  360. mdrData.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  361. mdrData.dwMDDataLen = (wcslen(DataBuf)+1)*2;
  362. mdrData.pbMDData = (PBYTE)DataBuf;
  363. hr = _pAdminBase->SetData(
  364. hObjHandle,
  365. _pszMetaBasePath,
  366. &mdrData);
  367. BAIL_ON_FAILURE(hr);
  368. error:
  369. if (_pAdminBase && hObjHandle) {
  370. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  371. }
  372. RRETURN(hr);
  373. }
  374. HRESULT
  375. CIISGenObject::GetInfo()
  376. {
  377. _pPropertyCache->flushpropcache();
  378. RRETURN(GetInfo(TRUE));
  379. }
  380. HRESULT
  381. CIISGenObject::GetInfo(
  382. BOOL fExplicit
  383. )
  384. {
  385. HRESULT hr = S_OK;
  386. METADATA_HANDLE hObjHandle = NULL;
  387. DWORD dwMDAttributes = METADATA_INHERIT;
  388. DWORD dwMDUserType = ALL_METADATA;
  389. DWORD dwMDDataType = ALL_METADATA;
  390. DWORD dwMDNumDataEntries;
  391. DWORD dwMDDataSetNumber;
  392. LPBYTE pBuffer = NULL;
  393. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  394. hr = E_ADS_OBJECT_UNBOUND;
  395. BAIL_ON_FAILURE(hr);
  396. }
  397. hr = OpenAdminBaseKey(
  398. _pszServerName,
  399. _pszMetaBasePath,
  400. METADATA_PERMISSION_READ,
  401. &_pAdminBase,
  402. &hObjHandle
  403. );
  404. BAIL_ON_FAILURE(hr);
  405. hr = MetaBaseGetAllData(
  406. _pAdminBase,
  407. hObjHandle,
  408. L"",
  409. dwMDAttributes,
  410. dwMDUserType,
  411. dwMDDataType,
  412. &dwMDNumDataEntries,
  413. &dwMDDataSetNumber,
  414. (LPBYTE *)&pBuffer
  415. );
  416. BAIL_ON_FAILURE(hr);
  417. hr = _pPropertyCache->IISUnMarshallProperties(
  418. pBuffer,
  419. pBuffer,
  420. dwMDNumDataEntries,
  421. fExplicit
  422. );
  423. BAIL_ON_FAILURE(hr);
  424. error:
  425. if (pBuffer) {
  426. FreeADsMem(pBuffer);
  427. }
  428. if (_pAdminBase && hObjHandle) {
  429. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  430. }
  431. RRETURN(hr);
  432. }
  433. /* IADsContainer methods */
  434. STDMETHODIMP
  435. CIISGenObject::get_Count(long FAR* retval)
  436. {
  437. RRETURN(E_NOTIMPL);
  438. }
  439. STDMETHODIMP
  440. CIISGenObject::get_Filter(THIS_ VARIANT FAR* pVar)
  441. {
  442. RRETURN(E_NOTIMPL);
  443. }
  444. STDMETHODIMP
  445. CIISGenObject::put_Filter(THIS_ VARIANT Var)
  446. {
  447. RRETURN(E_NOTIMPL);
  448. }
  449. STDMETHODIMP
  450. CIISGenObject::put_Hints(THIS_ VARIANT Var)
  451. {
  452. RRETURN( E_NOTIMPL);
  453. }
  454. STDMETHODIMP
  455. CIISGenObject::get_Hints(THIS_ VARIANT FAR* pVar)
  456. {
  457. RRETURN(E_NOTIMPL);
  458. }
  459. STDMETHODIMP
  460. CIISGenObject::GetObject(
  461. BSTR ClassName,
  462. BSTR RelativeName,
  463. IDispatch * FAR* ppObject
  464. )
  465. {
  466. HRESULT hr = S_OK;
  467. hr = ::RelativeGetObject(
  468. _ADsPath,
  469. ClassName,
  470. RelativeName,
  471. _Credentials,
  472. ppObject,
  473. FALSE
  474. );
  475. RRETURN(hr);
  476. }
  477. STDMETHODIMP
  478. CIISGenObject::get__NewEnum(
  479. THIS_ IUnknown * FAR* retval
  480. )
  481. {
  482. HRESULT hr;
  483. IUnknown FAR* punkEnum=NULL;
  484. IEnumVARIANT * penum = NULL;
  485. *retval = NULL;
  486. hr = CIISGenObjectEnum::Create(
  487. (CIISGenObjectEnum **)&penum,
  488. _ADsPath,
  489. _vFilter,
  490. _Credentials
  491. );
  492. BAIL_ON_FAILURE(hr);
  493. hr = penum->QueryInterface(
  494. IID_IUnknown,
  495. (VOID FAR* FAR*)retval
  496. );
  497. BAIL_ON_FAILURE(hr);
  498. if (penum) {
  499. penum->Release();
  500. }
  501. RRETURN(NOERROR);
  502. error:
  503. if (penum) {
  504. delete penum;
  505. }
  506. RRETURN(hr);
  507. }
  508. inline
  509. HRESULT
  510. ValidateRelativePath(
  511. IN LPCWSTR wszRelativePath
  512. )
  513. /*++
  514. Routine Description:
  515. Determine if a relative path is valid. This is really just to check
  516. assumptions that are made about the relative path.
  517. It doesn't do much now, but might be expanded and moved to a common
  518. location if necessary.
  519. Arguments:
  520. IN wszRelativePath : a relative ads path
  521. Return Value:
  522. E_ADS_BAD_PATHNAME if the path is not valid
  523. --*/
  524. {
  525. HRESULT hr = E_ADS_BAD_PATHNAME;
  526. if( wszRelativePath && *wszRelativePath != L'/' )
  527. {
  528. hr = S_OK;
  529. }
  530. RRETURN(hr);
  531. }
  532. STDMETHODIMP
  533. CIISGenObject::Create(
  534. THIS_ BSTR ClassName,
  535. BSTR RelativeName,
  536. IDispatch * FAR* ppObject
  537. )
  538. {
  539. HRESULT hr = S_OK;
  540. IADs * pADs = NULL;
  541. BOOL bRelativeNameExtended = FALSE;
  542. LPWSTR pwszParentClass = NULL;
  543. LPWSTR pwszParentADsPath = NULL;
  544. LPWSTR pwszRelativeName = NULL;
  545. DWORD i = 0;
  546. //
  547. // Validate if this class really exists in the schema
  548. // and validate that this object can be created in this
  549. // container
  550. //
  551. hr = _pSchema->ValidateClassName(ClassName);
  552. BAIL_ON_FAILURE(hr);
  553. //
  554. // Handle case where RelativeName may be an extended path,
  555. // such as foo/bar/baz.
  556. //
  557. hr = ValidateRelativePath( RelativeName );
  558. BAIL_ON_FAILURE(hr);
  559. bRelativeNameExtended = ( wcschr( RelativeName, L'/' ) != NULL );
  560. if( bRelativeNameExtended )
  561. {
  562. pwszRelativeName = wcsrchr( RelativeName, L'/' ) + 1;
  563. hr = ResolveExtendedChildPath( RelativeName,
  564. &pwszParentADsPath,
  565. &pwszParentClass );
  566. BAIL_ON_FAILURE(hr);
  567. }
  568. else
  569. {
  570. pwszParentClass = _ADsClass;
  571. pwszParentADsPath = _ADsPath;
  572. pwszRelativeName = RelativeName;
  573. }
  574. //
  575. // validate name --> can't have ',' in the name
  576. //
  577. while (RelativeName[i] != L'\0' && RelativeName[i] != L',')
  578. i++;
  579. if (RelativeName[i] != L'\0' || i >= METADATA_MAX_NAME_LEN) {
  580. hr = E_ADS_BAD_PARAMETER;
  581. BAIL_ON_FAILURE(hr);
  582. }
  583. hr = _pSchema->ValidateContainedClassName(pwszParentClass, ClassName);
  584. BAIL_ON_FAILURE(hr);
  585. hr = CIISGenObject::CreateGenericObject(
  586. pwszParentADsPath,
  587. pwszRelativeName,
  588. ClassName,
  589. _Credentials,
  590. ADS_OBJECT_UNBOUND,
  591. IID_IADs,
  592. (void **)&pADs
  593. );
  594. BAIL_ON_FAILURE(hr);
  595. hr = pADs->QueryInterface(
  596. IID_IDispatch,
  597. (void **)ppObject
  598. );
  599. BAIL_ON_FAILURE(hr);
  600. error:
  601. if (pADs) {
  602. pADs->Release();
  603. }
  604. if( bRelativeNameExtended )
  605. {
  606. ADsFreeString( pwszParentClass );
  607. ADsFreeString( pwszParentADsPath );
  608. }
  609. RRETURN(hr);
  610. }
  611. STDMETHODIMP
  612. CIISGenObject::Delete(
  613. THIS_ BSTR bstrClassName,
  614. BSTR bstrRelativeName
  615. )
  616. {
  617. HRESULT hr = S_OK;
  618. METADATA_HANDLE hObjHandle = NULL;
  619. COSERVERINFO csiName;
  620. COSERVERINFO *pcsiParam = &csiName;
  621. IClassFactory * pcsfFactory = NULL;
  622. IIISApplicationAdmin * pAppAdmin = NULL;
  623. //
  624. // Get Server and Path name
  625. //
  626. hr = CacheMetaDataPath();
  627. BAIL_ON_FAILURE(hr);
  628. // Check to see if we're deleting an IIsApplicationPool
  629. // If so, use the IISApplicationAdmin interface
  630. if ( !_wcsicmp(bstrClassName, L"IIsApplicationPool"))
  631. {
  632. memset(pcsiParam, 0, sizeof(COSERVERINFO));
  633. //
  634. // special case to handle "localhost" to work-around ole32 bug
  635. //
  636. if (_pszServerName == NULL || _wcsicmp(_pszServerName,L"localhost") == 0) {
  637. pcsiParam->pwszName = NULL;
  638. }
  639. else {
  640. pcsiParam->pwszName = _pszServerName;
  641. }
  642. hr = CoGetClassObject(
  643. CLSID_WamAdmin,
  644. CLSCTX_SERVER,
  645. pcsiParam,
  646. IID_IClassFactory,
  647. (void**) &pcsfFactory
  648. );
  649. BAIL_ON_FAILURE(hr);
  650. hr = pcsfFactory->CreateInstance(
  651. NULL,
  652. IID_IIISApplicationAdmin,
  653. (void **) &pAppAdmin
  654. );
  655. BAIL_ON_FAILURE(hr);
  656. hr = pAppAdmin->DeleteApplicationPool( bstrRelativeName );
  657. BAIL_ON_FAILURE(hr);
  658. }
  659. // Otherwise do the delete the old fashioned way
  660. else {
  661. hr = OpenAdminBaseKey(
  662. _pszServerName,
  663. _pszMetaBasePath,
  664. METADATA_PERMISSION_WRITE,
  665. &_pAdminBase,
  666. &hObjHandle
  667. );
  668. BAIL_ON_FAILURE(hr);
  669. //
  670. // Pass in full path
  671. //
  672. hr = MetaBaseDeleteObject(
  673. _pAdminBase,
  674. hObjHandle,
  675. (LPWSTR)bstrRelativeName
  676. );
  677. BAIL_ON_FAILURE(hr);
  678. }
  679. error:
  680. if (pcsfFactory) {
  681. pcsfFactory->Release();
  682. }
  683. if (pAppAdmin) {
  684. pAppAdmin->Release();
  685. }
  686. if (_pAdminBase && hObjHandle) {
  687. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  688. }
  689. RRETURN(hr);
  690. }
  691. STDMETHODIMP
  692. CIISGenObject::CopyHere(
  693. THIS_ BSTR SourceName,
  694. BSTR NewName,
  695. IDispatch * FAR* ppObject
  696. )
  697. {
  698. HRESULT hr = S_OK;
  699. IUnknown *pUnk = NULL;
  700. METADATA_HANDLE hObjHandle = NULL;
  701. LPWSTR pszIISPathName = NULL;
  702. IADs *pADs = NULL;
  703. BSTR bstrClassName = NULL;
  704. LPWSTR pszPath = NULL;
  705. IWamAdmin2 *pWamAdmin = NULL;
  706. LPWSTR pszIISNewName = NULL;
  707. hr = InitWamAdmin(_pszServerName, &pWamAdmin);
  708. BAIL_ON_FAILURE(hr);
  709. //
  710. // open common path node
  711. //
  712. hr = BuildIISPathFromADsPath(
  713. _ADsPath,
  714. &pszIISPathName
  715. );
  716. BAIL_ON_FAILURE(hr);
  717. hr = OpenAdminBaseKey(
  718. _pszServerName,
  719. pszIISPathName,
  720. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  721. &_pAdminBase,
  722. &hObjHandle
  723. );
  724. BAIL_ON_FAILURE(hr);
  725. //
  726. // Do Copy operation
  727. //
  728. hr = MetaBaseCopyObject(
  729. _pAdminBase,
  730. hObjHandle,
  731. (LPWSTR)SourceName,
  732. hObjHandle,
  733. (LPWSTR)NewName
  734. );
  735. BAIL_ON_FAILURE(hr);
  736. if (hObjHandle) {
  737. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  738. hObjHandle = NULL;
  739. }
  740. if (pszIISPathName) {
  741. DWORD dwLen;
  742. dwLen = wcslen(pszIISPathName) + wcslen(NewName) + 2;
  743. pszIISNewName = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
  744. if (!pszIISNewName) {
  745. hr = E_OUTOFMEMORY;
  746. BAIL_ON_FAILURE(hr);
  747. }
  748. wcscpy(pszIISNewName, pszIISPathName);
  749. if (NewName) {
  750. wcscat(pszIISNewName, L"/");
  751. wcscat(pszIISNewName, (LPWSTR)NewName);
  752. }
  753. }
  754. hr = pWamAdmin->AppRecover((LPWSTR) pszIISNewName, TRUE);
  755. BAIL_ON_FAILURE(hr);
  756. hr = get_CoreADsClass(&bstrClassName);
  757. BAIL_ON_FAILURE(hr);
  758. hr = CIISGenObject::CreateGenericObject(
  759. _ADsPath,
  760. NewName,
  761. bstrClassName,
  762. _Credentials,
  763. ADS_OBJECT_BOUND,
  764. IID_IADs,
  765. (void **)&pADs
  766. );
  767. BAIL_ON_FAILURE(hr);
  768. pszPath = ((CIISGenObject*)pADs)->ReturnMetaDataPath();
  769. hr = pADs->QueryInterface(
  770. IID_IDispatch,
  771. (void **)ppObject
  772. );
  773. BAIL_ON_FAILURE(hr);
  774. error:
  775. if (_pAdminBase) {
  776. if (hObjHandle) {
  777. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  778. }
  779. }
  780. if (pWamAdmin) {
  781. UninitWamAdmin(pWamAdmin);
  782. }
  783. if (bstrClassName) {
  784. ADsFreeString(bstrClassName);
  785. }
  786. if (pszIISPathName) {
  787. FreeADsStr(pszIISPathName);
  788. }
  789. if (pszIISNewName) {
  790. FreeADsMem(pszIISNewName);
  791. }
  792. if (pADs){
  793. pADs->Release();
  794. }
  795. RRETURN(hr);
  796. }
  797. STDMETHODIMP
  798. CIISGenObject::MoveHere(
  799. THIS_ BSTR SourceName,
  800. BSTR NewName,
  801. IDispatch * FAR* ppObject
  802. )
  803. {
  804. HRESULT hr = S_OK;
  805. IUnknown *pUnk = NULL;
  806. METADATA_HANDLE hObjHandle = NULL;
  807. LPWSTR pszIISPathName = NULL;
  808. IADs *pADs = NULL;
  809. BSTR bstrClassName = NULL;
  810. LPWSTR pszPath = NULL;
  811. IWamAdmin2 *pWamAdmin = NULL;
  812. LPWSTR pszIISOldName = NULL;
  813. LPWSTR pszIISNewName = NULL;
  814. hr = InitWamAdmin(_pszServerName, &pWamAdmin);
  815. BAIL_ON_FAILURE(hr);
  816. //
  817. // open common path node
  818. //
  819. hr = BuildIISPathFromADsPath(
  820. _ADsPath,
  821. &pszIISPathName
  822. );
  823. BAIL_ON_FAILURE(hr);
  824. if (pszIISPathName) {
  825. DWORD dwLen;
  826. dwLen = wcslen(pszIISPathName) + wcslen(SourceName) + 2;
  827. pszIISOldName = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
  828. if (!pszIISOldName) {
  829. hr = E_OUTOFMEMORY;
  830. BAIL_ON_FAILURE(hr);
  831. }
  832. wcscpy(pszIISOldName, pszIISPathName);
  833. if (NewName) {
  834. wcscat(pszIISOldName, L"/");
  835. wcscat(pszIISOldName, (LPWSTR)SourceName);
  836. }
  837. }
  838. hr = pWamAdmin->AppDeleteRecoverable((LPWSTR) pszIISOldName, TRUE);
  839. BAIL_ON_FAILURE(hr);
  840. hr = OpenAdminBaseKey(
  841. _pszServerName,
  842. pszIISPathName,
  843. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  844. &_pAdminBase,
  845. &hObjHandle
  846. );
  847. BAIL_ON_FAILURE(hr);
  848. //
  849. // Do Move operation
  850. //
  851. hr = MetaBaseMoveObject(
  852. _pAdminBase,
  853. hObjHandle,
  854. (LPWSTR)SourceName,
  855. hObjHandle,
  856. (LPWSTR)NewName
  857. );
  858. BAIL_ON_FAILURE(hr);
  859. if (hObjHandle) {
  860. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  861. hObjHandle = NULL;
  862. }
  863. if (pszIISPathName) {
  864. DWORD dwLen;
  865. dwLen = wcslen(pszIISPathName) + wcslen(NewName) + 2;
  866. pszIISNewName = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
  867. if (!pszIISNewName) {
  868. hr = E_OUTOFMEMORY;
  869. BAIL_ON_FAILURE(hr);
  870. }
  871. wcscpy(pszIISNewName, pszIISPathName);
  872. if (NewName) {
  873. wcscat(pszIISNewName, L"/");
  874. wcscat(pszIISNewName, (LPWSTR)NewName);
  875. }
  876. }
  877. hr = pWamAdmin->AppRecover((LPWSTR) pszIISNewName, TRUE);
  878. BAIL_ON_FAILURE(hr);
  879. hr = get_CoreADsClass(&bstrClassName);
  880. BAIL_ON_FAILURE(hr);
  881. hr = CIISGenObject::CreateGenericObject(
  882. _ADsPath,
  883. NewName,
  884. bstrClassName,
  885. _Credentials,
  886. ADS_OBJECT_BOUND,
  887. IID_IADs,
  888. (void **)&pADs
  889. );
  890. BAIL_ON_FAILURE(hr);
  891. pszPath = ((CIISGenObject*)pADs)->ReturnMetaDataPath();
  892. hr = pADs->QueryInterface(
  893. IID_IDispatch,
  894. (void **)ppObject
  895. );
  896. BAIL_ON_FAILURE(hr);
  897. error:
  898. if (_pAdminBase) {
  899. if (hObjHandle) {
  900. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  901. }
  902. }
  903. if (pWamAdmin) {
  904. UninitWamAdmin(pWamAdmin);
  905. }
  906. if (bstrClassName) {
  907. ADsFreeString(bstrClassName);
  908. }
  909. if (pszIISPathName) {
  910. FreeADsStr(pszIISPathName);
  911. }
  912. if (pszIISOldName) {
  913. FreeADsMem(pszIISOldName);
  914. }
  915. if (pszIISNewName) {
  916. FreeADsMem(pszIISNewName);
  917. }
  918. if (pADs){
  919. pADs->Release();
  920. }
  921. RRETURN(hr);
  922. }
  923. HRESULT
  924. CIISGenObject::AllocateGenObject(
  925. LPWSTR pszClassName,
  926. CCredentials& Credentials,
  927. CIISGenObject ** ppGenObject
  928. )
  929. {
  930. CIISGenObject FAR * pGenObject = NULL;
  931. CAggregatorDispMgr FAR * pDispMgr = NULL;
  932. CPropertyCache FAR * pPropertyCache = NULL;
  933. HRESULT hr = S_OK;
  934. pGenObject = new CIISGenObject();
  935. if (pGenObject == NULL) {
  936. hr = E_OUTOFMEMORY;
  937. }
  938. BAIL_ON_FAILURE(hr);
  939. pDispMgr = new CAggregatorDispMgr;
  940. if (pDispMgr == NULL) {
  941. hr = E_OUTOFMEMORY;
  942. }
  943. BAIL_ON_FAILURE(hr);
  944. hr = pDispMgr->LoadTypeInfoEntry(
  945. LIBID_ADs,
  946. IID_IADs,
  947. (IADs *)pGenObject,
  948. DISPID_REGULAR
  949. );
  950. BAIL_ON_FAILURE(hr);
  951. hr = pDispMgr->LoadTypeInfoEntry(LIBID_ADs,
  952. IID_IADsContainer,
  953. (IADsContainer *)pGenObject,
  954. DISPID_NEWENUM
  955. );
  956. BAIL_ON_FAILURE(hr);
  957. hr = pDispMgr->LoadTypeInfoEntry(
  958. LIBID_IISOle,
  959. IID_IISBaseObject,
  960. (IISBaseObject *)pGenObject,
  961. DISPID_REGULAR
  962. );
  963. BAIL_ON_FAILURE(hr);
  964. hr = CPropertyCache::createpropertycache(
  965. (CCoreADsObject FAR *)pGenObject,
  966. &pPropertyCache
  967. );
  968. BAIL_ON_FAILURE(hr);
  969. pDispMgr->RegisterPropertyCache((IPropertyCache*)pPropertyCache);
  970. pGenObject->_Credentials = Credentials;
  971. pGenObject->_pPropertyCache = pPropertyCache;
  972. pGenObject->_pDispMgr = pDispMgr;
  973. *ppGenObject = pGenObject;
  974. RRETURN(hr);
  975. error:
  976. delete pDispMgr;
  977. RRETURN(hr);
  978. }
  979. /* INTRINSA suppress=null_pointers, uninitialized */
  980. STDMETHODIMP
  981. CIISGenObject::Get(
  982. THIS_ BSTR bstrName,
  983. VARIANT FAR* pvProp
  984. )
  985. {
  986. HRESULT hr = S_OK;
  987. DWORD dwSyntaxId;
  988. DWORD dwSyntax;
  989. DWORD dwNumValues = 0;
  990. LPIISOBJECT pIISSrcObjects = NULL;
  991. WCHAR wchName[MAX_PATH];
  992. BSTR bstrClassName = NULL;
  993. //
  994. // check if property is a supported property
  995. //
  996. hr = get_CoreADsClass(&bstrClassName);
  997. BAIL_ON_FAILURE(hr);
  998. hr = _pSchema->ValidateProperty(bstrClassName, bstrName);
  999. BAIL_ON_FAILURE(hr);
  1000. //
  1001. // lookup ADSI IIS syntax Id
  1002. //
  1003. hr = _pSchema->LookupSyntaxID(bstrName, &dwSyntax);
  1004. BAIL_ON_FAILURE(hr);
  1005. //
  1006. // check if property is BITMASK type;
  1007. // if BITMASK type, get corresponding DWORD flag property
  1008. //
  1009. // check if property is RAW BINARY type;
  1010. // if RAW BINARY type, get corresponding NTACL flag property
  1011. //
  1012. if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY) {
  1013. hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
  1014. BAIL_ON_FAILURE(hr);
  1015. }
  1016. //
  1017. // retrieve data object from cache; if one exists
  1018. //
  1019. if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY)
  1020. {
  1021. hr = _pPropertyCache->getproperty(
  1022. wchName,
  1023. &dwSyntaxId,
  1024. &dwNumValues,
  1025. &pIISSrcObjects
  1026. );
  1027. }
  1028. else
  1029. {
  1030. hr = _pPropertyCache->getproperty(
  1031. bstrName,
  1032. &dwSyntaxId,
  1033. &dwNumValues,
  1034. &pIISSrcObjects
  1035. );
  1036. }
  1037. BAIL_ON_FAILURE(hr);
  1038. //
  1039. // reset it to its syntax id if BITMASK type
  1040. //
  1041. pIISSrcObjects->IISType = dwSyntax;
  1042. //
  1043. // translate the IIS objects to variants
  1044. //
  1045. //
  1046. // always return an array for multisz type
  1047. //
  1048. if (dwNumValues == 1 && dwSyntax != IIS_SYNTAX_ID_MULTISZ &&
  1049. dwSyntax != IIS_SYNTAX_ID_MIMEMAP ) {
  1050. hr = IISTypeToVarTypeCopy(
  1051. _pSchema,
  1052. bstrName,
  1053. pIISSrcObjects,
  1054. pvProp,
  1055. FALSE
  1056. );
  1057. }else {
  1058. hr = IISTypeToVarTypeCopyConstruct(
  1059. _pSchema,
  1060. bstrName,
  1061. pIISSrcObjects,
  1062. dwNumValues,
  1063. pvProp,
  1064. FALSE
  1065. );
  1066. }
  1067. BAIL_ON_FAILURE(hr);
  1068. error:
  1069. if (bstrClassName) {
  1070. ADsFreeString(bstrClassName);
  1071. }
  1072. if (pIISSrcObjects) {
  1073. IISTypeFreeIISObjects(
  1074. pIISSrcObjects,
  1075. dwNumValues
  1076. );
  1077. }
  1078. RRETURN(hr);
  1079. }
  1080. STDMETHODIMP
  1081. CIISGenObject::Put(
  1082. THIS_ BSTR bstrName,
  1083. VARIANT vProp
  1084. )
  1085. {
  1086. HRESULT hr = S_OK;
  1087. DWORD dwSyntaxId = 0;
  1088. DWORD dwIndex = 0;
  1089. LPIISOBJECT pIISDestObjects = NULL;
  1090. DWORD dwNumValues = 0;
  1091. VARIANT * pVarArray = NULL;
  1092. VARIANT * pvProp = NULL;
  1093. VARIANT vVar;
  1094. WCHAR wchName[MAX_PATH];
  1095. BSTR bstrClassName = NULL;
  1096. //
  1097. // check if property is a supported property
  1098. //
  1099. hr = get_CoreADsClass(&bstrClassName);
  1100. BAIL_ON_FAILURE(hr);
  1101. hr = _pSchema->ValidateProperty(bstrClassName, bstrName);
  1102. BAIL_ON_FAILURE(hr);
  1103. //
  1104. // lookup its syntax ID
  1105. //
  1106. hr = _pSchema->LookupSyntaxID( bstrName, &dwSyntaxId);
  1107. BAIL_ON_FAILURE(hr);
  1108. //
  1109. // Issue: How do we handle multi-valued support
  1110. //
  1111. VariantInit(&vVar);
  1112. VariantCopyInd(&vVar, &vProp);
  1113. if ((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar)) {
  1114. hr = ConvertArrayToVariantArray(
  1115. vVar,
  1116. &pVarArray,
  1117. &dwNumValues
  1118. );
  1119. BAIL_ON_FAILURE(hr);
  1120. pvProp = pVarArray;
  1121. }
  1122. else {
  1123. dwNumValues = 1;
  1124. pvProp = &vVar;
  1125. }
  1126. //
  1127. // check if the variant maps to the syntax of this property
  1128. //
  1129. hr = VarTypeToIISTypeCopyConstruct(
  1130. dwSyntaxId,
  1131. pvProp,
  1132. dwNumValues,
  1133. &pIISDestObjects,
  1134. FALSE
  1135. );
  1136. BAIL_ON_FAILURE(hr);
  1137. //
  1138. // check if property is BITMASK type;
  1139. // if BITMASK type, get corresponding DWORD flag property
  1140. //
  1141. if (dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
  1142. VARIANT vGetProp;
  1143. DWORD dwMask;
  1144. DWORD dwFlagValue;
  1145. hr = _pSchema->LookupBitMask(bstrName, &dwMask);
  1146. BAIL_ON_FAILURE(hr);
  1147. //
  1148. // get its corresponding DWORD flag value
  1149. //
  1150. hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
  1151. BAIL_ON_FAILURE(hr);
  1152. VariantInit(&vGetProp);
  1153. hr = Get(wchName, &vGetProp);
  1154. BAIL_ON_FAILURE(hr);
  1155. dwFlagValue = V_I4(&vGetProp);
  1156. if (pIISDestObjects->IISValue.value_1.dwDWORD) {
  1157. dwFlagValue |= dwMask;
  1158. }
  1159. else {
  1160. dwFlagValue &= ~dwMask;
  1161. }
  1162. pIISDestObjects->IISValue.value_1.dwDWORD = dwFlagValue;
  1163. pIISDestObjects->IISType = IIS_SYNTAX_ID_DWORD;
  1164. bstrName = wchName;
  1165. }
  1166. if (dwSyntaxId == IIS_SYNTAX_ID_BINARY) {
  1167. hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
  1168. BAIL_ON_FAILURE(hr);
  1169. bstrName = wchName;
  1170. }
  1171. //
  1172. // Find this property in the cache
  1173. //
  1174. hr = _pPropertyCache->findproperty(
  1175. bstrName,
  1176. &dwIndex
  1177. );
  1178. //
  1179. // If this property does not exist in the
  1180. // cache, add this property into the cache.
  1181. //
  1182. if (FAILED(hr)) {
  1183. hr = _pPropertyCache->addproperty(
  1184. bstrName,
  1185. dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ?
  1186. IIS_SYNTAX_ID_DWORD : dwSyntaxId,
  1187. dwNumValues,
  1188. pIISDestObjects
  1189. );
  1190. //
  1191. // If the operation fails for some reason
  1192. // move on to the next property
  1193. //
  1194. BAIL_ON_FAILURE(hr);
  1195. }
  1196. //
  1197. // Now update the property in the cache
  1198. //
  1199. hr = _pPropertyCache->putproperty(
  1200. bstrName,
  1201. CACHE_PROPERTY_MODIFIED,
  1202. dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ?
  1203. IIS_SYNTAX_ID_DWORD : dwSyntaxId,
  1204. dwNumValues,
  1205. pIISDestObjects
  1206. );
  1207. BAIL_ON_FAILURE(hr);
  1208. error:
  1209. if (pIISDestObjects) {
  1210. IISTypeFreeIISObjects(
  1211. pIISDestObjects,
  1212. dwNumValues
  1213. );
  1214. }
  1215. if (bstrClassName) {
  1216. ADsFreeString(bstrClassName);
  1217. }
  1218. if (pVarArray) {
  1219. DWORD i = 0;
  1220. for (i = 0; i < dwNumValues; i++) {
  1221. VariantClear(pVarArray + i);
  1222. }
  1223. FreeADsMem(pVarArray);
  1224. }
  1225. VariantClear(&vVar);
  1226. RRETURN(hr);
  1227. }
  1228. STDMETHODIMP
  1229. CIISGenObject::PutEx(
  1230. THIS_ long lnControlCode,
  1231. BSTR bstrName,
  1232. VARIANT vProp
  1233. )
  1234. {
  1235. HRESULT hr = S_OK;
  1236. DWORD dwSyntaxId = 0;
  1237. DWORD dwIndex = 0;
  1238. LPIISOBJECT pIISDestObjects = NULL;
  1239. DWORD dwNumValues = 0;
  1240. DWORD dwFlags = 0;
  1241. VARIANT * pVarArray = NULL;
  1242. VARIANT * pvProp = NULL;
  1243. VARIANT vVar;
  1244. WCHAR wchName[MAX_PATH];
  1245. BSTR bstrClassName = NULL;
  1246. METADATA_HANDLE hObjHandle = NULL;
  1247. //
  1248. // check if property is a supported property
  1249. //
  1250. hr = get_CoreADsClass(&bstrClassName);
  1251. BAIL_ON_FAILURE(hr);
  1252. hr = _pSchema->ValidateProperty(bstrClassName, bstrName);
  1253. BAIL_ON_FAILURE(hr);
  1254. //
  1255. // lookup its syntax Id
  1256. //
  1257. hr = _pSchema->LookupSyntaxID( bstrName, &dwSyntaxId);
  1258. BAIL_ON_FAILURE(hr);
  1259. switch (lnControlCode) {
  1260. case ADS_PROPERTY_CLEAR:
  1261. dwFlags = CACHE_PROPERTY_CLEARED;
  1262. pIISDestObjects = NULL;
  1263. dwNumValues = 0;
  1264. break;
  1265. case ADS_PROPERTY_UPDATE:
  1266. dwFlags = CACHE_PROPERTY_MODIFIED;
  1267. //
  1268. // Now begin the rest of the processing
  1269. //
  1270. VariantInit(&vVar);
  1271. VariantCopyInd(&vVar, &vProp);
  1272. if ((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar)) {
  1273. hr = ConvertArrayToVariantArray(
  1274. vVar,
  1275. &pVarArray,
  1276. &dwNumValues
  1277. );
  1278. BAIL_ON_FAILURE(hr);
  1279. pvProp = pVarArray;
  1280. }
  1281. else {
  1282. hr = E_FAIL;
  1283. BAIL_ON_FAILURE(hr);
  1284. }
  1285. VariantClear(&vVar);
  1286. //
  1287. // check if the variant maps to the syntax of this property
  1288. //
  1289. hr = VarTypeToIISTypeCopyConstruct(
  1290. dwSyntaxId,
  1291. pvProp,
  1292. dwNumValues,
  1293. &pIISDestObjects,
  1294. TRUE
  1295. );
  1296. BAIL_ON_FAILURE(hr);
  1297. break;
  1298. default:
  1299. RRETURN(hr = E_ADS_BAD_PARAMETER);
  1300. }
  1301. //
  1302. // check if property is BITMASK type;
  1303. // if BITMASK type, get corresponding DWORD flag property
  1304. //
  1305. if (dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
  1306. VARIANT vGetProp;
  1307. DWORD dwMask;
  1308. DWORD dwFlagValue;
  1309. hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
  1310. BAIL_ON_FAILURE(hr);
  1311. if (dwFlags != CACHE_PROPERTY_CLEARED) {
  1312. hr = _pSchema->LookupBitMask(bstrName, &dwMask);
  1313. BAIL_ON_FAILURE(hr);
  1314. //
  1315. // get its corresponding DWORD flag value
  1316. //
  1317. VariantInit(&vGetProp);
  1318. hr = Get(wchName, &vGetProp);
  1319. BAIL_ON_FAILURE(hr);
  1320. dwFlagValue = V_I4(&vGetProp);
  1321. if (pIISDestObjects->IISValue.value_1.dwDWORD) {
  1322. dwFlagValue |= dwMask;
  1323. }
  1324. else {
  1325. dwFlagValue &= ~dwMask;
  1326. }
  1327. pIISDestObjects->IISValue.value_1.dwDWORD = dwFlagValue;
  1328. pIISDestObjects->IISType = IIS_SYNTAX_ID_DWORD;
  1329. }
  1330. bstrName = wchName;
  1331. }
  1332. if (dwSyntaxId == IIS_SYNTAX_ID_BINARY) {
  1333. hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
  1334. BAIL_ON_FAILURE(hr);
  1335. bstrName = wchName;
  1336. }
  1337. //
  1338. // Find this property in the cache
  1339. //
  1340. hr = _pPropertyCache->findproperty(
  1341. bstrName,
  1342. &dwIndex
  1343. );
  1344. //
  1345. // If this property does not exist in the
  1346. // cache, add this property into the cache.
  1347. //
  1348. if (FAILED(hr)) {
  1349. hr = _pPropertyCache->addproperty(
  1350. bstrName,
  1351. dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ?
  1352. IIS_SYNTAX_ID_DWORD : dwSyntaxId,
  1353. dwNumValues,
  1354. pIISDestObjects
  1355. );
  1356. //
  1357. // If the operation fails for some reason
  1358. // move on to the next property
  1359. //
  1360. BAIL_ON_FAILURE(hr);
  1361. }
  1362. //
  1363. // Now update the property in the cache
  1364. //
  1365. hr = _pPropertyCache->putproperty(
  1366. bstrName,
  1367. dwFlags,
  1368. dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ?
  1369. IIS_SYNTAX_ID_DWORD : dwSyntaxId,
  1370. dwNumValues,
  1371. pIISDestObjects
  1372. );
  1373. BAIL_ON_FAILURE(hr);
  1374. if (dwFlags == CACHE_PROPERTY_CLEARED) {
  1375. DWORD dwMetaId;
  1376. hr = _pSchema->LookupMetaID(bstrName, &dwMetaId);
  1377. BAIL_ON_FAILURE(hr);
  1378. hr = OpenAdminBaseKey(
  1379. _pszServerName,
  1380. _pszMetaBasePath,
  1381. METADATA_PERMISSION_WRITE,
  1382. &_pAdminBase,
  1383. &hObjHandle
  1384. );
  1385. BAIL_ON_FAILURE(hr);
  1386. hr = _pAdminBase->DeleteData(
  1387. hObjHandle,
  1388. (LPWSTR)L"",
  1389. dwMetaId,
  1390. ALL_METADATA
  1391. );
  1392. if (hr == MD_ERROR_DATA_NOT_FOUND) {
  1393. hr = S_OK;
  1394. }
  1395. }
  1396. error:
  1397. if (_pAdminBase && hObjHandle) {
  1398. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  1399. }
  1400. if (bstrClassName) {
  1401. ADsFreeString(bstrClassName);
  1402. }
  1403. if (pIISDestObjects) {
  1404. IISTypeFreeIISObjects(
  1405. pIISDestObjects,
  1406. dwNumValues
  1407. );
  1408. }
  1409. if (pVarArray) {
  1410. DWORD i = 0;
  1411. for (i = 0; i < dwNumValues; i++) {
  1412. VariantClear(pVarArray + i);
  1413. }
  1414. FreeADsMem(pVarArray);
  1415. }
  1416. RRETURN(hr);
  1417. }
  1418. /* INTRINSA suppress=null_pointers, uninitialized */
  1419. STDMETHODIMP
  1420. CIISGenObject::GetEx(
  1421. THIS_ BSTR bstrName,
  1422. VARIANT FAR* pvProp
  1423. )
  1424. {
  1425. HRESULT hr = S_OK;
  1426. DWORD dwSyntaxId;
  1427. DWORD dwSyntax;
  1428. DWORD dwNumValues = 0;
  1429. LPIISOBJECT pIISSrcObjects = NULL;
  1430. WCHAR wchName[MAX_PATH];
  1431. BSTR bstrClassName = NULL;
  1432. //
  1433. // check if property is a supported property
  1434. //
  1435. hr = get_CoreADsClass(&bstrClassName);
  1436. BAIL_ON_FAILURE(hr);
  1437. hr = _pSchema->ValidateProperty(bstrClassName, bstrName);
  1438. BAIL_ON_FAILURE(hr);
  1439. //
  1440. // lookup its syntax Id
  1441. //
  1442. hr = _pSchema->LookupSyntaxID(bstrName, &dwSyntax);
  1443. BAIL_ON_FAILURE(hr);
  1444. //
  1445. // check if property is BITMASK type;
  1446. // if BITMASK type, get corresponding DWORD flag property
  1447. //
  1448. // check if property is RAW BINARY type;
  1449. // if RAW BINARY type, get corresponding NTACL flag property
  1450. //
  1451. if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY) {
  1452. hr = _pSchema->LookupFlagPropName(bstrName, (LPWSTR)wchName);
  1453. BAIL_ON_FAILURE(hr);
  1454. }
  1455. //
  1456. // retrieve data object from cache; if one exists
  1457. //
  1458. if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY)
  1459. {
  1460. hr = _pPropertyCache->getproperty(
  1461. wchName,
  1462. &dwSyntaxId,
  1463. &dwNumValues,
  1464. &pIISSrcObjects
  1465. );
  1466. }
  1467. else
  1468. {
  1469. hr = _pPropertyCache->getproperty(
  1470. bstrName,
  1471. &dwSyntaxId,
  1472. &dwNumValues,
  1473. &pIISSrcObjects
  1474. );
  1475. }
  1476. BAIL_ON_FAILURE(hr);
  1477. //
  1478. // reset it to its syntax id if BITMASK type
  1479. //
  1480. pIISSrcObjects->IISType = dwSyntax;
  1481. //
  1482. // translate the IIS objects to variants
  1483. //
  1484. hr = IISTypeToVarTypeCopyConstruct(
  1485. _pSchema,
  1486. bstrName,
  1487. pIISSrcObjects,
  1488. dwNumValues,
  1489. pvProp,
  1490. TRUE
  1491. );
  1492. BAIL_ON_FAILURE(hr);
  1493. error:
  1494. if (bstrClassName) {
  1495. ADsFreeString(bstrClassName);
  1496. }
  1497. if (pIISSrcObjects) {
  1498. IISTypeFreeIISObjects(
  1499. pIISSrcObjects,
  1500. dwNumValues
  1501. );
  1502. }
  1503. RRETURN(hr);
  1504. }
  1505. HRESULT
  1506. CIISGenObject::CacheMetaDataPath()
  1507. {
  1508. HRESULT hr = E_FAIL;
  1509. OBJECTINFO ObjectInfo;
  1510. POBJECTINFO pObjectInfo = &ObjectInfo;
  1511. CLexer Lexer(_ADsPath);
  1512. LPWSTR pszIISPathName = NULL;
  1513. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  1514. hr = ADsObject(&Lexer, pObjectInfo);
  1515. BAIL_ON_FAILURE(hr);
  1516. _pszServerName = AllocADsStr(pObjectInfo->TreeName);
  1517. if (!_pszServerName) {
  1518. hr = E_OUTOFMEMORY;
  1519. BAIL_ON_FAILURE(hr);
  1520. }
  1521. hr = InitServerInfo(_pszServerName, &_pAdminBase, &_pSchema);
  1522. BAIL_ON_FAILURE(hr);
  1523. pszIISPathName = AllocADsStr(_ADsPath);
  1524. if (!pszIISPathName) {
  1525. hr = E_OUTOFMEMORY;
  1526. BAIL_ON_FAILURE(hr);
  1527. }
  1528. *pszIISPathName = L'\0';
  1529. hr = BuildIISPathFromADsPath(
  1530. pObjectInfo,
  1531. pszIISPathName
  1532. );
  1533. BAIL_ON_FAILURE(hr);
  1534. _pszMetaBasePath = AllocADsStr(pszIISPathName);
  1535. if (!_pszMetaBasePath) {
  1536. hr = E_OUTOFMEMORY;
  1537. BAIL_ON_FAILURE(hr);
  1538. }
  1539. error:
  1540. if (pszIISPathName) {
  1541. FreeADsStr(pszIISPathName);
  1542. }
  1543. FreeObjectInfo(pObjectInfo);
  1544. RRETURN(hr);
  1545. }
  1546. STDMETHODIMP
  1547. CIISGenObject::GetDataPaths(
  1548. THIS_ BSTR bstrName,
  1549. THIS_ LONG lnAttribute,
  1550. VARIANT FAR* pvProp
  1551. )
  1552. {
  1553. HRESULT hr = S_OK;
  1554. DWORD dwMetaId;
  1555. DWORD dwAttribute;
  1556. DWORD dwTemp;
  1557. METADATA_HANDLE hObjHandle = NULL;
  1558. LPBYTE pBuffer = NULL;
  1559. //
  1560. // check if property is a supported property
  1561. //
  1562. hr = _pSchema->LookupMetaID(bstrName, &dwMetaId);
  1563. BAIL_ON_FAILURE(hr);
  1564. hr = _pSchema->LookupMDFlags(dwMetaId, &dwAttribute, &dwTemp);
  1565. BAIL_ON_FAILURE(hr);
  1566. switch (lnAttribute) {
  1567. case IIS_ANY_PROPERTY:
  1568. break;
  1569. case IIS_INHERITABLE_ONLY:
  1570. if ((METADATA_INHERIT & dwAttribute) != METADATA_INHERIT) {
  1571. RRETURN(hr = MD_ERROR_DATA_NOT_FOUND);
  1572. }
  1573. break;
  1574. default :
  1575. RRETURN(hr = E_ADS_BAD_PARAMETER);
  1576. }
  1577. //
  1578. // Get Server and Path name
  1579. //
  1580. hr = CacheMetaDataPath();
  1581. BAIL_ON_FAILURE(hr);
  1582. hr = OpenAdminBaseKey(
  1583. _pszServerName,
  1584. _pszMetaBasePath,
  1585. METADATA_PERMISSION_READ,
  1586. &_pAdminBase,
  1587. &hObjHandle
  1588. );
  1589. BAIL_ON_FAILURE(hr);
  1590. hr = MetaBaseGetDataPaths(_pAdminBase,
  1591. hObjHandle,
  1592. dwMetaId,
  1593. (LPBYTE *)&pBuffer
  1594. );
  1595. BAIL_ON_FAILURE(hr);
  1596. hr = MakeVariantFromPathArray( (LPWSTR)_ADsPath, (LPWSTR)pBuffer, pvProp);
  1597. BAIL_ON_FAILURE(hr);
  1598. error:
  1599. if (pBuffer) {
  1600. FreeADsMem(pBuffer);
  1601. }
  1602. if (_pAdminBase && hObjHandle) {
  1603. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  1604. }
  1605. RRETURN(hr);
  1606. }
  1607. STDMETHODIMP
  1608. CIISGenObject::GetPropertyAttribObj(
  1609. THIS_ BSTR bstrName,
  1610. IDispatch * FAR* ppObject
  1611. )
  1612. {
  1613. HRESULT hr = S_OK;
  1614. DWORD dwMetaId;
  1615. DWORD i = 0;
  1616. PROPERTYINFO *pPropertyInfo = NULL;
  1617. IISPropertyAttribute * pPropAttrib = NULL;
  1618. WCHAR wchName[MAX_PATH];
  1619. METADATA_HANDLE hObjHandle = NULL;
  1620. DWORD dwBufferSize = 0;
  1621. METADATA_RECORD mdrMDData;
  1622. LPBYTE pBuffer = NULL;
  1623. VARIANT vVar;
  1624. VariantInit(&vVar);
  1625. *ppObject = NULL;
  1626. //
  1627. // if passed in bstrName is a meta id, then convert it to property name
  1628. //
  1629. if (wcslen(bstrName) >= MAX_PATH) bstrName[MAX_PATH - 1] = L'\0';
  1630. wcscpy((LPWSTR)wchName, bstrName);
  1631. while (wchName[i] != L'\0' && wchName[i] >= L'0' &&
  1632. wchName[i] <= L'9') {
  1633. i++;
  1634. }
  1635. if (i == wcslen((LPWSTR)wchName)) {
  1636. dwMetaId = _wtoi((LPWSTR)wchName);
  1637. hr = _pSchema->ConvertID_To_PropName(dwMetaId, (LPWSTR)wchName);
  1638. BAIL_ON_FAILURE(hr);
  1639. }
  1640. else {
  1641. //
  1642. // check if property is a supported property
  1643. //
  1644. hr = _pSchema->LookupMetaID(bstrName, &dwMetaId);
  1645. BAIL_ON_FAILURE(hr);
  1646. }
  1647. hr = OpenAdminBaseKey(
  1648. _pszServerName,
  1649. _pszMetaBasePath,
  1650. METADATA_PERMISSION_READ,
  1651. &_pAdminBase,
  1652. &hObjHandle
  1653. );
  1654. BAIL_ON_FAILURE(hr);
  1655. MD_SET_DATA_RECORD(&mdrMDData,
  1656. dwMetaId,
  1657. METADATA_INHERIT | METADATA_ISINHERITED,
  1658. ALL_METADATA,
  1659. ALL_METADATA,
  1660. dwBufferSize,
  1661. pBuffer);
  1662. hr = _pAdminBase->GetData(
  1663. hObjHandle,
  1664. L"",
  1665. &mdrMDData,
  1666. &dwBufferSize
  1667. );
  1668. pBuffer = (LPBYTE) AllocADsMem(dwBufferSize);
  1669. mdrMDData.pbMDData = pBuffer;
  1670. mdrMDData.dwMDDataLen = dwBufferSize;
  1671. hr = _pAdminBase->GetData(
  1672. hObjHandle,
  1673. L"",
  1674. &mdrMDData,
  1675. &dwBufferSize
  1676. );
  1677. BAIL_ON_FAILURE(hr);
  1678. //
  1679. // get default value
  1680. //
  1681. pPropertyInfo = _pSchema->GetPropertyInfo(wchName);
  1682. ASSERT(pPropertyInfo != NULL);
  1683. if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_DWORD ||
  1684. pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_MIMEMAP ||
  1685. pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_IPSECLIST ||
  1686. pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BINARY ||
  1687. pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_NTACL) {
  1688. vVar.vt = VT_I4;
  1689. vVar.lVal = pPropertyInfo->dwDefault;
  1690. }
  1691. else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL ||
  1692. pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
  1693. vVar.vt = VT_BOOL;
  1694. vVar.boolVal = pPropertyInfo->dwDefault ? VARIANT_TRUE : VARIANT_FALSE;
  1695. }
  1696. else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_MULTISZ) {
  1697. LPWSTR pszStr = pPropertyInfo->szDefault;
  1698. hr = MakeVariantFromStringArray(NULL,
  1699. pszStr,
  1700. &vVar);
  1701. BAIL_ON_FAILURE(hr);
  1702. }
  1703. else {
  1704. vVar.vt = VT_BSTR;
  1705. hr = ADsAllocString( pPropertyInfo->szDefault, &(vVar.bstrVal));
  1706. BAIL_ON_FAILURE(hr);
  1707. }
  1708. hr = CPropertyAttribute::CreatePropertyAttribute(
  1709. IID_IISPropertyAttribute,
  1710. (VOID**)&pPropAttrib
  1711. );
  1712. BAIL_ON_FAILURE(hr);
  1713. hr = ((CPropertyAttribute*)pPropAttrib)->InitFromRawData(
  1714. (LPWSTR) wchName,
  1715. dwMetaId,
  1716. mdrMDData.dwMDUserType, // usertype
  1717. mdrMDData.dwMDAttributes, // attributes
  1718. &vVar
  1719. );
  1720. BAIL_ON_FAILURE(hr);
  1721. *ppObject = (IDispatch*)pPropAttrib;
  1722. error:
  1723. if (pBuffer) {
  1724. FreeADsMem(pBuffer);
  1725. }
  1726. if (hObjHandle) {
  1727. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  1728. }
  1729. RRETURN(hr);
  1730. }
  1731. HRESULT
  1732. CIISGenObject::ResolveExtendedChildPath(
  1733. IN BSTR RelativeChildPath,
  1734. OUT BSTR *pParentPath,
  1735. OUT BSTR *pParentClass
  1736. )
  1737. /*++
  1738. Routine Description:
  1739. Helper method called from CIISGenObject::Create() finds the
  1740. metabase key that is most proximate to RelativeChildPath and
  1741. returns the ADS class for this key along with adjusted path
  1742. for the parent.
  1743. Arguments:
  1744. IN RelativeChildPath : An extended subpath, such as foo/bar
  1745. OUT pParentPath : Allocated with ADsAllocString
  1746. OUT pParentClass : Allocated with ADsAllocString
  1747. Return Value:
  1748. S_OK
  1749. S_FALSE : No path found in the metabase
  1750. --*/
  1751. {
  1752. ADsAssert( RelativeChildPath );
  1753. ADsAssert( pParentPath );
  1754. ADsAssert( pParentClass );
  1755. *pParentPath = NULL;
  1756. *pParentClass = NULL;
  1757. HRESULT hr = S_OK;
  1758. DWORD cbBuffSize;
  1759. LPWSTR pwszPathBuffer = NULL;
  1760. DWORD dwLen;
  1761. BOOL bFound;
  1762. WCHAR *pch = NULL;
  1763. WCHAR wszParentClassBuffer[MAX_PATH];
  1764. //
  1765. // Build buffer to hold the metabase and ads paths
  1766. //
  1767. cbBuffSize = (wcslen(_ADsPath) + wcslen(RelativeChildPath) + 2)
  1768. * sizeof(WCHAR);
  1769. pwszPathBuffer = (LPWSTR)AllocADsMem( cbBuffSize );
  1770. if( !pwszPathBuffer )
  1771. {
  1772. hr = E_OUTOFMEMORY;
  1773. BAIL_ON_FAILURE(hr);
  1774. }
  1775. ZeroMemory( pwszPathBuffer, cbBuffSize );
  1776. //
  1777. // Build the metabase path for the child
  1778. //
  1779. wcscpy( pwszPathBuffer, _pszMetaBasePath );
  1780. dwLen = wcslen( pwszPathBuffer );
  1781. ADsAssert( dwLen );
  1782. if( pwszPathBuffer[dwLen - 1] != L'/' )
  1783. {
  1784. pwszPathBuffer[dwLen] = L'/';
  1785. }
  1786. wcscat( pwszPathBuffer, RelativeChildPath );
  1787. //
  1788. // Look for the closest path in the metabase to our child
  1789. //
  1790. bFound = FALSE;
  1791. pch = wcsrchr( pwszPathBuffer, L'/' );
  1792. if (pch != NULL)
  1793. *pch = 0;
  1794. while( !bFound && 0 != wcscmp( pwszPathBuffer, _pszMetaBasePath ) )
  1795. {
  1796. hr = MetaBaseDetectKey( _pAdminBase, pwszPathBuffer );
  1797. if( SUCCEEDED(hr) )
  1798. {
  1799. bFound = TRUE;
  1800. }
  1801. else if( ERROR_PATH_NOT_FOUND == HRESULT_CODE(hr) )
  1802. {
  1803. // Continue up the path buffer
  1804. pch = wcsrchr( pwszPathBuffer, L'/' );
  1805. if (pch != NULL)
  1806. *pch = 0;
  1807. hr = S_FALSE;
  1808. }
  1809. else
  1810. {
  1811. BAIL_ON_FAILURE( hr );
  1812. }
  1813. }
  1814. //
  1815. // Get pParentClass
  1816. //
  1817. if( bFound )
  1818. {
  1819. // Get the key type from the node
  1820. hr = MetaBaseGetADsClass( _pAdminBase,
  1821. pwszPathBuffer,
  1822. _pSchema,
  1823. wszParentClassBuffer,
  1824. MAX_PATH
  1825. );
  1826. BAIL_ON_FAILURE( hr );
  1827. }
  1828. else
  1829. {
  1830. // Use our own key type
  1831. wcscpy( wszParentClassBuffer, _ADsClass );
  1832. }
  1833. hr = ADsAllocString( wszParentClassBuffer, pParentClass );
  1834. BAIL_ON_FAILURE( hr );
  1835. //
  1836. // Get pParentPath
  1837. //
  1838. wcscpy( pwszPathBuffer, _ADsPath );
  1839. wcscat( pwszPathBuffer, L"/" );
  1840. wcscat( pwszPathBuffer, RelativeChildPath );
  1841. pch = wcsrchr( pwszPathBuffer, L'/' );
  1842. if (pch != NULL)
  1843. *pch = 0;
  1844. hr = ADsAllocString( pwszPathBuffer, pParentPath );
  1845. BAIL_ON_FAILURE( hr );
  1846. error:
  1847. if( pwszPathBuffer )
  1848. {
  1849. FreeADsMem( pwszPathBuffer );
  1850. }
  1851. RRETURN( hr );
  1852. }