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.

681 lines
17 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // sdodictionary.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the class SdoDictionary.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 03/01/1999 Original version.
  16. // 01/27/2000 Add support for proxy policies.
  17. // 04/17/2000 Port to new dictionary API.
  18. //
  19. ///////////////////////////////////////////////////////////////////////////////
  20. #include <stdafx.h>
  21. #include <vector>
  22. #include <iastlb.h>
  23. #include <iastlutl.h>
  24. #include <iasutil.h>
  25. #include <iasuuid.h>
  26. #include <attrdef.h>
  27. #include <sdoattribute.h>
  28. #include <sdodictionary.h>
  29. #include "resource.h"
  30. using namespace std;
  31. // Function type used with bsearch and qsort.
  32. typedef int (__cdecl *CompFn)(const void*, const void*);
  33. inline SdoDictionary::SdoDictionary() throw ()
  34. : refCount(0),
  35. dnaryLoc(NULL),
  36. size(0),
  37. byId(NULL),
  38. byName(NULL),
  39. byLdapName(NULL)
  40. {
  41. }
  42. inline SdoDictionary::~SdoDictionary() throw ()
  43. {
  44. for (ULONG i = 0; i < size; ++i)
  45. {
  46. if (byId[i]) { byId[i]->Release(); }
  47. }
  48. delete[] byId;
  49. delete[] byName;
  50. delete[] byLdapName;
  51. delete dnaryLoc;
  52. }
  53. HRESULT SdoDictionary::createInstance(
  54. PCWSTR path,
  55. bool local,
  56. SdoDictionary** newDnary
  57. ) throw ()
  58. {
  59. // Check the arguments.
  60. if (path == NULL || newDnary == NULL) { return E_INVALIDARG; }
  61. // Initialize the out parameter.
  62. *newDnary = NULL;
  63. // Create a new dictionary.
  64. SdoDictionary* dnary = new (std::nothrow) SdoDictionary;
  65. if (!dnary) { return E_OUTOFMEMORY; }
  66. // Build the DSN.
  67. PWCHAR dsn = (PWCHAR)_alloca((wcslen(path) + 11) * sizeof(WCHAR));
  68. wcscat(wcscpy(dsn, path), L"\\dnary.mdb");
  69. // Initialize the dictionary.
  70. HRESULT hr = dnary->initialize(dsn, local);
  71. if (FAILED(hr))
  72. {
  73. delete dnary;
  74. return hr;
  75. }
  76. // Set the refCount & return.
  77. dnary->refCount = 1;
  78. *newDnary = dnary;
  79. return S_OK;
  80. }
  81. const AttributeDefinition* SdoDictionary::findById(
  82. ULONG id
  83. ) const throw ()
  84. {
  85. const AttributeDefinition* const* match;
  86. match = (const AttributeDefinition* const*)
  87. bsearch(
  88. &id,
  89. byId,
  90. size,
  91. sizeof(AttributeDefinition*),
  92. (CompFn)AttributeDefinition::searchById
  93. );
  94. return match ? *match : NULL;
  95. }
  96. const AttributeDefinition* SdoDictionary::findByName(
  97. PCWSTR name
  98. ) const throw ()
  99. {
  100. const AttributeDefinition* const* match;
  101. match = (const AttributeDefinition* const*)
  102. bsearch(
  103. name,
  104. byName,
  105. size,
  106. sizeof(AttributeDefinition*),
  107. (CompFn)AttributeDefinition::searchByName
  108. );
  109. return match ? *match : NULL;
  110. }
  111. const AttributeDefinition* SdoDictionary::findByLdapName(
  112. PCWSTR name
  113. ) const throw ()
  114. {
  115. const AttributeDefinition* const* match;
  116. match = (const AttributeDefinition* const*)
  117. bsearch(
  118. name,
  119. byLdapName,
  120. size,
  121. sizeof(AttributeDefinition*),
  122. (CompFn)AttributeDefinition::searchByLdapName
  123. );
  124. return match ? *match : NULL;
  125. }
  126. STDMETHODIMP_(ULONG) SdoDictionary::AddRef()
  127. {
  128. return InterlockedIncrement(&refCount);
  129. }
  130. STDMETHODIMP_(ULONG) SdoDictionary::Release()
  131. {
  132. ULONG l = InterlockedDecrement(&refCount);
  133. if (l == 0) { delete this; }
  134. return l;
  135. }
  136. STDMETHODIMP SdoDictionary::QueryInterface(REFIID iid, void ** ppvObject)
  137. {
  138. if (ppvObject == NULL) { return E_POINTER; }
  139. if (iid == __uuidof(ISdoDictionaryOld) ||
  140. iid == __uuidof(IUnknown) ||
  141. iid == __uuidof(IDispatch))
  142. {
  143. *ppvObject = this;
  144. }
  145. else if (iid == __uuidof(ISdo))
  146. {
  147. *ppvObject = static_cast<ISdo*>(this);
  148. }
  149. else
  150. {
  151. return E_NOINTERFACE;
  152. }
  153. InterlockedIncrement(&refCount);
  154. return S_OK;
  155. }
  156. STDMETHODIMP SdoDictionary::EnumAttributes(
  157. VARIANT* Id,
  158. VARIANT* pValues
  159. )
  160. {
  161. // Check the arguments.
  162. if (Id == NULL || pValues == NULL) { return E_INVALIDARG; }
  163. // Initialize the out parameters.
  164. VariantInit(Id);
  165. VariantInit(pValues);
  166. // Find out what the caller's asking for.
  167. const AttributeDefinition* single;
  168. const AttributeDefinition* const* src;
  169. ULONG numAttrs;
  170. if (V_VT(Id) == VT_EMPTY)
  171. {
  172. // He wants all the attributes.
  173. src = byId;
  174. numAttrs = size;
  175. }
  176. else if (V_VT(Id) == VT_I4)
  177. {
  178. // He wants a single attribute.
  179. single = findById(V_VT(Id));
  180. if (!single) { return DISP_E_MEMBERNOTFOUND; }
  181. src = &single;
  182. numAttrs = 1;
  183. }
  184. else
  185. {
  186. // Invalid VARIANT type.
  187. return E_INVALIDARG;
  188. }
  189. HRESULT hr = S_OK;
  190. do
  191. {
  192. //////////
  193. // Allocate SAFEARRAYs to hold the return values.
  194. //////////
  195. V_ARRAY(Id) = SafeArrayCreateVector(VT_I4, 0, numAttrs);
  196. V_VT(Id) = VT_ARRAY | VT_I4;
  197. V_ARRAY(pValues) = SafeArrayCreateVector(VT_VARIANT, 0, numAttrs);
  198. V_VT(pValues) = VT_ARRAY | VT_VARIANT;
  199. if (!V_ARRAY(Id) || !V_ARRAY(pValues))
  200. {
  201. hr = E_OUTOFMEMORY;
  202. break;
  203. }
  204. //////////
  205. // Populate the arrays.
  206. //////////
  207. const AttributeDefinition* const* end = src + numAttrs;
  208. PULONG dstId = (PULONG)V_ARRAY(Id)->pvData;
  209. LPVARIANT dstName = (LPVARIANT)V_ARRAY(pValues)->pvData;
  210. for ( ; src != end; ++src, ++dstId, ++dstName)
  211. {
  212. *dstId = (*src)->id;
  213. V_BSTR(dstName) = SysAllocString((*src)->name);
  214. if (!V_BSTR(dstName))
  215. {
  216. hr = E_OUTOFMEMORY;
  217. break;
  218. }
  219. V_VT(dstName) = VT_BSTR;
  220. }
  221. } while (false);
  222. // If anything went wrong, clean up.
  223. if (FAILED(hr))
  224. {
  225. VariantClear(Id);
  226. VariantClear(pValues);
  227. }
  228. return hr;
  229. }
  230. STDMETHODIMP SdoDictionary::GetAttributeInfo(
  231. ATTRIBUTEID Id,
  232. VARIANT* pInfoIDs,
  233. VARIANT* pInfoValues
  234. )
  235. {
  236. // Check the arguments.
  237. if (pInfoValues == NULL ||
  238. pInfoIDs == NULL ||
  239. // V_VT(pInfoIDs) != (VT_ARRAY | VT_I4) ||
  240. V_ARRAY(pInfoIDs) == NULL ||
  241. V_ARRAY(pInfoIDs)->cDims != 1)
  242. {
  243. return E_INVALIDARG;
  244. }
  245. // Initialize the out parameter.
  246. VariantInit(pInfoValues);
  247. // Find the attribute of interest.
  248. const AttributeDefinition* def = findById(Id);
  249. if (!def) { return DISP_E_MEMBERNOTFOUND; }
  250. // Allocate the outbound array.
  251. ULONG num = V_ARRAY(pInfoIDs)->rgsabound[0].cElements;
  252. V_ARRAY(pInfoValues) = SafeArrayCreateVector(VT_VARIANT, 0, num);
  253. if (!V_ARRAY(pInfoValues)) { return E_OUTOFMEMORY; }
  254. V_VT(pInfoValues) = VT_ARRAY | VT_VARIANT;
  255. // Fill in the information.
  256. PULONG src = (PULONG)V_ARRAY(pInfoIDs)->pvData;
  257. LPVARIANT dst = (LPVARIANT)V_ARRAY(pInfoValues)->pvData;
  258. for ( ; num > 0; --num, ++src, ++dst)
  259. {
  260. HRESULT hr = def->getInfo((ATTRIBUTEINFO)*src, dst);
  261. if (FAILED(hr))
  262. {
  263. VariantClear(pInfoValues);
  264. return hr;
  265. }
  266. }
  267. return S_OK;
  268. }
  269. STDMETHODIMP SdoDictionary::EnumAttributeValues(
  270. ATTRIBUTEID Id,
  271. VARIANT* pValueIds,
  272. VARIANT* pValuesDesc
  273. )
  274. {
  275. // Check the arguments.
  276. if (pValueIds == NULL || pValuesDesc == NULL) { return E_INVALIDARG; }
  277. // Initialize the out parameters.
  278. VariantInit(pValueIds);
  279. VariantInit(pValuesDesc);
  280. // Find the attribute of interest.
  281. const AttributeDefinition* def = findById(Id);
  282. if (!def) { return DISP_E_MEMBERNOTFOUND; }
  283. // If it's not enumerable, there's nothing to do.
  284. if (def->enumNames == NULL) { return S_OK; }
  285. // Copy the enum Names and Values.
  286. HRESULT hr = SafeArrayCopy(def->enumValues, &V_ARRAY(pValueIds));
  287. if (SUCCEEDED(hr))
  288. {
  289. V_VT(pValueIds) = VT_ARRAY | VT_I4;
  290. hr = SafeArrayCopy(def->enumNames, &V_ARRAY(pValuesDesc));
  291. if (SUCCEEDED(hr))
  292. {
  293. V_VT(pValuesDesc) = VT_ARRAY | VT_VARIANT;
  294. }
  295. else
  296. {
  297. VariantClear(pValueIds);
  298. }
  299. }
  300. return hr;
  301. }
  302. STDMETHODIMP SdoDictionary::CreateAttribute(
  303. ATTRIBUTEID Id,
  304. IDispatch** ppAttributeObject
  305. )
  306. {
  307. // Check the arguments.
  308. if (ppAttributeObject == NULL) { return E_INVALIDARG; }
  309. // Initialize the out parameter.
  310. *ppAttributeObject = NULL;
  311. // Find the attribute of interest.
  312. const AttributeDefinition* def = findById(Id);
  313. if (!def) { return DISP_E_MEMBERNOTFOUND; }
  314. SdoAttribute* newAttr;
  315. HRESULT hr = SdoAttribute::createInstance(def, &newAttr);
  316. if (FAILED(hr)) { return hr; }
  317. *ppAttributeObject = newAttr;
  318. return S_OK;
  319. }
  320. STDMETHODIMP SdoDictionary::GetAttributeID(
  321. BSTR bstrAttributeName,
  322. ATTRIBUTEID* pId
  323. )
  324. {
  325. // Check the arguments.
  326. if (bstrAttributeName == NULL || pId == NULL) { return E_INVALIDARG; }
  327. const AttributeDefinition* match;
  328. // Check for LDAP Name first since this will speed up load time.
  329. match = findByLdapName(bstrAttributeName);
  330. if (!match)
  331. {
  332. // Maybe it's a display name instead.
  333. match = findByName(bstrAttributeName);
  334. }
  335. if (!match) { return DISP_E_MEMBERNOTFOUND; }
  336. *pId = (ATTRIBUTEID)match->id;
  337. return S_OK;
  338. }
  339. STDMETHODIMP SdoDictionary::GetPropertyInfo(LONG Id, IUnknown** ppPropertyInfo)
  340. { return E_NOTIMPL; }
  341. STDMETHODIMP SdoDictionary::GetProperty(LONG Id, VARIANT* pValue)
  342. {
  343. // Check the input args.
  344. if (pValue == NULL) { return E_INVALIDARG; }
  345. // Initialize the out parameter.
  346. VariantInit(pValue);
  347. // We only have one property.
  348. if (Id != PROPERTY_DICTIONARY_LOCATION) { return DISP_E_MEMBERNOTFOUND; }
  349. // dnaryLoc may be NULL.
  350. if (dnaryLoc)
  351. {
  352. V_BSTR(pValue) = SysAllocString(dnaryLoc);
  353. if (!V_BSTR(pValue)) { return E_OUTOFMEMORY; }
  354. }
  355. else
  356. {
  357. V_BSTR(pValue) = NULL;
  358. }
  359. V_VT(pValue) = VT_BSTR;
  360. return S_OK;
  361. }
  362. STDMETHODIMP SdoDictionary::PutProperty(LONG Id, VARIANT* pValue)
  363. { return E_ACCESSDENIED; }
  364. STDMETHODIMP SdoDictionary::ResetProperty(LONG Id)
  365. { return S_OK; }
  366. STDMETHODIMP SdoDictionary::Apply()
  367. { return S_OK; }
  368. STDMETHODIMP SdoDictionary::Restore()
  369. { return S_OK; }
  370. STDMETHODIMP SdoDictionary::get__NewEnum(IUnknown** ppEnumVARIANT)
  371. { return E_NOTIMPL; }
  372. HRESULT SdoDictionary::initialize(PCWSTR dsn, bool local) throw ()
  373. {
  374. const size_t IAS_MAX_STRING = 512;
  375. // Save the dsn.
  376. size_t nbyte = (wcslen(dsn) + 1) * sizeof(WCHAR);
  377. dnaryLoc = (PWSTR)operator new (nbyte, std::nothrow);
  378. if (!dnaryLoc) { return E_OUTOFMEMORY; }
  379. memcpy(dnaryLoc, dsn, nbyte);
  380. // Vector to hold the AttributeDefinitions.
  381. vector<const AttributeDefinition*> defs;
  382. HRESULT hr = S_OK;
  383. try
  384. {
  385. // Names of various columns in the dictionary.
  386. const PCWSTR COLUMNS[] =
  387. {
  388. L"ID",
  389. L"Name",
  390. L"Syntax",
  391. L"MultiValued",
  392. L"VendorID",
  393. L"IsAllowedInProfile",
  394. L"IsAllowedInCondition",
  395. L"-IsAllowedInProxyProfile",
  396. L"-IsAllowedInProxyCondition",
  397. L"Description",
  398. L"LDAPName",
  399. L"EnumNames",
  400. L"EnumValues",
  401. NULL
  402. };
  403. // Open the attributes table.
  404. IASTL::IASDictionary dnary(COLUMNS, (local ? NULL : dsn));
  405. defs.reserve(dnary.getNumRows());
  406. while (dnary.next())
  407. {
  408. // We're not interested in attributes that don't have a name.
  409. if (dnary.isEmpty(1)) { continue; }
  410. // Create a new AttributeDefinition.
  411. CComPtr<AttributeDefinition> def;
  412. HRESULT hr = AttributeDefinition::createInstance(&def);
  413. if (FAILED(hr)) { throw bad_alloc(); }
  414. /////////
  415. // Process the fields in the query result.
  416. /////////
  417. def->id = (ULONG)dnary.getLong(0);
  418. def->name = SysAllocString(dnary.getBSTR(1));
  419. if (!def->name) { throw bad_alloc(); }
  420. def->syntax = (ULONG)dnary.getLong(2);
  421. if (dnary.getBool(3))
  422. {
  423. def->restrictions |= MULTIVALUED;
  424. }
  425. def->vendor = (ULONG)dnary.getLong(4);
  426. if (dnary.getBool(5))
  427. {
  428. def->restrictions |= ALLOWEDINPROFILE;
  429. }
  430. if (dnary.getBool(6))
  431. {
  432. def->restrictions |= ALLOWEDINCONDITION;
  433. }
  434. if (dnary.getBool(7))
  435. {
  436. def->restrictions |= ALLOWEDINPROXYPROFILE;
  437. }
  438. if (dnary.getBool(8))
  439. {
  440. def->restrictions |= ALLOWEDINPROXYCONDITION;
  441. }
  442. if (dnary.isEmpty(9))
  443. {
  444. // Whistler machine. Load the string from the rc file
  445. WCHAR strTemp[IAS_MAX_STRING];
  446. int nbChar = LoadString(
  447. _Module.GetResourceInstance(),
  448. static_cast<UINT>(def->id),
  449. strTemp,
  450. IAS_MAX_STRING
  451. );
  452. if (nbChar > 0)
  453. {
  454. // Description found
  455. def->description = SysAllocString(strTemp);
  456. if (!def->description) { throw bad_alloc();}
  457. }
  458. else
  459. {
  460. // Load the Default string
  461. nbChar = LoadString(
  462. _Module.GetResourceInstance(),
  463. IDS_DESC_NOT_AVAIL,
  464. strTemp,
  465. IAS_MAX_STRING
  466. );
  467. _ASSERT(nbChar > 0);
  468. def->description = SysAllocString(strTemp);
  469. if (!def->description) { throw bad_alloc();}
  470. }
  471. }
  472. else
  473. {
  474. // This is a Windows 2000 machine
  475. def->description = SysAllocString(dnary.getBSTR(9));
  476. if (!def->description) { throw bad_alloc(); }
  477. }
  478. if (!dnary.isEmpty(10))
  479. {
  480. def->ldapName = SysAllocString(dnary.getBSTR(10));
  481. }
  482. else
  483. {
  484. def->ldapName = SysAllocString(def->name);
  485. }
  486. if (!def->ldapName) { throw bad_alloc(); }
  487. // Get the enumeration SAFEARRAYs.
  488. if (!dnary.isEmpty(11))
  489. {
  490. hr = SafeArrayCopy(
  491. V_ARRAY(dnary.getVariant(11)),
  492. &def->enumNames
  493. );
  494. if (FAILED(hr)) { _com_issue_error(hr); }
  495. }
  496. if (!dnary.isEmpty(12))
  497. {
  498. hr = SafeArrayCopy(
  499. V_ARRAY(dnary.getVariant(12)),
  500. &def->enumValues
  501. );
  502. if (FAILED(hr)) { _com_issue_error(hr); }
  503. }
  504. // Add this to the entries vector.
  505. defs.push_back(def);
  506. // We've safely stored the attribute, so detach.
  507. *(&def) = NULL;
  508. }
  509. // Allocate the permanent arrays.
  510. size = defs.size();
  511. byId = new const AttributeDefinition*[size];
  512. byName = new const AttributeDefinition*[size];
  513. byLdapName = new const AttributeDefinition*[size];
  514. // Fill in the arrays.
  515. size_t nbyte = size * sizeof(AttributeDefinition*);
  516. memcpy(byId, defs.begin(), nbyte);
  517. memcpy(byName, defs.begin(), nbyte);
  518. memcpy(byLdapName, defs.begin(), nbyte);
  519. // Sort the arrays.
  520. qsort(
  521. byId,
  522. size,
  523. sizeof(AttributeDefinition*),
  524. (CompFn)AttributeDefinition::sortById
  525. );
  526. qsort(
  527. byName,
  528. size,
  529. sizeof(AttributeDefinition*),
  530. (CompFn)AttributeDefinition::sortByName
  531. );
  532. qsort(
  533. byLdapName,
  534. size,
  535. sizeof(AttributeDefinition*),
  536. (CompFn)AttributeDefinition::sortByLdapName
  537. );
  538. }
  539. catch (const _com_error& ce)
  540. {
  541. hr = ce.Error();
  542. }
  543. catch (const std::bad_alloc&)
  544. {
  545. hr = E_OUTOFMEMORY;
  546. }
  547. catch (...)
  548. {
  549. hr = DISP_E_EXCEPTION;
  550. }
  551. if (FAILED(hr))
  552. {
  553. vector<const AttributeDefinition*>::iterator i;
  554. for (i = defs.begin(); i != defs.end(); ++i)
  555. {
  556. if (*i) { (*i)->Release(); }
  557. }
  558. delete[] byId;
  559. delete[] byName;
  560. delete[] byLdapName;
  561. size = 0;
  562. }
  563. return hr;
  564. }