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.

1341 lines
32 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997
  5. //
  6. // File: schemini.cxx
  7. //
  8. // Contents: Loading Schema/Property from metabase code
  9. //
  10. // History: 28-Apr-97 Markand Created.
  11. // History: 18-Aug-98 sophiac Extensible schema
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "iis.hxx"
  15. #define INITGUID
  16. #pragma hdrstop
  17. #include "mddef.h"
  18. #include <tchar.h>
  19. #define DEFAULT_TIMEOUT_VALUE 30000
  20. StrMap::StrMap() {
  21. count = 0;
  22. mapSize = 64;
  23. map = (StrMapEntry *)malloc(sizeof(StrMapEntry) * mapSize);
  24. }
  25. StrMap::~StrMap() {
  26. free(map);
  27. }
  28. DWORD StrMap::GetEntries() {
  29. return count;
  30. }
  31. LPWSTR StrMap::GetEntryName(DWORD dwIndex) {
  32. return map[dwIndex].m_str;
  33. }
  34. BOOL StrMap::CheckSpace() {
  35. if (count < mapSize)
  36. return TRUE;
  37. mapSize += 32;
  38. if ((map = (StrMapEntry *)realloc(map, sizeof(StrMapEntry)*mapSize)) == NULL)
  39. return FALSE;
  40. return TRUE;
  41. }
  42. BOOL StrMap::Add(LPWSTR str, void *data) {
  43. if (!CheckSpace())
  44. return FALSE;
  45. map[count].m_str = str;
  46. map[count].m_data = data;
  47. count++;
  48. return TRUE;
  49. }
  50. BOOL StrMap::ClearEntry(DWORD dwIndex) {
  51. count--;
  52. void* prop = map[count].m_data;
  53. // replace object to be deleted by last object in list and decrement count
  54. map[dwIndex].m_str = map[count].m_str;
  55. map[dwIndex].m_data = map[count].m_data;
  56. map[count].m_str = NULL;
  57. map[count].m_data = NULL;
  58. if (prop)
  59. delete prop;
  60. return TRUE;
  61. }
  62. void *StrMap::Find(LPWSTR str) {
  63. for (int i=0; i < count; i++) {
  64. if (!_wcsicmp(str, map[i].m_str))
  65. return map[i].m_data;
  66. }
  67. return NULL;
  68. }
  69. void *StrMap::operator[] (LPWSTR str) {
  70. return Find(str);
  71. }
  72. DWORDMap::DWORDMap() {
  73. count = 0;
  74. mapSize = 64;
  75. map = (DWORDMapEntry *)malloc(sizeof(DWORDMapEntry) * mapSize);
  76. }
  77. DWORDMap::~DWORDMap() {
  78. free(map);
  79. }
  80. BOOL DWORDMap::CheckSpace() {
  81. if (count < mapSize)
  82. return TRUE;
  83. mapSize += 32;
  84. if ((map = (DWORDMapEntry *)realloc(map, sizeof(DWORDMapEntry)*mapSize)) == NULL)
  85. return FALSE;
  86. return TRUE;
  87. }
  88. BOOL DWORDMap::Add(DWORD val, void *data) {
  89. if (!CheckSpace())
  90. return FALSE;
  91. map[count].m_val = val;
  92. map[count].m_data = data;
  93. count++;
  94. return TRUE;
  95. }
  96. BOOL DWORDMap::ClearEntry(DWORD id) {
  97. // !! don't delete the m_data here
  98. // !! it will be or already has been deleted
  99. // !! by StrMap::ClearEntry
  100. int ri = 0;
  101. for (int i=0; i < count; i++) {
  102. if (id == map[i].m_val)
  103. ri = i;
  104. }
  105. count--;
  106. map[ri].m_val = map[count].m_val;
  107. map[ri].m_data = map[count].m_data;
  108. map[count].m_val = NULL;
  109. map[count].m_data = NULL;
  110. return TRUE;
  111. }
  112. void *DWORDMap::Find(DWORD val) {
  113. for (int i=0; i < count; i++) {
  114. if (val == map[i].m_val)
  115. return map[i].m_data;
  116. }
  117. return NULL;
  118. }
  119. void *DWORDMap::operator[] (DWORD val) {
  120. return Find(val);
  121. }
  122. IIsSchemaClass::IIsSchemaClass(LPWSTR _name) {
  123. memset(&classInfo, 0, sizeof(CLASSINFO));
  124. name = new WCHAR[wcslen(_name)+1];
  125. wcscpy(name, _name);
  126. }
  127. IIsSchemaClass::~IIsSchemaClass() {
  128. delete[] name;
  129. if (classInfo.bstrContainment)
  130. FreeADsMem(classInfo.bstrContainment);
  131. if (classInfo.bstrOptionalProperties)
  132. FreeADsMem(classInfo.bstrOptionalProperties);
  133. if (classInfo.bstrMandatoryProperties)
  134. FreeADsMem(classInfo.bstrMandatoryProperties);
  135. }
  136. HRESULT
  137. IISSchemaProperty::SetpropInfo(PROPERTYINFO *ppropInfo) {
  138. HRESULT hr = S_OK;
  139. LPWSTR pszStr;
  140. if (propInfo.bstrOID) {
  141. ADsFreeString( propInfo.bstrOID );
  142. }
  143. if (propInfo.bstrSyntax) {
  144. ADsFreeString( propInfo.bstrSyntax );
  145. }
  146. if (propInfo.szDefault) {
  147. if (propInfo.dwSyntaxId == IIS_SYNTAX_ID_STRING ||
  148. propInfo.dwSyntaxId == IIS_SYNTAX_ID_EXPANDSZ) {
  149. FreeADsStr( propInfo.szDefault );
  150. }
  151. else if (propInfo.dwSyntaxId == IIS_SYNTAX_ID_MULTISZ) {
  152. FreeADsMem( propInfo.szDefault );
  153. }
  154. }
  155. memset(&propInfo, 0, sizeof(PROPERTYINFO));
  156. memcpy(&propInfo, ppropInfo, sizeof(PROPERTYINFO));
  157. hr = ADsAllocString(ppropInfo->bstrSyntax, &propInfo.bstrSyntax);
  158. BAIL_ON_FAILURE(hr);
  159. hr = ADsAllocString(ppropInfo->bstrOID, &propInfo.bstrOID);
  160. BAIL_ON_FAILURE(hr);
  161. switch(ppropInfo->dwSyntaxId) {
  162. case IIS_SYNTAX_ID_DWORD:
  163. case IIS_SYNTAX_ID_BOOL:
  164. case IIS_SYNTAX_ID_BOOL_BITMASK:
  165. propInfo.dwDefault = ppropInfo->dwDefault;
  166. break;
  167. case IIS_SYNTAX_ID_STRING:
  168. case IIS_SYNTAX_ID_EXPANDSZ:
  169. if (ppropInfo->szDefault) {
  170. propInfo.szDefault = AllocADsStr((LPWSTR)(ppropInfo->szDefault));
  171. if (!propInfo.szDefault) {
  172. hr = E_OUTOFMEMORY;
  173. BAIL_ON_FAILURE(hr);
  174. }
  175. }
  176. break;
  177. case IIS_SYNTAX_ID_MIMEMAP:
  178. case IIS_SYNTAX_ID_MULTISZ:
  179. pszStr = ppropInfo->szDefault;
  180. //
  181. // calculate length
  182. //
  183. if (pszStr) {
  184. DWORD dwLen = 0;
  185. //
  186. // if first char is a null char
  187. //
  188. if (*pszStr == L'\0') {
  189. dwLen = 1;
  190. pszStr++;
  191. }
  192. while (*pszStr != L'\0') {
  193. while (*pszStr != L'\0') {
  194. pszStr++;
  195. dwLen++;
  196. }
  197. pszStr++;
  198. dwLen++;
  199. }
  200. propInfo.szDefault = (LPWSTR)AllocADsMem((dwLen +1) * sizeof(WCHAR));
  201. if (!propInfo.szDefault) {
  202. hr = E_OUTOFMEMORY;
  203. BAIL_ON_FAILURE(hr);
  204. }
  205. memcpy(propInfo.szDefault, (LPWSTR)ppropInfo->szDefault,
  206. (dwLen+1)*sizeof(WCHAR));
  207. }
  208. break;
  209. default:
  210. break;
  211. }
  212. error:
  213. RRETURN(hr);
  214. }
  215. IISSchemaProperty::IISSchemaProperty(DWORD id, LPWSTR _name, int nameLen) {
  216. memset(&propInfo, 0, sizeof(PROPERTYINFO));
  217. name = new WCHAR[nameLen];
  218. wcscpy(name, _name);
  219. propID = id;
  220. }
  221. IISSchemaProperty::~IISSchemaProperty() {
  222. delete[] name;
  223. if (propInfo.szDefault) {
  224. if (propInfo.dwSyntaxId == IIS_SYNTAX_ID_MULTISZ) {
  225. FreeADsMem(propInfo.szDefault);
  226. }
  227. else {
  228. FreeADsStr(propInfo.szDefault);
  229. }
  230. }
  231. }
  232. HRESULT IIsSchemaClass::findContainedClassName(LPWSTR pszContainName) {
  233. WCHAR szName[MAX_PATH];
  234. LPWSTR ObjectList = (LPWSTR)classInfo.bstrContainment;
  235. while ((ObjectList = grabProp(szName, ObjectList)) != NULL) {
  236. if (*szName != L'\0') {
  237. if (!_wcsicmp(szName, pszContainName)) {
  238. return S_OK;
  239. }
  240. }
  241. }
  242. return E_ADS_SCHEMA_VIOLATION;
  243. }
  244. HRESULT IIsSchemaClass::SetclassInfo(PCLASSINFO pClassInfo) {
  245. HRESULT hr = S_OK;
  246. LPBYTE pBuffer = NULL;
  247. DWORD dwSize;
  248. if (classInfo.bstrContainment)
  249. FreeADsMem(classInfo.bstrContainment);
  250. if (classInfo.bstrOptionalProperties)
  251. FreeADsMem(classInfo.bstrOptionalProperties);
  252. if (classInfo.bstrMandatoryProperties)
  253. FreeADsMem(classInfo.bstrMandatoryProperties);
  254. memset(&classInfo, 0, sizeof(CLASSINFO));
  255. if (pClassInfo) {
  256. if (pClassInfo->bstrContainment) {
  257. dwSize = (wcslen(pClassInfo->bstrContainment)+1)*sizeof(WCHAR);
  258. pBuffer = (LPBYTE)AllocADsMem(dwSize);
  259. if (!pBuffer) {
  260. hr = E_OUTOFMEMORY;
  261. BAIL_ON_FAILURE(hr);
  262. }
  263. memcpy(pBuffer, pClassInfo->bstrContainment, dwSize);
  264. classInfo.bstrContainment = (BSTR)pBuffer;
  265. }
  266. if (pClassInfo->bstrMandatoryProperties) {
  267. dwSize = (wcslen(pClassInfo->bstrMandatoryProperties)+1)*sizeof(WCHAR);
  268. pBuffer = (LPBYTE)AllocADsMem(dwSize);
  269. if (!pBuffer) {
  270. hr = E_OUTOFMEMORY;
  271. BAIL_ON_FAILURE(hr);
  272. }
  273. memcpy(pBuffer, pClassInfo->bstrMandatoryProperties, dwSize);
  274. classInfo.bstrMandatoryProperties = (BSTR)pBuffer;
  275. }
  276. if (pClassInfo->bstrOptionalProperties) {
  277. dwSize = (wcslen(pClassInfo->bstrOptionalProperties)+1)*sizeof(WCHAR);
  278. pBuffer = (LPBYTE)AllocADsMem(dwSize);
  279. if (!pBuffer) {
  280. hr = E_OUTOFMEMORY;
  281. BAIL_ON_FAILURE(hr);
  282. }
  283. memcpy(pBuffer, pClassInfo->bstrOptionalProperties, dwSize);
  284. classInfo.bstrOptionalProperties = (BSTR)pBuffer;
  285. }
  286. classInfo.fContainer = pClassInfo->fContainer;
  287. }
  288. error:
  289. RRETURN(hr);
  290. }
  291. HRESULT IIsSchemaClass::findProp(LPWSTR pszPropName) {
  292. WCHAR szName[MAX_PATH];
  293. LPWSTR ObjectList = (LPWSTR)classInfo.bstrOptionalProperties;
  294. while ((ObjectList = grabProp(szName, ObjectList)) != NULL) {
  295. if (*szName != L'\0') {
  296. if (!_wcsicmp(szName, pszPropName)) {
  297. return S_OK;
  298. }
  299. }
  300. }
  301. ObjectList = (LPWSTR)classInfo.bstrMandatoryProperties;
  302. while ((ObjectList = grabProp(szName, ObjectList)) != NULL) {
  303. if (*szName != L'\0') {
  304. if (!_wcsicmp(szName, pszPropName)) {
  305. return S_OK;
  306. }
  307. }
  308. }
  309. return E_ADS_PROPERTY_NOT_SUPPORTED;
  310. }
  311. BOOL IISSchemaProperty::InitFromMetaData(METADATA_GETALL_RECORD *mdga, BYTE *data) {
  312. PropValue pv;
  313. if (mdga->dwMDDataType == BINARY_METADATA &&
  314. mdga->dwMDDataLen >= sizeof(PropValue) - sizeof(LPWSTR)) {
  315. memcpy(&pv, (data+mdga->dwMDDataOffset), sizeof(PropValue));
  316. propInfo.dwMetaID = pv.dwMetaID;
  317. propInfo.dwPropID = pv.dwPropID;
  318. propInfo.dwSyntaxId = pv.dwSynID;
  319. propInfo.lMaxRange = (long)pv.dwMaxRange;
  320. propInfo.lMinRange = (long)pv.dwMinRange;
  321. propInfo.dwFlags = pv.dwFlags;
  322. propInfo.dwMask = pv.dwMask;
  323. propInfo.dwMetaFlags = pv.dwMetaFlags;
  324. propInfo.dwUserGroup = pv.dwUserGroup;
  325. propInfo.fMultiValued = pv.fMultiValued;
  326. propInfo.bstrSyntax = SyntaxIdToString(pv.dwSynID);
  327. return TRUE;
  328. }
  329. return FALSE;
  330. }
  331. BOOL IISSchemaProperty::InitPropertyDefaults(METADATA_GETALL_RECORD *mdga, BYTE *data) {
  332. WCHAR *ptr;
  333. propInfo.dwDefault = 0;
  334. propInfo.szDefault = NULL;
  335. switch(mdga->dwMDDataType) {
  336. case DWORD_METADATA:
  337. propInfo.dwDefault = *(DWORD *)(data+mdga->dwMDDataOffset);
  338. break;
  339. case STRING_METADATA:
  340. case EXPANDSZ_METADATA:
  341. propInfo.szDefault = AllocADsStr((LPWSTR)(data+mdga->dwMDDataOffset));
  342. break;
  343. case MULTISZ_METADATA:
  344. ptr = (LPWSTR)(data+mdga->dwMDDataOffset);
  345. propInfo.szDefault = (LPWSTR) AllocADsMem(mdga->dwMDDataLen);
  346. memcpy(propInfo.szDefault, (LPWSTR)ptr, mdga->dwMDDataLen);
  347. break;
  348. case BINARY_METADATA:
  349. break;
  350. }
  351. return TRUE;
  352. }
  353. WCHAR *grabProp(WCHAR *out, WCHAR *in) {
  354. if (!in || *in == L'\0') {
  355. *out = L'\0';
  356. return NULL;
  357. }
  358. while (*in != L',' && *in != L'\0') {
  359. *out++ = *in++;
  360. }
  361. *out = L'\0';
  362. if (*in == L',')
  363. return ++in;
  364. return in;
  365. }
  366. WCHAR *SyntaxIdToString(DWORD syntaxID) {
  367. switch(syntaxID) {
  368. case IIS_SYNTAX_ID_BOOL:
  369. case IIS_SYNTAX_ID_BOOL_BITMASK:
  370. return L"Boolean";
  371. case IIS_SYNTAX_ID_DWORD:
  372. return L"Integer";
  373. case IIS_SYNTAX_ID_STRING:
  374. return L"String";
  375. case IIS_SYNTAX_ID_EXPANDSZ:
  376. return L"ExpandSz";
  377. case IIS_SYNTAX_ID_MIMEMAP:
  378. return L"MimeMapList";
  379. case IIS_SYNTAX_ID_MULTISZ:
  380. return L"List";
  381. case IIS_SYNTAX_ID_IPSECLIST:
  382. return L"IPSec";
  383. case IIS_SYNTAX_ID_NTACL:
  384. return L"NTAcl";
  385. case IIS_SYNTAX_ID_BINARY:
  386. return L"Binary";
  387. default:
  388. return L"(ERROR -- UNDEFINED SYNTAX ID)";
  389. }
  390. }
  391. BOOL DataForSyntaxID(PROPERTYINFO *pp, METADATA_RECORD *mdr) {
  392. static DWORD value=0;
  393. WCHAR *ptr;
  394. int i;
  395. switch(pp->dwSyntaxId) {
  396. case IIS_SYNTAX_ID_BOOL:
  397. case IIS_SYNTAX_ID_BOOL_BITMASK:
  398. case IIS_SYNTAX_ID_DWORD:
  399. mdr->dwMDDataType = DWORD_METADATA;
  400. mdr->dwMDDataLen = sizeof(DWORD);
  401. mdr->pbMDData = (unsigned char *)&(pp->dwDefault);
  402. break;
  403. case IIS_SYNTAX_ID_STRING:
  404. mdr->dwMDDataType = STRING_METADATA;
  405. if (pp->szDefault) {
  406. mdr->dwMDDataLen = (wcslen(pp->szDefault)+1)*2;
  407. }
  408. else {
  409. mdr->dwMDDataLen = 0;
  410. }
  411. mdr->pbMDData = (unsigned char *)pp->szDefault;
  412. break;
  413. case IIS_SYNTAX_ID_EXPANDSZ:
  414. mdr->dwMDDataType = EXPANDSZ_METADATA;
  415. if (pp->szDefault) {
  416. mdr->dwMDDataLen = (wcslen(pp->szDefault)+1)*2;
  417. }
  418. else {
  419. mdr->dwMDDataLen = 0;
  420. }
  421. mdr->pbMDData = (unsigned char *)pp->szDefault;
  422. break;
  423. case IIS_SYNTAX_ID_MIMEMAP:
  424. case IIS_SYNTAX_ID_MULTISZ:
  425. //
  426. // Note, ALL multisz types must have an extra \0 in the table.
  427. //
  428. mdr->dwMDDataType = MULTISZ_METADATA;
  429. if (pp->szDefault) {
  430. ptr = pp->szDefault;
  431. if (*ptr == L'\0') {
  432. ptr++;
  433. }
  434. while (*ptr!=0) {
  435. ptr += wcslen(ptr)+1;
  436. }
  437. mdr->dwMDDataLen = DIFF((char *)ptr - (char *)pp->szDefault)+2;
  438. }
  439. else {
  440. mdr->dwMDDataLen = 0;
  441. }
  442. mdr->pbMDData = (unsigned char *)pp->szDefault;
  443. break;
  444. case IIS_SYNTAX_ID_IPSECLIST:
  445. case IIS_SYNTAX_ID_NTACL:
  446. case IIS_SYNTAX_ID_BINARY:
  447. mdr->dwMDDataType = BINARY_METADATA;
  448. mdr->dwMDDataLen = 0;
  449. mdr->pbMDData = NULL;
  450. break;
  451. default:
  452. mdr->dwMDDataType = DWORD_METADATA;
  453. mdr->dwMDDataLen = sizeof(DWORD);
  454. mdr->pbMDData = (unsigned char *)&value;
  455. return FALSE;
  456. }
  457. return TRUE;
  458. }
  459. DWORD SyntaxToMetaID(DWORD syntaxID) {
  460. switch(syntaxID) {
  461. case IIS_SYNTAX_ID_BOOL:
  462. case IIS_SYNTAX_ID_BOOL_BITMASK:
  463. case IIS_SYNTAX_ID_DWORD:
  464. return DWORD_METADATA;
  465. case IIS_SYNTAX_ID_STRING:
  466. return STRING_METADATA;
  467. case IIS_SYNTAX_ID_EXPANDSZ:
  468. return EXPANDSZ_METADATA;
  469. case IIS_SYNTAX_ID_MIMEMAP:
  470. case IIS_SYNTAX_ID_MULTISZ:
  471. case IIS_SYNTAX_ID_HTTPERRORS:
  472. case IIS_SYNTAX_ID_HTTPHEADERS:
  473. return MULTISZ_METADATA;
  474. case IIS_SYNTAX_ID_IPSECLIST:
  475. case IIS_SYNTAX_ID_NTACL:
  476. case IIS_SYNTAX_ID_BINARY:
  477. return BINARY_METADATA;
  478. default:
  479. // printf("ERROR, Unknown Syntax Type %x", syntaxID);
  480. return 0;
  481. }
  482. return 0;
  483. }
  484. MetaHandle::MetaHandle(IMSAdminBasePtr _pmb) : pmb(_pmb) {
  485. if (pmb)
  486. pmb->AddRef();
  487. h = 0;
  488. }
  489. MetaHandle::~MetaHandle() {
  490. if (pmb) {
  491. if (h)
  492. pmb->CloseKey(h);
  493. pmb->Release();
  494. }
  495. }
  496. HRESULT IIsSchema::IdToPropNameW(DWORD id, LPWSTR buf) {
  497. IISSchemaProperty *prop = (IISSchemaProperty *)idToProp[id];
  498. if (!prop)
  499. return E_ADS_PROPERTY_NOT_SUPPORTED;
  500. wcscpy(buf, prop->getName());
  501. return S_OK;
  502. }
  503. HRESULT IIsSchema::PropNameWToId(LPWSTR propNameW, DWORD *id) {
  504. IISSchemaProperty *prop = (IISSchemaProperty *)nameToProp[propNameW];
  505. if (!prop)
  506. return E_ADS_PROPERTY_NOT_SUPPORTED;
  507. *id = prop->getPropID();
  508. return S_OK;
  509. }
  510. HRESULT IIsSchema::LookupFlagPropName(LPWSTR propNameW, LPWSTR FlagPropName) {
  511. DWORD id;
  512. IISSchemaProperty *prop = (IISSchemaProperty *)nameToProp[propNameW];
  513. if (!prop)
  514. return E_ADS_PROPERTY_NOT_SUPPORTED;
  515. id = prop->getMetaID();
  516. return (ConvertID_To_PropName(id, FlagPropName));
  517. }
  518. HRESULT IIsSchema::LookupMetaID(LPWSTR propNameW, PDWORD pdwMetaId) {
  519. IISSchemaProperty *prop = (IISSchemaProperty *)nameToProp[propNameW];
  520. if (!prop)
  521. return E_ADS_PROPERTY_NOT_SUPPORTED;
  522. *pdwMetaId = prop->getMetaID();
  523. return S_OK;
  524. }
  525. HRESULT IIsSchema::LookupPropID(LPWSTR propNameW, PDWORD pdwPropId) {
  526. IISSchemaProperty *prop = (IISSchemaProperty *)nameToProp[propNameW];
  527. if (!prop)
  528. return E_ADS_PROPERTY_NOT_SUPPORTED;
  529. *pdwPropId = prop->getPropID();
  530. return S_OK;
  531. }
  532. HRESULT IIsSchema::PropNameWToIISSchemaProp(LPWSTR propNameW, IISSchemaProperty **prop) {
  533. *prop = NULL;
  534. *prop = (IISSchemaProperty *)nameToProp[propNameW];
  535. if (!*prop)
  536. return E_ADS_PROPERTY_NOT_SUPPORTED;
  537. return S_OK;
  538. }
  539. HRESULT IIsSchema::ValidatePropertyName( LPWSTR szPropName) {
  540. DWORD propID;
  541. HRESULT hr;
  542. hr = PropNameWToId(szPropName, &propID);
  543. RRETURN(hr);
  544. }
  545. HRESULT IIsSchema::ValidateProperty(LPWSTR szClassName, LPWSTR szPropName) {
  546. HRESULT hr;
  547. IIsSchemaClass *sc;
  548. sc = (IIsSchemaClass*)nameToClass[szClassName];
  549. if (!sc)
  550. return E_ADS_PROPERTY_NOT_SUPPORTED;
  551. hr = sc->findProp(szPropName);
  552. RRETURN(hr);
  553. }
  554. HRESULT IIsSchema::ValidateContainedClassName(LPWSTR szClassName, LPWSTR szContainName) {
  555. HRESULT hr;
  556. IIsSchemaClass *sc;
  557. sc = (IIsSchemaClass *)nameToClass[szClassName];
  558. if (!sc)
  559. RRETURN(E_ADS_UNKNOWN_OBJECT);
  560. hr = sc->findContainedClassName(szContainName);
  561. RRETURN(hr);
  562. }
  563. HRESULT
  564. IIsSchema::GetDefaultProperty(
  565. LPWSTR szPropName,
  566. PDWORD pdwNumValues,
  567. PDWORD pdwSyntax,
  568. LPBYTE *pBuffer
  569. )
  570. /*++
  571. Routine Description:
  572. Arguments:
  573. LPBYTE *pBuffer - pBuffer is not allocated, it just holds the
  574. address of the default value in the PROPINFO
  575. structure
  576. Return Value:
  577. Notes:
  578. Called by CPropertyCache::getproperty
  579. Currently binary values are not supported correctly, we
  580. may not ever support them.
  581. --*/
  582. {
  583. HRESULT hr = S_OK;
  584. IISSchemaProperty *prop = (IISSchemaProperty *)nameToProp[szPropName];
  585. if (!prop)
  586. return E_ADS_PROPERTY_NOT_SUPPORTED;
  587. *pdwSyntax = prop->getSyntaxID();
  588. switch(*pdwSyntax) {
  589. case IIS_SYNTAX_ID_BOOL:
  590. case IIS_SYNTAX_ID_BOOL_BITMASK:
  591. case IIS_SYNTAX_ID_DWORD:
  592. *pBuffer = (LPBYTE)prop->getdwDefaultAddr();
  593. *pdwNumValues = 1;
  594. break;
  595. case IIS_SYNTAX_ID_BINARY:
  596. case IIS_SYNTAX_ID_IPSECLIST:
  597. case IIS_SYNTAX_ID_NTACL:
  598. //
  599. // We don't currently support setting or getting default values,
  600. // so pBuffer should always be NULL. To support default values
  601. // on binaries, we need to transmit the length in the PROPINFO
  602. // structure.
  603. //
  604. *pBuffer = (LPBYTE)prop->getszDefault();
  605. ADsAssert( *pBuffer == NULL );
  606. *pdwNumValues = 0;
  607. break;
  608. case IIS_SYNTAX_ID_MULTISZ:
  609. {
  610. *pBuffer = (LPBYTE)prop->getszDefault();
  611. LPWSTR pszStr = (LPWSTR)*pBuffer;
  612. if (*pszStr == 0) {
  613. *pdwNumValues = 1;
  614. }
  615. else {
  616. *pdwNumValues = 0;
  617. }
  618. while (*pszStr != L'\0') {
  619. while (*pszStr != L'\0') {
  620. pszStr++;
  621. }
  622. (*pdwNumValues)++;
  623. pszStr++;
  624. }
  625. break;
  626. }
  627. default:
  628. *pBuffer = (LPBYTE)prop->getszDefault();
  629. *pdwNumValues = 1;
  630. break;
  631. }
  632. RRETURN(hr);
  633. }
  634. HRESULT IIsSchema::PropNameWToSyntaxId(LPWSTR propNameW, DWORD *syntaxID) {
  635. IISSchemaProperty *prop;
  636. HRESULT hr;
  637. hr = PropNameWToIISSchemaProp(propNameW, &prop);
  638. BAIL_ON_FAILURE(hr);
  639. *syntaxID = prop->getSyntaxID();
  640. return S_OK;
  641. error:
  642. return E_ADS_PROPERTY_NOT_SUPPORTED;
  643. }
  644. HRESULT IIsSchema::ValidateClassName(LPWSTR classNameW) {
  645. if (nameToClass[classNameW])
  646. RRETURN(ERROR_SUCCESS);
  647. else
  648. RRETURN(E_ADS_SCHEMA_VIOLATION);
  649. }
  650. HRESULT IIsSchema::ConvertID_To_PropName(
  651. DWORD dwIdentifier,
  652. LPWSTR pszPropertyName
  653. )
  654. {
  655. HRESULT hr = S_OK;
  656. hr = IdToPropNameW(dwIdentifier, pszPropertyName);
  657. RRETURN(hr);
  658. }
  659. HRESULT IIsSchema::ConvertPropName_To_ID(
  660. LPWSTR pszPropertyName,
  661. PDWORD pdwIdentifier
  662. )
  663. {
  664. HRESULT hr = S_OK;
  665. DWORD i;
  666. if (!pszPropertyName) {
  667. hr = E_ADS_PROPERTY_NOT_SUPPORTED;
  668. BAIL_ON_FAILURE(hr);
  669. }
  670. hr = PropNameWToId(pszPropertyName, pdwIdentifier);
  671. error:
  672. RRETURN(hr);
  673. }
  674. HRESULT IIsSchema::LookupSyntaxID(
  675. LPWSTR pszPropertyName,
  676. PDWORD pdwSyntaxId
  677. )
  678. {
  679. HRESULT hr = S_OK;
  680. DWORD i;
  681. if (!pszPropertyName) {
  682. hr = E_ADS_PROPERTY_NOT_SUPPORTED;
  683. BAIL_ON_FAILURE(hr);
  684. }
  685. hr = PropNameWToSyntaxId(pszPropertyName, pdwSyntaxId);
  686. error:
  687. RRETURN(hr);
  688. }
  689. HRESULT IIsSchema::LookupMDFlags(
  690. DWORD dwPropID,
  691. PDWORD pdwAttribute,
  692. PDWORD pdwUserType
  693. )
  694. {
  695. HRESULT hr = S_OK;
  696. IISSchemaProperty *prop=(IISSchemaProperty *)idToProp[dwPropID];
  697. if (prop) {
  698. *pdwAttribute = prop->getMetaFlags();
  699. *pdwUserType = prop->getUserGroup();
  700. } else {
  701. hr = E_ADS_PROPERTY_NOT_SUPPORTED;
  702. BAIL_ON_FAILURE(hr);
  703. }
  704. return S_OK;
  705. error:
  706. RRETURN(hr);
  707. }
  708. HRESULT
  709. IIsSchema::LookupBitMask(
  710. LPWSTR pszPropertyName,
  711. PDWORD pdwMaskBits
  712. )
  713. {
  714. HRESULT hr = S_OK;
  715. IISSchemaProperty *prop=NULL;
  716. hr = PropNameWToIISSchemaProp(pszPropertyName, &prop);
  717. BAIL_ON_FAILURE(hr);
  718. if (prop) {
  719. *pdwMaskBits = prop->getMask();
  720. } else {
  721. hr = E_ADS_PROPERTY_NOT_SUPPORTED;
  722. BAIL_ON_FAILURE(hr);
  723. }
  724. return S_OK;
  725. error:
  726. RRETURN(hr);
  727. }
  728. HRESULT IIsSchema::LoadAllData(IMSAdminBasePtr &pmb,
  729. MetaHandle &root,
  730. WCHAR *subdir,
  731. BYTE **buf,
  732. DWORD *size,
  733. DWORD *count) {
  734. DWORD dataSet;
  735. DWORD neededSize;
  736. HRESULT hr;
  737. //
  738. // Try to get the property names.
  739. //
  740. hr = pmb->GetAllData(root,
  741. subdir,
  742. METADATA_NO_ATTRIBUTES,
  743. ALL_METADATA,
  744. ALL_METADATA,
  745. count,
  746. &dataSet,
  747. *size,
  748. *buf,
  749. &neededSize);
  750. if (!SUCCEEDED(hr)) {
  751. DWORD code = ERROR_INSUFFICIENT_BUFFER;
  752. if (hr == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) {
  753. // printf("Names buf of %d not big enough. Need %d bytes\n",
  754. // getAllBufSize,
  755. // neededSize);
  756. delete *buf;
  757. *buf = 0;
  758. *size = neededSize;
  759. *buf = new BYTE[neededSize];
  760. hr = pmb->GetAllData(root,
  761. subdir,
  762. METADATA_NO_ATTRIBUTES,
  763. ALL_METADATA,
  764. ALL_METADATA,
  765. count,
  766. &dataSet,
  767. *size,
  768. *buf,
  769. &neededSize);
  770. }
  771. }
  772. return hr;
  773. }
  774. // BUGBUG: Get rid of this constant ASAP!
  775. // Sergeia: fix for bug 189797, buffer was too small
  776. const DWORD getAllBufSize = 4096*2;
  777. HRESULT IIsSchema::InitSchema(WCHAR *baseName){
  778. // IUnknown* pIUnknown;
  779. DWORD bufSize = getAllBufSize;
  780. BYTE *buf = new BYTE[bufSize];
  781. HRESULT hr;
  782. COSERVERINFO csiName;
  783. COSERVERINFO *pcsiParam = &csiName;
  784. IClassFactory * pcsfFactory = NULL;
  785. IMSAdminBase * pAdminBase = NULL;
  786. IMSAdminBase * pAdminBaseT = NULL;
  787. DWORD count=0, dataSet=0, neededSize=0, dwStatus;
  788. METADATA_GETALL_RECORD *pmd;
  789. DWORD propBufSize = 128;
  790. DWORD i;
  791. MetaHandle root(NULL);
  792. LPWSTR pContainment = NULL;
  793. LPWSTR pOptProp = NULL;
  794. LPWSTR pMandProp = NULL;
  795. DWORD dwData = 0;
  796. CLASSINFO classInfo;
  797. // printf("Loading schema....\n");
  798. memset(pcsiParam, 0, sizeof(COSERVERINFO));
  799. pcsiParam->pwszName = baseName;
  800. csiName.pAuthInfo = NULL;
  801. pcsiParam = &csiName;
  802. hr = CoGetClassObject(
  803. CLSID_MSAdminBase,
  804. CLSCTX_SERVER,
  805. pcsiParam,
  806. IID_IClassFactory,
  807. (void**) &pcsfFactory
  808. );
  809. BAIL_ON_FAILURE(hr);
  810. hr = pcsfFactory->CreateInstance(
  811. NULL,
  812. IID_IMSAdminBase,
  813. (void **) &pAdminBase
  814. );
  815. BAIL_ON_FAILURE(hr);
  816. root.setpointer(pAdminBase);
  817. hr = pAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  818. L"/Schema/Properties",
  819. METADATA_PERMISSION_READ,
  820. DEFAULT_TIMEOUT_VALUE,
  821. root);
  822. BAIL_ON_FAILURE(hr);
  823. hr = LoadAllData(pAdminBase, root, L"Names", &buf, &bufSize, &count);
  824. BAIL_ON_FAILURE(hr);
  825. // printf("Loaded %d Properties\n", count);
  826. //
  827. // Now, here we've gotten the list of properties/names.
  828. // Create IIsSchemaProperty objects for each. We then
  829. // Add the object to the two maps. Later, we will load
  830. // all of the "Properties/Values" properties, look up (by
  831. // id) the object, and initialize the property value.
  832. //
  833. pmd = (METADATA_GETALL_RECORD *)buf;
  834. for ( i=0;i < count; i++, pmd++) {
  835. if (pmd->dwMDDataType != STRING_METADATA) {
  836. // printf("Error: Property name not a string, need to figure out what to do.\n");
  837. continue;
  838. }
  839. LPWSTR name = (WCHAR *)(buf + pmd->dwMDDataOffset);
  840. // printf(" Loading %s\n", name);
  841. IISSchemaProperty *pProp
  842. = new IISSchemaProperty(
  843. pmd->dwMDIdentifier,
  844. name,
  845. pmd->dwMDDataLen);
  846. idToProp.Add(pmd->dwMDIdentifier, pProp);
  847. nameToProp.Add(pProp->getName(), pProp);
  848. }
  849. hr = LoadAllData(pAdminBase, root, L"Types", &buf, &bufSize, &count);
  850. BAIL_ON_FAILURE(hr);
  851. //
  852. // Now, here we've gotten the list of properties/values.
  853. // We then need to look up the properties by id (since that's
  854. // what we have) and initialize the property type information.
  855. //
  856. for (i=0;i < count; i++) {
  857. pmd = ((METADATA_GETALL_RECORD*)buf) + i;
  858. IISSchemaProperty *pProp = (IISSchemaProperty *)(idToProp[pmd->dwMDIdentifier]);
  859. if (pProp == NULL) {
  860. // printf("Error finding prop value %x", pmd->dwMDIdentifier);
  861. continue;
  862. }
  863. pProp->InitFromMetaData(pmd, buf);
  864. }
  865. hr = LoadAllData(pAdminBase, root, L"Defaults", &buf, &bufSize, &count);
  866. BAIL_ON_FAILURE(hr);
  867. //
  868. // Now, here we've gotten the list of properties/defaults.
  869. // We then need to look up the properties by id (since that's
  870. // what we have) and initialize the property type information.
  871. //
  872. for (i=0;i < count; i++) {
  873. pmd = ((METADATA_GETALL_RECORD*)buf) + i;
  874. IISSchemaProperty *pProp = (IISSchemaProperty *)(idToProp[pmd->dwMDIdentifier]);
  875. if (pProp == NULL) {
  876. // printf("Error finding prop value %x", pmd->dwMDIdentifier);
  877. continue;
  878. }
  879. pProp->InitPropertyDefaults(pmd, buf);
  880. }
  881. root.close();
  882. // Next, we need to initialize the class map.
  883. WCHAR className[METADATA_MAX_NAME_LEN];
  884. hr = pAdminBase->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  885. L"/Schema/Classes",
  886. METADATA_PERMISSION_READ,
  887. DEFAULT_TIMEOUT_VALUE,
  888. root);
  889. BAIL_ON_FAILURE(hr);
  890. for (i=0; TRUE ; i++) {
  891. hr = pAdminBase->EnumKeys(root, L"", (LPWSTR)className, i);
  892. if (!SUCCEEDED(hr)) {
  893. hr = ERROR_SUCCESS ;
  894. break;
  895. }
  896. IIsSchemaClass *psc = new IIsSchemaClass(className);
  897. //
  898. // Load the Containment, Mandatory, Optional, and Container properties.
  899. //
  900. hr = MetaBaseGetStringData(pAdminBase,
  901. root,
  902. className,
  903. MD_SCHEMA_CLASS_CONTAINMENT,
  904. (LPBYTE*)&pContainment
  905. );
  906. BAIL_ON_FAILURE(hr);
  907. hr = MetaBaseGetStringData(pAdminBase,
  908. root,
  909. className,
  910. MD_SCHEMA_CLASS_OPT_PROPERTIES,
  911. (LPBYTE*)&pOptProp
  912. );
  913. BAIL_ON_FAILURE(hr);
  914. hr = MetaBaseGetStringData(pAdminBase,
  915. root,
  916. className,
  917. MD_SCHEMA_CLASS_MAND_PROPERTIES,
  918. (LPBYTE*)&pMandProp
  919. );
  920. BAIL_ON_FAILURE(hr);
  921. hr = MetaBaseGetDwordData(pAdminBase,
  922. root,
  923. className,
  924. MD_SCHEMA_CLASS_CONTAINER,
  925. &dwData
  926. );
  927. BAIL_ON_FAILURE(hr);
  928. classInfo.bstrContainment = pContainment;
  929. classInfo.bstrOptionalProperties = pOptProp;
  930. classInfo.bstrMandatoryProperties = pMandProp;
  931. classInfo.fContainer = dwData ? TRUE : FALSE;
  932. psc->SetclassInfo(&classInfo);
  933. nameToClass.Add(psc->getName(), psc);
  934. }
  935. error:
  936. if (pAdminBase) {
  937. pAdminBase->Release();
  938. }
  939. if (pContainment) {
  940. FreeADsMem(pContainment);
  941. }
  942. if (pOptProp) {
  943. FreeADsMem(pOptProp);
  944. }
  945. if (pMandProp) {
  946. FreeADsMem(pMandProp);
  947. }
  948. if (hr != ERROR_SUCCESS) {
  949. if (buf)
  950. delete buf;
  951. }
  952. if (pcsfFactory) {
  953. pcsfFactory->Release();
  954. }
  955. RRETURN(hr);
  956. }
  957. HRESULT IIsSchema::GetTotalEntries(PDWORD pdwEntries) {
  958. *pdwEntries = nameToClass.GetEntries() + nameToProp.GetEntries();
  959. RRETURN(S_OK);
  960. }
  961. DWORD IIsSchema::GetClassEntries() {
  962. return nameToClass.GetEntries();
  963. }
  964. DWORD IIsSchema::GetPropEntries() {
  965. return nameToProp.GetEntries();
  966. }
  967. LPWSTR IIsSchema::GetClassName(DWORD dwIndex) {
  968. return nameToClass.GetEntryName(dwIndex);
  969. }
  970. LPWSTR IIsSchema::GetPropName(DWORD dwIndex) {
  971. return nameToProp.GetEntryName(dwIndex);
  972. }
  973. HRESULT IIsSchema::RemoveEntry(BOOL bClass, LPWSTR pszName) {
  974. DWORD i;
  975. DWORD id = 0;
  976. LPWSTR pszPropName;
  977. LPWSTR pszClassName;
  978. IISSchemaProperty *prop;
  979. if (bClass)
  980. {
  981. // clear nameToClass entry using pszName
  982. for ( i = 0; i < nameToClass.GetEntries(); i++ )
  983. {
  984. pszClassName = nameToClass.GetEntryName(i);
  985. if (pszClassName != NULL && _wcsicmp( pszClassName, pszName) == 0 ) {
  986. nameToClass.ClearEntry(i);
  987. }
  988. }
  989. }
  990. else
  991. {
  992. // clear nameToProp entry using pszName
  993. for ( i = 0; i < nameToProp.GetEntries(); i++ )
  994. {
  995. pszPropName = nameToProp.GetEntryName(i);
  996. if (pszPropName != NULL && _wcsicmp( pszPropName, pszName) == 0 ) {
  997. prop = (IISSchemaProperty *)nameToProp[pszPropName];
  998. if (!prop)
  999. RRETURN(E_ADS_PROPERTY_NOT_SUPPORTED);
  1000. id = prop->getPropID();
  1001. nameToProp.ClearEntry(i);
  1002. }
  1003. }
  1004. // clear idToProp entry using id
  1005. if (id != 0)
  1006. {
  1007. idToProp.ClearEntry(id);
  1008. }
  1009. }
  1010. RRETURN(S_OK);
  1011. }
  1012. PCLASSINFO IIsSchema::GetClassInfo(LPWSTR pszName) {
  1013. DWORD i;
  1014. LPWSTR pszClassName;
  1015. IIsSchemaClass *sc;
  1016. for ( i = 0; i < nameToClass.GetEntries(); i++ )
  1017. {
  1018. pszClassName = nameToClass.GetEntryName(i);
  1019. if (pszClassName != NULL && _wcsicmp( pszClassName, pszName) == 0 ) {
  1020. sc = (IIsSchemaClass *)nameToClass[pszClassName];
  1021. return sc != NULL ? sc->GetclassInfo() : NULL;
  1022. }
  1023. }
  1024. return NULL;
  1025. }
  1026. PPROPERTYINFO IIsSchema::GetPropertyInfo(LPWSTR pszName) {
  1027. DWORD i;
  1028. LPWSTR pszPropName;
  1029. IISSchemaProperty *prop;
  1030. for ( i = 0; i < nameToProp.GetEntries(); i++ )
  1031. {
  1032. pszPropName = nameToProp.GetEntryName(i);
  1033. if (pszPropName != NULL && _wcsicmp( pszPropName, pszName) == 0 ) {
  1034. prop = (IISSchemaProperty *)nameToProp[pszPropName];
  1035. return prop->GetpropInfo();
  1036. }
  1037. }
  1038. return NULL;
  1039. }
  1040. HRESULT IIsSchema::SetClassInfo(LPWSTR pszName, PCLASSINFO pClassInfo) {
  1041. DWORD i;
  1042. LPWSTR pszClassName;
  1043. IIsSchemaClass *sc;
  1044. for ( i = 0; i < nameToClass.GetEntries(); i++ )
  1045. {
  1046. pszClassName = nameToClass.GetEntryName(i);
  1047. if (pszClassName != NULL && _wcsicmp( pszClassName, pszName) == 0 ) {
  1048. sc = (IIsSchemaClass *)nameToClass[pszClassName];
  1049. return sc != NULL ? sc->SetclassInfo(pClassInfo) : E_FAIL;
  1050. }
  1051. }
  1052. //
  1053. // add to schema cache if doesn't exist
  1054. //
  1055. sc = new IIsSchemaClass(pszName);
  1056. sc->SetclassInfo(pClassInfo);
  1057. nameToClass.Add(sc->getName(), sc);
  1058. RRETURN(S_OK);
  1059. }
  1060. HRESULT IIsSchema::SetPropertyInfo(LPWSTR pszName, PPROPERTYINFO pPropInfo) {
  1061. DWORD i;
  1062. LPWSTR pszPropName;
  1063. IISSchemaProperty *prop;
  1064. for ( i = 0; i < nameToProp.GetEntries(); i++ )
  1065. {
  1066. pszPropName = nameToProp.GetEntryName(i);
  1067. if ( _wcsicmp( pszPropName, pszName) == 0 ) {
  1068. prop = (IISSchemaProperty *)nameToProp[pszPropName];
  1069. return prop != NULL ? prop->SetpropInfo(pPropInfo) : E_FAIL;
  1070. }
  1071. }
  1072. //
  1073. // add to schema cache if doesn't exist
  1074. //
  1075. prop = new IISSchemaProperty(pPropInfo->dwPropID,
  1076. pszName,
  1077. wcslen(pszName)+1);
  1078. if (prop != NULL)
  1079. prop->SetpropInfo(pPropInfo);
  1080. else
  1081. return E_FAIL;
  1082. idToProp.Add(pPropInfo->dwPropID, prop);
  1083. nameToProp.Add(prop->getName(), prop);
  1084. RRETURN(S_OK);
  1085. }
  1086. IIsSchema::IIsSchema() {}
  1087. void InitPropValue(PropValue *pv, PROPERTYINFO *pi) {
  1088. pv->dwSynID = pi->dwSyntaxId;
  1089. pv->dwMetaID = pi->dwMetaID;
  1090. pv->dwPropID = pi->dwPropID;
  1091. pv->dwMaxRange = (DWORD)pi->lMaxRange;
  1092. pv->dwMinRange = (DWORD)pi->lMinRange;
  1093. switch(pi->dwSyntaxId) {
  1094. case IIS_SYNTAX_ID_DWORD:
  1095. case IIS_SYNTAX_ID_BOOL:
  1096. case IIS_SYNTAX_ID_BOOL_BITMASK:
  1097. pv->dwMetaType = DWORD_METADATA;
  1098. break;
  1099. case IIS_SYNTAX_ID_STRING:
  1100. pv->dwMetaType = STRING_METADATA;
  1101. break;
  1102. case IIS_SYNTAX_ID_EXPANDSZ:
  1103. pv->dwMetaType = EXPANDSZ_METADATA;
  1104. break;
  1105. case IIS_SYNTAX_ID_MIMEMAP:
  1106. case IIS_SYNTAX_ID_MULTISZ:
  1107. pv->dwMetaType = MULTISZ_METADATA;
  1108. break;
  1109. case IIS_SYNTAX_ID_NTACL:
  1110. case IIS_SYNTAX_ID_BINARY:
  1111. case IIS_SYNTAX_ID_IPSECLIST:
  1112. pv->dwMetaType = BINARY_METADATA;
  1113. break;
  1114. }
  1115. pv->dwFlags = pi->dwFlags;
  1116. pv->fMultiValued = pi->fMultiValued;
  1117. pv->dwMask = pi->dwMask;
  1118. pv->dwMetaFlags = pi->dwMetaFlags;
  1119. pv->dwUserGroup = pi->dwUserGroup;
  1120. }