Leaked source code of windows server 2003
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.

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