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.

730 lines
16 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: cschobj.cxx
  7. //
  8. // Contents: Microsoft ADs IIS Provider Schema Object
  9. //
  10. //
  11. // History: 01-30-98 sophiac Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "iis.hxx"
  15. #pragma hdrstop
  16. // Class CIISSchema
  17. DEFINE_IDispatch_Implementation(CIISSchema)
  18. DEFINE_IADs_Implementation(CIISSchema)
  19. CIISSchema::CIISSchema() :
  20. _pSchema(NULL),
  21. _pDispMgr(NULL),
  22. _pszServerName(NULL),
  23. _pAdminBase(NULL)
  24. {
  25. ENLIST_TRACKING(CIISSchema);
  26. }
  27. HRESULT
  28. CIISSchema::CreateSchema(
  29. LPWSTR pszServerName,
  30. BSTR Parent,
  31. BSTR CommonName,
  32. DWORD dwObjectState,
  33. REFIID riid,
  34. void **ppvObj
  35. )
  36. {
  37. CIISSchema FAR * pSchema = NULL;
  38. HRESULT hr = S_OK;
  39. hr = AllocateSchemaObject(&pSchema);
  40. BAIL_ON_FAILURE(hr);
  41. hr = InitServerInfo(pszServerName,
  42. &pSchema->_pAdminBase,
  43. &pSchema->_pSchema);
  44. BAIL_ON_FAILURE(hr);
  45. pSchema->_pszServerName = AllocADsStr(pszServerName);
  46. if (!pSchema->_pszServerName) {
  47. hr = E_OUTOFMEMORY;
  48. BAIL_ON_FAILURE(hr);
  49. }
  50. hr = pSchema->InitializeCoreObject(
  51. Parent,
  52. CommonName,
  53. SCHEMA_CLASS_NAME,
  54. L"",
  55. CLSID_IISSchema,
  56. dwObjectState
  57. );
  58. BAIL_ON_FAILURE(hr);
  59. hr = pSchema->QueryInterface(riid, ppvObj);
  60. BAIL_ON_FAILURE(hr);
  61. pSchema->Release();
  62. RRETURN(hr);
  63. error:
  64. delete pSchema;
  65. RRETURN(hr);
  66. }
  67. CIISSchema::~CIISSchema( )
  68. {
  69. delete _pDispMgr;
  70. if (_pszServerName) {
  71. FreeADsStr(_pszServerName);
  72. }
  73. }
  74. STDMETHODIMP
  75. CIISSchema::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  76. {
  77. if (IsEqualIID(iid, IID_IUnknown))
  78. {
  79. *ppv = (IADs FAR *) this;
  80. }
  81. else if (IsEqualIID(iid, IID_IADsContainer))
  82. {
  83. *ppv = (IADsContainer FAR *) this;
  84. }
  85. else if (IsEqualIID(iid, IID_IADs))
  86. {
  87. *ppv = (IADs FAR *) this;
  88. }
  89. else if (IsEqualIID(iid, IID_IISSchemaObject))
  90. {
  91. *ppv = (IISSchemaObject FAR *) this;
  92. }
  93. else if (IsEqualIID(iid, IID_IDispatch))
  94. {
  95. *ppv = (IADs FAR *) this;
  96. }
  97. else
  98. {
  99. *ppv = NULL;
  100. return E_NOINTERFACE;
  101. }
  102. AddRef();
  103. return NOERROR;
  104. }
  105. STDMETHODIMP
  106. CIISSchema::SetInfo(THIS)
  107. {
  108. RRETURN(E_NOTIMPL);
  109. }
  110. STDMETHODIMP
  111. CIISSchema::GetInfo(THIS)
  112. {
  113. RRETURN(E_NOTIMPL);
  114. }
  115. /* IADsContainer methods */
  116. STDMETHODIMP
  117. CIISSchema::get_Count(long FAR* retval)
  118. {
  119. HRESULT hr;
  120. DWORD dwEntries;
  121. if ( !retval )
  122. RRETURN(E_ADS_BAD_PARAMETER);
  123. hr = _pSchema->GetTotalEntries(&dwEntries);
  124. if ( SUCCEEDED(hr))
  125. *retval = dwEntries + g_cIISSyntax;
  126. RRETURN(hr);
  127. }
  128. STDMETHODIMP
  129. CIISSchema::get_Filter(THIS_ VARIANT FAR* pVar)
  130. {
  131. RRETURN(E_NOTIMPL);
  132. }
  133. STDMETHODIMP
  134. CIISSchema::put_Filter(THIS_ VARIANT Var)
  135. {
  136. RRETURN(E_NOTIMPL);
  137. }
  138. STDMETHODIMP
  139. CIISSchema::put_Hints(THIS_ VARIANT Var)
  140. {
  141. RRETURN( E_NOTIMPL);
  142. }
  143. STDMETHODIMP
  144. CIISSchema::get_Hints(THIS_ VARIANT FAR* pVar)
  145. {
  146. RRETURN(E_NOTIMPL);
  147. }
  148. STDMETHODIMP
  149. CIISSchema::GetObject(
  150. THIS_ BSTR ClassName,
  151. BSTR RelativeName,
  152. IDispatch * FAR* ppObject
  153. )
  154. {
  155. LPWSTR pszBuffer = NULL;
  156. HRESULT hr = S_OK;
  157. DWORD dwLen;
  158. CCredentials Credentials;
  159. *ppObject = NULL;
  160. if (!RelativeName || !*RelativeName) {
  161. RRETURN(E_ADS_UNKNOWN_OBJECT);
  162. }
  163. dwLen = wcslen(_ADsPath) + wcslen(RelativeName) + wcslen(ClassName) + 4;
  164. pszBuffer = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
  165. if (!pszBuffer) {
  166. hr = E_OUTOFMEMORY;
  167. BAIL_ON_FAILURE(hr);
  168. }
  169. wcscpy(pszBuffer, _ADsPath);
  170. wcscat(pszBuffer, L"/");
  171. wcscat(pszBuffer, RelativeName);
  172. if (ClassName && *ClassName) {
  173. wcscat(pszBuffer,L",");
  174. wcscat(pszBuffer, ClassName);
  175. }
  176. hr = ::GetObject(
  177. pszBuffer,
  178. Credentials,
  179. (LPVOID *)ppObject
  180. );
  181. BAIL_ON_FAILURE(hr);
  182. error:
  183. if (pszBuffer) {
  184. FreeADsMem(pszBuffer);
  185. }
  186. RRETURN(hr);
  187. }
  188. STDMETHODIMP
  189. CIISSchema::get__NewEnum(
  190. THIS_ IUnknown * FAR* retval
  191. )
  192. {
  193. HRESULT hr;
  194. IUnknown FAR* punkEnum=NULL;
  195. IEnumVARIANT * penum = NULL;
  196. if ( !retval )
  197. RRETURN(E_ADS_BAD_PARAMETER);
  198. *retval = NULL;
  199. hr = CIISSchemaEnum::Create(
  200. (CIISSchemaEnum **)&penum,
  201. _pSchema,
  202. _ADsPath,
  203. _Name
  204. );
  205. BAIL_ON_FAILURE(hr);
  206. hr = penum->QueryInterface(
  207. IID_IUnknown,
  208. (VOID FAR* FAR*)retval
  209. );
  210. BAIL_ON_FAILURE(hr);
  211. if (penum) {
  212. penum->Release();
  213. }
  214. RRETURN(NOERROR);
  215. error:
  216. if (penum) {
  217. delete penum;
  218. }
  219. RRETURN(hr);
  220. }
  221. STDMETHODIMP
  222. CIISSchema::Create(
  223. THIS_ BSTR ClassName,
  224. BSTR RelativeName,
  225. IDispatch * FAR* ppObject
  226. )
  227. {
  228. HRESULT hr = S_OK;
  229. DWORD i = 1;
  230. //
  231. // We can only create "Class","Property" here, "Syntax" is read-only
  232. //
  233. //
  234. // check if property/class already exists
  235. //
  236. if (_pSchema->ValidateClassName(RelativeName) == ERROR_SUCCESS ||
  237. _pSchema->ValidatePropertyName(RelativeName) == ERROR_SUCCESS ) {
  238. hr = E_ADS_OBJECT_EXISTS;
  239. BAIL_ON_FAILURE(hr);
  240. }
  241. //
  242. // validate name -->
  243. // must start w/ a-z, A-Z, or underscore
  244. // must only contain a-z, A-Z, 0-9, or underscore
  245. //
  246. // check first character
  247. if ( // if first char is
  248. (RelativeName[0] < 65 || RelativeName[0] > 90) && // not uppercase letter and
  249. (RelativeName[0] < 97 || RelativeName[0] > 122) && // not lowercase letter and
  250. RelativeName[0] != 95 // not underscore
  251. ) // then bail
  252. {
  253. hr = E_ADS_BAD_PARAMETER;
  254. BAIL_ON_FAILURE(hr);
  255. }
  256. while ( // while characters are
  257. (RelativeName[i] >= 65 && RelativeName[i] <= 90) || // uppercase letters or
  258. (RelativeName[i] >= 97 && RelativeName[i] <= 122) || // lowercase letters or
  259. (RelativeName[i] >= 48 && RelativeName[i] <= 57) || // digits or
  260. RelativeName[i] == 95 // underscores
  261. ) // then things are okay
  262. i++;
  263. if (RelativeName[i] != L'\0' || i >= METADATA_MAX_NAME_LEN) {
  264. hr = E_ADS_BAD_PARAMETER;
  265. BAIL_ON_FAILURE(hr);
  266. }
  267. if ( ( _wcsicmp( ClassName, CLASS_CLASS_NAME ) == 0 ) )
  268. {
  269. //
  270. // Now, create the class
  271. //
  272. hr = CIISClass::CreateClass(
  273. _ADsPath,
  274. RelativeName,
  275. ADS_OBJECT_UNBOUND,
  276. IID_IUnknown,
  277. (void **) ppObject );
  278. }
  279. else if ( ( _wcsicmp( ClassName, PROPERTY_CLASS_NAME ) == 0 ) )
  280. {
  281. hr = CIISProperty::CreateProperty(
  282. _ADsPath,
  283. RelativeName,
  284. ADS_OBJECT_UNBOUND,
  285. IID_IUnknown,
  286. (void **) ppObject );
  287. }
  288. else
  289. {
  290. hr = E_ADS_BAD_PARAMETER;
  291. }
  292. error:
  293. RRETURN(hr);
  294. }
  295. STDMETHODIMP
  296. CIISSchema::Delete(
  297. THIS_ BSTR bstrClassName,
  298. BSTR bstrRelativeName
  299. )
  300. {
  301. HRESULT hr;
  302. BOOL bClass;
  303. METADATA_HANDLE hObjHandle = NULL;
  304. if ( ( _wcsicmp( bstrClassName, CLASS_CLASS_NAME ) == 0 ) )
  305. {
  306. hr = _pSchema->ValidateClassName(bstrRelativeName);
  307. BAIL_ON_FAILURE(hr);
  308. bClass = TRUE;
  309. //
  310. // remove entry from metabase
  311. //
  312. hr = OpenAdminBaseKey(
  313. _pszServerName,
  314. SCHEMA_CLASS_METABASE_PATH,
  315. METADATA_PERMISSION_WRITE,
  316. &_pAdminBase,
  317. &hObjHandle
  318. );
  319. BAIL_ON_FAILURE(hr);
  320. hr = MetaBaseDeleteObject(
  321. _pAdminBase,
  322. hObjHandle,
  323. (LPWSTR)bstrRelativeName
  324. );
  325. if (hr == MD_ERROR_DATA_NOT_FOUND) {
  326. hr = S_OK;
  327. }
  328. BAIL_ON_FAILURE(hr);
  329. }
  330. else if ( ( _wcsicmp( bstrClassName, PROPERTY_CLASS_NAME ) == 0 ) )
  331. {
  332. DWORD dwMetaId;
  333. hr = _pSchema->ValidatePropertyName(bstrRelativeName);
  334. BAIL_ON_FAILURE(hr);
  335. bClass = FALSE;
  336. //
  337. // Lookup metaid
  338. //
  339. hr = _pSchema->LookupMetaID(bstrRelativeName, &dwMetaId);
  340. BAIL_ON_FAILURE(hr);
  341. //
  342. // remove entry from metabase
  343. //
  344. hr = OpenAdminBaseKey(
  345. _pszServerName,
  346. SCHEMA_PROP_METABASE_PATH,
  347. METADATA_PERMISSION_WRITE,
  348. &_pAdminBase,
  349. &hObjHandle
  350. );
  351. BAIL_ON_FAILURE(hr);
  352. hr = _pAdminBase->DeleteData(
  353. hObjHandle,
  354. (LPWSTR)L"Names",
  355. dwMetaId,
  356. ALL_METADATA
  357. );
  358. if (hr == MD_ERROR_DATA_NOT_FOUND) {
  359. hr = S_OK;
  360. }
  361. BAIL_ON_FAILURE(hr);
  362. hr = _pAdminBase->DeleteData(
  363. hObjHandle,
  364. (LPWSTR)L"Types",
  365. dwMetaId,
  366. ALL_METADATA
  367. );
  368. if (hr == MD_ERROR_DATA_NOT_FOUND) {
  369. hr = S_OK;
  370. }
  371. BAIL_ON_FAILURE(hr);
  372. hr = _pAdminBase->DeleteData(
  373. hObjHandle,
  374. (LPWSTR)L"Defaults",
  375. dwMetaId,
  376. ALL_METADATA
  377. );
  378. if (hr == MD_ERROR_DATA_NOT_FOUND) {
  379. hr = S_OK;
  380. }
  381. BAIL_ON_FAILURE(hr);
  382. }
  383. else
  384. {
  385. hr = E_ADS_BAD_PARAMETER;
  386. BAIL_ON_FAILURE(hr);
  387. }
  388. //
  389. // remove entry from schema cache
  390. //
  391. hr = _pSchema->RemoveEntry(bClass, bstrRelativeName);
  392. error:
  393. if (_pAdminBase && hObjHandle) {
  394. CloseAdminBaseKey(_pAdminBase, hObjHandle);
  395. }
  396. RRETURN(hr);
  397. }
  398. STDMETHODIMP
  399. CIISSchema::CopyHere(
  400. THIS_ BSTR SourceName,
  401. BSTR NewName,
  402. IDispatch * FAR* ppObject
  403. )
  404. {
  405. RRETURN(E_NOTIMPL);
  406. }
  407. STDMETHODIMP
  408. CIISSchema::MoveHere(
  409. THIS_ BSTR SourceName,
  410. BSTR NewName,
  411. IDispatch * FAR* ppObject
  412. )
  413. {
  414. RRETURN(E_NOTIMPL);
  415. }
  416. HRESULT
  417. CIISSchema::AllocateSchemaObject(
  418. CIISSchema ** ppSchema
  419. )
  420. {
  421. CIISSchema FAR * pSchema = NULL;
  422. CAggregatorDispMgr FAR * pDispMgr = NULL;
  423. HRESULT hr = S_OK;
  424. pSchema = new CIISSchema();
  425. if (pSchema == NULL) {
  426. hr = E_OUTOFMEMORY;
  427. }
  428. BAIL_ON_FAILURE(hr);
  429. pDispMgr = new CAggregatorDispMgr;
  430. if (pDispMgr == NULL) {
  431. hr = E_OUTOFMEMORY;
  432. }
  433. BAIL_ON_FAILURE(hr);
  434. hr = pDispMgr->LoadTypeInfoEntry(
  435. LIBID_ADs,
  436. IID_IADs,
  437. (IADs *)pSchema,
  438. DISPID_REGULAR
  439. );
  440. BAIL_ON_FAILURE(hr);
  441. hr = pDispMgr->LoadTypeInfoEntry(
  442. LIBID_ADs,
  443. IID_IADsContainer,
  444. (IADsContainer *)pSchema,
  445. DISPID_NEWENUM
  446. );
  447. BAIL_ON_FAILURE(hr);
  448. hr = pDispMgr->LoadTypeInfoEntry(
  449. LIBID_IISOle,
  450. IID_IISSchemaObject,
  451. (IISSchemaObject *)pSchema,
  452. DISPID_REGULAR
  453. );
  454. BAIL_ON_FAILURE(hr);
  455. pSchema->_pDispMgr = pDispMgr;
  456. *ppSchema = pSchema;
  457. RRETURN(hr);
  458. error:
  459. delete pDispMgr;
  460. delete pSchema;
  461. RRETURN(hr);
  462. }
  463. STDMETHODIMP
  464. CIISSchema::GetInfo(
  465. THIS_ DWORD dwApiLevel,
  466. BOOL fExplicit
  467. )
  468. {
  469. RRETURN(E_NOTIMPL);
  470. }
  471. STDMETHODIMP
  472. CIISSchema::Get(
  473. THIS_ BSTR bstrName,
  474. VARIANT FAR* pvProp
  475. )
  476. {
  477. RRETURN(E_NOTIMPL);
  478. }
  479. STDMETHODIMP
  480. CIISSchema::Put(
  481. THIS_ BSTR bstrName,
  482. VARIANT vProp
  483. )
  484. {
  485. RRETURN(E_NOTIMPL);
  486. }
  487. STDMETHODIMP
  488. CIISSchema::GetEx(
  489. THIS_ BSTR bstrName,
  490. VARIANT FAR* pvProp
  491. )
  492. {
  493. RRETURN(E_NOTIMPL);
  494. }
  495. STDMETHODIMP
  496. CIISSchema::PutEx(
  497. THIS_ long lnControlCode,
  498. BSTR bstrName,
  499. VARIANT vProp
  500. )
  501. {
  502. RRETURN(E_NOTIMPL);
  503. }
  504. STDMETHODIMP
  505. CIISSchema::GetSchemaPropertyAttributes(
  506. THIS_ BSTR bstrName,
  507. IDispatch * FAR* ppObject
  508. )
  509. {
  510. HRESULT hr = S_OK;
  511. DWORD dwMetaId;
  512. PROPERTYINFO *pPropertyInfo = NULL;
  513. DWORD i = 0;
  514. IISPropertyAttribute * pPropAttrib = NULL;
  515. WCHAR wchName[MAX_PATH];
  516. VARIANT vVar;
  517. VariantInit(&vVar);
  518. *ppObject = NULL;
  519. //
  520. // if passed in bstrName is a meta id, then convert it to property name
  521. //
  522. if (wcslen(bstrName) >= MAX_PATH) bstrName[MAX_PATH - 1] = L'\0';
  523. wcscpy((LPWSTR)wchName, bstrName);
  524. while (wchName[i] != L'\0' && wchName[i] >= L'0' &&
  525. wchName[i] <= L'9') {
  526. i++;
  527. }
  528. if (i == wcslen((LPWSTR)wchName)) {
  529. dwMetaId = _wtoi((LPWSTR)wchName);
  530. hr = _pSchema->ConvertID_To_PropName(dwMetaId, (LPWSTR)wchName);
  531. BAIL_ON_FAILURE(hr);
  532. }
  533. else {
  534. //
  535. // check if property is a supported property
  536. //
  537. hr = _pSchema->LookupMetaID(wchName, &dwMetaId);
  538. BAIL_ON_FAILURE(hr);
  539. }
  540. //
  541. // get property attribute value
  542. //
  543. pPropertyInfo = _pSchema->GetPropertyInfo(wchName);
  544. ASSERT(pPropertyInfo != NULL);
  545. if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_DWORD ||
  546. pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_IPSECLIST ||
  547. pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_NTACL ||
  548. pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BINARY ) {
  549. vVar.vt = VT_I4;
  550. vVar.lVal = pPropertyInfo->dwDefault;
  551. }
  552. else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL ||
  553. pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
  554. vVar.vt = VT_BOOL;
  555. vVar.boolVal = pPropertyInfo->dwDefault ? VARIANT_TRUE : VARIANT_FALSE;
  556. }
  557. else if (pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_MULTISZ ||
  558. pPropertyInfo->dwSyntaxId == IIS_SYNTAX_ID_MIMEMAP ) {
  559. LPWSTR pszStr = pPropertyInfo->szDefault;
  560. hr = MakeVariantFromStringArray(NULL,
  561. pszStr,
  562. &vVar);
  563. BAIL_ON_FAILURE(hr);
  564. }
  565. else {
  566. vVar.vt = VT_BSTR;
  567. hr = ADsAllocString( pPropertyInfo->szDefault, &(vVar.bstrVal));
  568. BAIL_ON_FAILURE(hr);
  569. }
  570. hr = CPropertyAttribute::CreatePropertyAttribute(
  571. IID_IISPropertyAttribute,
  572. (VOID**)&pPropAttrib
  573. );
  574. BAIL_ON_FAILURE(hr);
  575. hr = ((CPropertyAttribute*)pPropAttrib)->InitFromRawData(
  576. (LPWSTR) wchName,
  577. dwMetaId,
  578. pPropertyInfo->dwUserGroup,
  579. pPropertyInfo->dwMetaFlags,
  580. &vVar
  581. );
  582. BAIL_ON_FAILURE(hr);
  583. *ppObject = (IDispatch*)pPropAttrib;
  584. error:
  585. VariantClear(&vVar);
  586. RRETURN(hr);
  587. }
  588. STDMETHODIMP
  589. CIISSchema::PutSchemaPropertyAttributes(
  590. THIS_ IDispatch * pObject
  591. )
  592. {
  593. RRETURN(E_NOTIMPL);
  594. }