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.

1192 lines
26 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // sdowrap.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines various wrapper classes for manipulating SDOs.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 02/10/2000 Original version.
  16. // 04/19/2000 Support for using wrappers across apartment boundaries.
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #include <proxypch.h>
  20. #include <sdowrap.h>
  21. #include <condlist.h>
  22. #include <iaslimits.h>
  23. VOID
  24. WINAPI
  25. SdoTrimBSTR(
  26. CComBSTR& bstr
  27. )
  28. {
  29. // Characters to be trimmed.
  30. static const WCHAR delim[] = L" \t\n";
  31. if (bstr.m_str)
  32. {
  33. PCWSTR begin, end, first, last;
  34. // Find the beginning and end of the whole string.
  35. begin = bstr;
  36. end = begin + wcslen(begin);
  37. // Find the first and last character of the trimmed string.
  38. first = begin + wcsspn(begin, delim);
  39. for (last = end; last > first && wcschr(delim, *(last - 1)); --last) { }
  40. // If they're not the same ...
  41. if (first != begin || last != end)
  42. {
  43. // ... then we have to allocate a new string ...
  44. BSTR newBstr = SysAllocStringLen(first, last - first);
  45. if (!newBstr) { AfxThrowOleException(E_OUTOFMEMORY); }
  46. // ... and replace the original.
  47. SysFreeString(bstr.m_str);
  48. bstr.m_str = newBstr;
  49. }
  50. }
  51. }
  52. BOOL SdoException::GetErrorMessage(
  53. LPWSTR lpszError,
  54. UINT nMaxError,
  55. PUINT pnHelpContext
  56. )
  57. {
  58. UINT id;
  59. switch (type)
  60. {
  61. case CONNECT_ERROR:
  62. id = IDS_PROXY_E_SDO_CONNECT;
  63. break;
  64. case READ_ERROR:
  65. id = IDS_PROXY_E_SDO_READ;
  66. break;
  67. default:
  68. id = IDS_PROXY_E_SDO_WRITE;
  69. }
  70. return LoadStringW(
  71. AfxGetResourceHandle(),
  72. id,
  73. lpszError,
  74. nMaxError
  75. );
  76. }
  77. inline SdoException::SdoException(HRESULT hr, Type errorType) throw ()
  78. : type(errorType)
  79. {
  80. m_sc = hr;
  81. }
  82. VOID
  83. WINAPI
  84. SdoThrowException(
  85. HRESULT hr,
  86. SdoException::Type errorType
  87. )
  88. {
  89. throw new SdoException(hr, errorType);
  90. }
  91. // Extract an interface pointer from a VARIANT.
  92. void ExtractInterface(const VARIANT& v, REFIID iid, PVOID* intfc)
  93. {
  94. if (V_VT(&v) != VT_UNKNOWN && V_VT(&v) != VT_DISPATCH)
  95. {
  96. AfxThrowOleException(DISP_E_TYPEMISMATCH);
  97. }
  98. if (!V_UNKNOWN(&v))
  99. {
  100. AfxThrowOleException(E_POINTER);
  101. }
  102. CheckError(V_UNKNOWN(&v)->QueryInterface(iid, intfc));
  103. }
  104. Sdo::Sdo(IUnknown* unk)
  105. {
  106. if (unk)
  107. {
  108. CheckError(unk->QueryInterface(__uuidof(ISdo), (PVOID*)&self));
  109. }
  110. }
  111. bool Sdo::setName(BSTR value)
  112. {
  113. if (!self) { AfxThrowOleException(E_POINTER); }
  114. bool retval;
  115. VARIANT v;
  116. V_VT(&v) = VT_BSTR;
  117. V_BSTR(&v) = value;
  118. HRESULT hr = self->PutProperty(PROPERTY_SDO_NAME, &v);
  119. if (SUCCEEDED(hr))
  120. {
  121. retval = true;
  122. }
  123. else if (hr == E_INVALIDARG && value && value[0])
  124. {
  125. retval = false;
  126. }
  127. else
  128. {
  129. AfxThrowOleException(hr);
  130. }
  131. return retval;
  132. }
  133. void Sdo::clearValue(LONG id)
  134. {
  135. if (!self) { AfxThrowOleException(E_POINTER); }
  136. VARIANT v;
  137. V_VT(&v) = VT_EMPTY;
  138. HRESULT hr = self->PutProperty(id, &v);
  139. if (FAILED(hr) && hr != DISP_E_MEMBERNOTFOUND)
  140. {
  141. AfxThrowOleException(hr);
  142. }
  143. }
  144. void Sdo::getValue(LONG id, bool& value) const
  145. {
  146. VARIANT v;
  147. getValue(id, VT_BOOL, &v, true);
  148. value = (V_BOOL(&v) != 0);
  149. }
  150. void Sdo::getValue(LONG id, bool& value, bool defVal) const
  151. {
  152. VARIANT v;
  153. if (getValue(id, VT_BOOL, &v, false))
  154. {
  155. value = (V_BOOL(&v) != 0);
  156. }
  157. else
  158. {
  159. value = defVal;
  160. }
  161. }
  162. void Sdo::getValue(LONG id, LONG& value) const
  163. {
  164. VARIANT v;
  165. getValue(id, VT_I4, &v, true);
  166. value = V_UI4(&v);
  167. }
  168. void Sdo::getValue(LONG id, LONG& value, LONG defVal) const
  169. {
  170. VARIANT v;
  171. if (getValue(id, VT_I4, &v, false))
  172. {
  173. value = V_UI4(&v);
  174. }
  175. else
  176. {
  177. value = defVal;
  178. }
  179. }
  180. void Sdo::getValue(LONG id, CComBSTR& value) const
  181. {
  182. VARIANT v;
  183. getValue(id, VT_BSTR, &v, true);
  184. SysFreeString(value.m_str);
  185. value.m_str = V_BSTR(&v);
  186. }
  187. void Sdo::getValue(LONG id, CComBSTR& value, PCWSTR defVal) const
  188. {
  189. VARIANT v;
  190. if (getValue(id, VT_BSTR, &v, false))
  191. {
  192. SysFreeString(value.m_str);
  193. value.m_str = V_BSTR(&v);
  194. }
  195. else
  196. {
  197. value = defVal;
  198. if (defVal && !value) { AfxThrowOleException(E_OUTOFMEMORY); }
  199. }
  200. }
  201. void Sdo::getValue(LONG id, VARIANT& value) const
  202. {
  203. if (!self) { AfxThrowOleException(E_POINTER); }
  204. VariantClear(&value);
  205. CheckError(self->GetProperty(id, &value));
  206. }
  207. void Sdo::getValue(LONG id, SdoCollection& value) const
  208. {
  209. if (!self) { AfxThrowOleException(E_POINTER); }
  210. CComVariant v;
  211. HRESULT hr = self->GetProperty(id, &v);
  212. if (FAILED(hr))
  213. {
  214. switch (hr)
  215. {
  216. case DISP_E_MEMBERNOTFOUND:
  217. case E_OUTOFMEMORY:
  218. AfxThrowOleException(hr);
  219. default:
  220. SdoThrowException(hr, SdoException::READ_ERROR);
  221. }
  222. }
  223. CComPtr<ISdoCollection> obj;
  224. ExtractInterface(v, __uuidof(ISdoCollection), (PVOID*)&obj);
  225. value = obj;
  226. }
  227. void Sdo::setValue(LONG id, bool value)
  228. {
  229. VARIANT v;
  230. V_VT(&v) = VT_BOOL;
  231. V_BOOL(&v) = value ? VARIANT_TRUE : VARIANT_FALSE;
  232. setValue(id, v);
  233. }
  234. void Sdo::setValue(LONG id, LONG value)
  235. {
  236. VARIANT v;
  237. V_VT(&v) = VT_I4;
  238. V_I4(&v) = value;
  239. setValue(id, v);
  240. }
  241. void Sdo::setValue(LONG id, BSTR value)
  242. {
  243. VARIANT v;
  244. V_VT(&v) = VT_BSTR;
  245. V_BSTR(&v) = value;
  246. setValue(id, v);
  247. }
  248. void Sdo::setValue(LONG id, const VARIANT& val)
  249. {
  250. if (!self) { AfxThrowOleException(E_POINTER); }
  251. CheckError(self->PutProperty(id, const_cast<VARIANT*>(&val)));
  252. }
  253. void Sdo::apply()
  254. {
  255. if (!self) { AfxThrowOleException(E_POINTER); }
  256. HRESULT hr = self->Apply();
  257. if (FAILED(hr))
  258. {
  259. switch (hr)
  260. {
  261. case E_OUTOFMEMORY:
  262. AfxThrowOleException(hr);
  263. default:
  264. SdoThrowException(hr, SdoException::WRITE_ERROR);
  265. }
  266. }
  267. }
  268. void Sdo::restore()
  269. {
  270. if (!self) { AfxThrowOleException(E_POINTER); }
  271. CheckError(self->Restore());
  272. }
  273. bool Sdo::getValue(LONG id, VARTYPE vt, VARIANT* val, bool mandatory) const
  274. {
  275. if (!self) { AfxThrowOleException(E_POINTER); }
  276. V_VT(val) = VT_EMPTY;
  277. HRESULT hr = self->GetProperty(id, val);
  278. if (SUCCEEDED(hr))
  279. {
  280. if (V_VT(val) == VT_EMPTY)
  281. {
  282. if (mandatory)
  283. {
  284. AfxThrowOleException(DISP_E_MEMBERNOTFOUND);
  285. }
  286. }
  287. else if (V_VT(val) != vt)
  288. {
  289. VariantClear(val);
  290. AfxThrowOleException(DISP_E_TYPEMISMATCH);
  291. }
  292. else
  293. {
  294. return true;
  295. }
  296. }
  297. else if (hr == DISP_E_MEMBERNOTFOUND)
  298. {
  299. if (mandatory)
  300. {
  301. AfxThrowOleException(DISP_E_MEMBERNOTFOUND);
  302. }
  303. }
  304. else
  305. {
  306. AfxThrowOleException(hr);
  307. }
  308. return false;
  309. }
  310. SdoEnum::SdoEnum(IUnknown* unk)
  311. {
  312. if (unk)
  313. {
  314. CheckError(unk->QueryInterface(__uuidof(IEnumVARIANT), (PVOID*)&self));
  315. }
  316. }
  317. bool SdoEnum::next(Sdo& s)
  318. {
  319. if (!self) { AfxThrowOleException(E_POINTER); }
  320. CComVariant element;
  321. ULONG fetched;
  322. HRESULT hr = self->Next(1, &element, &fetched);
  323. if (hr == S_OK && fetched)
  324. {
  325. CComPtr<ISdo> obj;
  326. ExtractInterface(element, __uuidof(ISdo), (PVOID*)&obj);
  327. s = obj;
  328. return true;
  329. }
  330. CheckError(hr);
  331. return false;
  332. }
  333. void SdoEnum::reset()
  334. {
  335. if (!self) { AfxThrowOleException(E_POINTER); }
  336. CheckError(self->Reset());
  337. }
  338. SdoCollection::SdoCollection(IUnknown* unk)
  339. {
  340. if (unk)
  341. {
  342. CheckError(unk->QueryInterface(__uuidof(ISdoCollection), (PVOID*)&self));
  343. }
  344. }
  345. void SdoCollection::add(ISdo* sdo)
  346. {
  347. if (!self) { AfxThrowOleException(E_POINTER); }
  348. // We must hold a reference across the call to Add since the interface
  349. // pointer passed to Add is an [in, out] parameter.
  350. CComPtr<IDispatch> disp(sdo);
  351. CheckError(self->Add(NULL, &disp));
  352. }
  353. LONG SdoCollection::count() throw ()
  354. {
  355. if (!self) { AfxThrowOleException(E_POINTER); }
  356. LONG retval;
  357. CheckError(self->get_Count(&retval));
  358. return retval;
  359. }
  360. Sdo SdoCollection::create(BSTR name)
  361. {
  362. Sdo newObj = tryCreate(name);
  363. if (!newObj)
  364. {
  365. AfxThrowOleException(IAS_E_LICENSE_VIOLATION);
  366. }
  367. return newObj;
  368. }
  369. Sdo SdoCollection::tryCreate(BSTR name)
  370. {
  371. if (!self) { AfxThrowOleException(E_POINTER); }
  372. CComBSTR tmp;
  373. // If no name is specified, we'll make use a GUID.
  374. if (!name)
  375. {
  376. // Create the GUID.
  377. UUID uuid;
  378. UuidCreate(&uuid);
  379. // Convert to a string.
  380. WCHAR buffer[40];
  381. StringFromGUID2(uuid, buffer, sizeof(buffer)/sizeof(buffer[0]));
  382. // Convert the string to a BSTR.
  383. name = tmp = buffer;
  384. if (!name) { AfxThrowOleException(E_OUTOFMEMORY); }
  385. }
  386. CComPtr<IDispatch> disp;
  387. HRESULT hr = self->Add(name, &disp);
  388. if (FAILED(hr) && (hr != IAS_E_LICENSE_VIOLATION))
  389. {
  390. AfxThrowOleException(hr);
  391. }
  392. return Sdo(disp);
  393. }
  394. Sdo SdoCollection::find(BSTR name)
  395. {
  396. if (!self) { AfxThrowOleException(E_POINTER); }
  397. VARIANT v;
  398. V_VT(&v) = VT_BSTR;
  399. V_BSTR(&v) = name;
  400. CComPtr<IDispatch> disp;
  401. HRESULT hr = self->Item(&v, &disp);
  402. if (FAILED(hr) && hr != DISP_E_MEMBERNOTFOUND)
  403. {
  404. AfxThrowOleException(hr);
  405. }
  406. return Sdo(disp);
  407. }
  408. SdoEnum SdoCollection::getNewEnum()
  409. {
  410. if (!self) { AfxThrowOleException(E_POINTER); }
  411. CComPtr<IUnknown> unk;
  412. CheckError(self->get__NewEnum(&unk));
  413. return SdoEnum(unk);
  414. }
  415. bool SdoCollection::isNameUnique(BSTR name)
  416. {
  417. if (!self) { AfxThrowOleException(E_POINTER); }
  418. VARIANT_BOOL retval;
  419. CheckError(self->IsNameUnique(name, &retval));
  420. return retval != 0;
  421. }
  422. void SdoCollection::reload()
  423. {
  424. if (self)
  425. {
  426. HRESULT hr = self->Reload();
  427. if (FAILED(hr))
  428. {
  429. switch (hr)
  430. {
  431. case DISP_E_MEMBERNOTFOUND:
  432. case E_OUTOFMEMORY:
  433. AfxThrowOleException(hr);
  434. default:
  435. SdoThrowException(hr, SdoException::READ_ERROR);
  436. }
  437. }
  438. }
  439. }
  440. void SdoCollection::remove(ISdo* sdo)
  441. {
  442. if (!self) { AfxThrowOleException(E_POINTER); }
  443. HRESULT hr = self->Remove(sdo);
  444. if (FAILED(hr))
  445. {
  446. switch (hr)
  447. {
  448. case DISP_E_MEMBERNOTFOUND:
  449. case E_OUTOFMEMORY:
  450. AfxThrowOleException(hr);
  451. default:
  452. SdoThrowException(hr, SdoException::WRITE_ERROR);
  453. }
  454. }
  455. }
  456. void SdoCollection::removeAll()
  457. {
  458. if (!self) { AfxThrowOleException(E_POINTER); }
  459. HRESULT hr = self->RemoveAll();
  460. if (FAILED(hr))
  461. {
  462. switch (hr)
  463. {
  464. case E_OUTOFMEMORY:
  465. AfxThrowOleException(hr);
  466. default:
  467. SdoThrowException(hr, SdoException::WRITE_ERROR);
  468. }
  469. }
  470. }
  471. SdoDictionary::SdoDictionary(IUnknown* unk)
  472. {
  473. if (unk)
  474. {
  475. CheckError(unk->QueryInterface(
  476. __uuidof(ISdoDictionaryOld),
  477. (PVOID*)&self
  478. ));
  479. }
  480. }
  481. Sdo SdoDictionary::createAttribute(ATTRIBUTEID id) const
  482. {
  483. if (!self) { AfxThrowOleException(E_POINTER); }
  484. CComPtr<IDispatch> disp;
  485. CheckError(self->CreateAttribute(id, &disp));
  486. return Sdo(disp);
  487. }
  488. ULONG SdoDictionary::enumAttributeValues(ATTRIBUTEID attrId, IdName*& values)
  489. {
  490. if (!self) { AfxThrowOleException(E_POINTER); }
  491. // Get the variant arrays.
  492. CComVariant v1, v2;
  493. CheckError(self->EnumAttributeValues(attrId, &v1, &v2));
  494. // Allocate memory for the 'friendly' array.
  495. ULONG nelem = V_ARRAY(&v1)->rgsabound[0].cElements;
  496. IdName* vals = new (AfxThrow) IdName[nelem];
  497. // Get the raw data.
  498. VARIANT* id = (VARIANT*)V_ARRAY(&v1)->pvData;
  499. VARIANT* name = (VARIANT*)V_ARRAY(&v2)->pvData;
  500. // Copy the variant data into the friendly array.
  501. for (ULONG i = 0; i < nelem; ++i, ++id, ++name)
  502. {
  503. vals[i].id = V_I4(id);
  504. vals[i].name = V_BSTR(name);
  505. if (!vals[i].name)
  506. {
  507. delete[] vals;
  508. AfxThrowOleException(E_OUTOFMEMORY);
  509. }
  510. }
  511. values = vals;
  512. return nelem;
  513. }
  514. SdoMachine::SdoMachine(IUnknown* unk)
  515. {
  516. if (unk)
  517. {
  518. CheckError(unk->QueryInterface(__uuidof(ISdoMachine), (PVOID*)&self));
  519. }
  520. }
  521. void SdoMachine::attach(BSTR machineName)
  522. {
  523. if (!self) { create(); }
  524. if (machineName && !machineName[0]) { machineName = NULL; }
  525. HRESULT hr = self->Attach(machineName);
  526. if (FAILED(hr))
  527. {
  528. switch (hr)
  529. {
  530. case E_OUTOFMEMORY:
  531. AfxThrowOleException(hr);
  532. default:
  533. SdoThrowException(hr, SdoException::CONNECT_ERROR);
  534. }
  535. }
  536. }
  537. void SdoMachine::create()
  538. {
  539. self.Release();
  540. CheckError(CoCreateInstance(
  541. __uuidof(SdoMachine),
  542. NULL,
  543. CLSCTX_INPROC_SERVER,
  544. __uuidof(ISdoMachine),
  545. (PVOID*)&self
  546. ));
  547. }
  548. Sdo SdoMachine::getIAS()
  549. {
  550. if (!self) { AfxThrowOleException(E_POINTER); }
  551. // Get the service SDO.
  552. CComPtr<IUnknown> unk;
  553. CComBSTR serviceName(L"IAS");
  554. if (!serviceName) { AfxThrowOleException(E_OUTOFMEMORY); }
  555. HRESULT hr = self->GetServiceSDO(
  556. DATA_STORE_LOCAL,
  557. serviceName,
  558. &unk
  559. );
  560. if (FAILED(hr))
  561. {
  562. switch (hr)
  563. {
  564. case E_OUTOFMEMORY:
  565. AfxThrowOleException(hr);
  566. default:
  567. SdoThrowException(hr, SdoException::CONNECT_ERROR);
  568. }
  569. }
  570. return Sdo(unk);
  571. }
  572. SdoDictionary SdoMachine::getDictionary()
  573. {
  574. if (!self) { AfxThrowOleException(E_POINTER); }
  575. // Get the dictionary SDO.
  576. CComPtr<IUnknown> unk;
  577. HRESULT hr = self->GetDictionarySDO(&unk);
  578. if (FAILED(hr))
  579. {
  580. switch (hr)
  581. {
  582. case E_OUTOFMEMORY:
  583. AfxThrowOleException(hr);
  584. default:
  585. SdoThrowException(hr, SdoException::CONNECT_ERROR);
  586. }
  587. }
  588. return SdoDictionary(unk);
  589. }
  590. void SdoConsumer::propertyChanged(SnapInView& view, IASPROPERTIES id)
  591. { }
  592. bool SdoConsumer::queryRefresh(SnapInView& view)
  593. { return true; }
  594. void SdoConsumer::refreshComplete(SnapInView& view)
  595. { }
  596. SdoConnection::SdoConnection() throw ()
  597. : dictionary(0),
  598. service(0),
  599. control(0),
  600. attrList(NULL)
  601. { }
  602. SdoConnection::~SdoConnection() throw ()
  603. {
  604. executeInMTA(mtaDisconnect);
  605. }
  606. void SdoConnection::advise(SdoConsumer& obj)
  607. {
  608. consumers.Add(&obj);
  609. }
  610. void SdoConnection::unadvise(SdoConsumer& obj)
  611. {
  612. for (int i = 0; i < consumers.GetSize(); ++i)
  613. {
  614. if (consumers[i] == &obj)
  615. {
  616. consumers.RemoveAt(i);
  617. break;
  618. }
  619. }
  620. }
  621. SdoDictionary SdoConnection::getDictionary()
  622. {
  623. if (!dictionary) { AfxThrowOleException(E_POINTER); }
  624. CComPtr<ISdoDictionaryOld> obj;
  625. CheckError(git->GetInterfaceFromGlobal(
  626. dictionary,
  627. __uuidof(ISdoDictionaryOld),
  628. (PVOID*)&obj
  629. ));
  630. return SdoDictionary(obj);
  631. }
  632. SdoCollection SdoConnection::getProxyPolicies()
  633. {
  634. SdoCollection retval;
  635. getService().getValue(
  636. PROPERTY_IAS_PROXYPOLICIES_COLLECTION,
  637. retval
  638. );
  639. return retval;
  640. }
  641. SdoCollection SdoConnection::getProxyProfiles()
  642. {
  643. SdoCollection retval;
  644. getService().getValue(
  645. PROPERTY_IAS_PROXYPROFILES_COLLECTION,
  646. retval
  647. );
  648. return retval;
  649. }
  650. SdoCollection SdoConnection::getServerGroups()
  651. {
  652. SdoCollection retval;
  653. getService().getValue(
  654. PROPERTY_IAS_RADIUSSERVERGROUPS_COLLECTION,
  655. retval
  656. );
  657. return retval;
  658. }
  659. void SdoConnection::connect(PCWSTR computerName)
  660. {
  661. if (machine) { AfxThrowOleException(E_UNEXPECTED); }
  662. machineName = computerName;
  663. if (computerName && !machineName)
  664. {
  665. AfxThrowOleException(E_OUTOFMEMORY);
  666. }
  667. executeInMTA(mtaConnect);
  668. }
  669. void SdoConnection::propertyChanged(SnapInView& view, IASPROPERTIES id)
  670. {
  671. for (int i = 0; i < consumers.GetSize(); ++i)
  672. {
  673. ((SdoConsumer*)consumers[i])->propertyChanged(view, id);
  674. }
  675. }
  676. bool SdoConnection::refresh(SnapInView& view)
  677. {
  678. int i;
  679. // Make sure the refresh is okay.
  680. for (i = 0; i < consumers.GetSize(); ++i)
  681. {
  682. if (!((SdoConsumer*)consumers[i])->queryRefresh(view))
  683. {
  684. return false;
  685. }
  686. }
  687. // Get a new connection.
  688. executeInMTA(mtaRefresh);
  689. // Let the consumers know we've refreshed.
  690. for (i = 0; i < consumers.GetSize(); ++i)
  691. {
  692. ((SdoConsumer*)consumers[i])->refreshComplete(view);
  693. }
  694. return true;
  695. }
  696. void SdoConnection::resetService()
  697. {
  698. if (!control) { AfxThrowOleException(E_POINTER); }
  699. CComPtr<ISdoServiceControl> obj;
  700. CheckError(git->GetInterfaceFromGlobal(
  701. control,
  702. __uuidof(ISdoServiceControl),
  703. (PVOID*)&obj
  704. ));
  705. // We ignore the error code since the SDOs return an error when the service
  706. // isn't running.
  707. obj->ResetService();
  708. }
  709. CIASAttrList* SdoConnection::getCIASAttrList()
  710. {
  711. if (!attrList)
  712. {
  713. attrList = CreateCIASAttrList();
  714. if (!attrList) { AfxThrowOleException(E_OUTOFMEMORY); }
  715. }
  716. return attrList;
  717. }
  718. Sdo SdoConnection::getService()
  719. {
  720. if (!service) { AfxThrowOleException(E_POINTER); }
  721. CComPtr<ISdo> obj;
  722. CheckError(git->GetInterfaceFromGlobal(
  723. service,
  724. __uuidof(ISdo),
  725. (PVOID*)&obj
  726. ));
  727. return Sdo(obj);
  728. }
  729. void SdoConnection::mtaConnect()
  730. {
  731. // Get the GIT.
  732. CheckError(CoCreateInstance(
  733. CLSID_StdGlobalInterfaceTable,
  734. NULL,
  735. CLSCTX_INPROC_SERVER,
  736. __uuidof(IGlobalInterfaceTable),
  737. (PVOID*)&git
  738. ));
  739. // Attach to the machine.
  740. machine.attach(machineName);
  741. // Get the dictionary SDO.
  742. CheckError(git->RegisterInterfaceInGlobal(
  743. machine.getDictionary(),
  744. __uuidof(ISdoDictionaryOld),
  745. &dictionary
  746. ));
  747. // Get the service SDO.
  748. Sdo serviceSdo = machine.getIAS();
  749. CheckError(git->RegisterInterfaceInGlobal(
  750. serviceSdo,
  751. __uuidof(ISdo),
  752. &service
  753. ));
  754. // Get the control SDO.
  755. CComPtr<ISdoServiceControl> controlSdo;
  756. CheckError(serviceSdo.self->QueryInterface(
  757. __uuidof(ISdoServiceControl),
  758. (PVOID*)&controlSdo
  759. ));
  760. CheckError(git->RegisterInterfaceInGlobal(
  761. controlSdo,
  762. __uuidof(ISdoServiceControl),
  763. &control
  764. ));
  765. }
  766. void SdoConnection::mtaDisconnect()
  767. {
  768. // Revoke all the GIT cookies.
  769. if (git)
  770. {
  771. if (dictionary) { git->RevokeInterfaceFromGlobal(dictionary); }
  772. if (service) { git->RevokeInterfaceFromGlobal(service); }
  773. if (control) { git->RevokeInterfaceFromGlobal(control); }
  774. git.Release();
  775. }
  776. DestroyCIASAttrList(attrList);
  777. // Drop the connection.
  778. machine.release();
  779. }
  780. void SdoConnection::mtaRefresh()
  781. {
  782. // Revoke the old connection.
  783. if (service)
  784. {
  785. git->RevokeInterfaceFromGlobal(service);
  786. service = 0;
  787. }
  788. // Get a new connection.
  789. CheckError(git->RegisterInterfaceInGlobal(
  790. machine.getIAS(),
  791. __uuidof(ISdo),
  792. &service
  793. ));
  794. }
  795. namespace
  796. {
  797. // Struct to store the data for an MTA action.
  798. struct ActionData
  799. {
  800. SdoConnection* cxn;
  801. SdoConnection::Action action;
  802. };
  803. };
  804. void SdoConnection::executeInMTA(Action action)
  805. {
  806. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  807. if (SUCCEEDED(hr))
  808. {
  809. // We're already in the MTA, so execute in place.
  810. (this->*action)();
  811. CoUninitialize();
  812. }
  813. else
  814. {
  815. // Save the action data.
  816. ActionData data = { this, action };
  817. // Create a thread to perform the action.
  818. HANDLE thread = CreateThread(
  819. NULL,
  820. 0,
  821. actionRoutine,
  822. &data,
  823. 0,
  824. NULL
  825. );
  826. // Wait for the thread to exit and retrieve the exit code.
  827. DWORD exitCode;
  828. if (!thread ||
  829. WaitForSingleObject(thread, INFINITE) == WAIT_FAILED ||
  830. !GetExitCodeThread(thread, &exitCode))
  831. {
  832. exitCode = GetLastError();
  833. hr = HRESULT_FROM_WIN32(exitCode);
  834. }
  835. else
  836. {
  837. hr = (HRESULT)exitCode;
  838. }
  839. CloseHandle(thread);
  840. CheckError(hr);
  841. }
  842. }
  843. DWORD WINAPI SdoConnection::actionRoutine(PVOID parameter) throw ()
  844. {
  845. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  846. if (SUCCEEDED(hr))
  847. {
  848. ActionData* data = (ActionData*)parameter;
  849. try
  850. {
  851. ((data->cxn)->*(data->action))();
  852. hr = S_OK;
  853. }
  854. catch (CException* e)
  855. {
  856. hr = COleException::Process(e);
  857. e->Delete();
  858. }
  859. CoUninitialize();
  860. }
  861. return (DWORD)hr;
  862. }
  863. SdoProfile::SdoProfile(SdoConnection& connection)
  864. : cxn(connection)
  865. {
  866. }
  867. SdoProfile::SdoProfile(SdoConnection& connection, Sdo& profile)
  868. : cxn(connection)
  869. {
  870. operator=(profile);
  871. }
  872. SdoProfile& SdoProfile::operator=(Sdo& profile)
  873. {
  874. if (!profile) { AfxThrowOleException(E_POINTER); }
  875. // Get the new attributes collection.
  876. SdoCollection newSelf;
  877. profile.getValue(PROPERTY_PROFILE_ATTRIBUTES_COLLECTION, newSelf);
  878. return operator=(newSelf);
  879. }
  880. SdoProfile& SdoProfile::operator=(ISdoCollection* p)
  881. {
  882. if (!p) { AfxThrowOleException(E_POINTER); }
  883. SdoCollection newSelf(p);
  884. // Create a temporary vector to hold the attributes.
  885. SdoVector newAttrs;
  886. newAttrs.reserve(newSelf.count());
  887. // Get the attributes.
  888. Sdo attr;
  889. SdoEnum sdoEnum(newSelf.getNewEnum());
  890. while (sdoEnum.next(attr))
  891. {
  892. newAttrs.push_back(attr);
  893. }
  894. // Store the results.
  895. attrs.swap(newAttrs);
  896. self = newSelf;
  897. return *this;
  898. }
  899. void SdoProfile::clear()
  900. {
  901. self.removeAll();
  902. attrs.clear();
  903. }
  904. Sdo SdoProfile::find(ATTRIBUTEID id) const
  905. {
  906. return getExisting(id);
  907. }
  908. void SdoProfile::clearValue(ATTRIBUTEID id)
  909. {
  910. ISdo* sdo = getExisting(id);
  911. if (sdo)
  912. {
  913. self.remove(sdo);
  914. attrs.erase(sdo);
  915. }
  916. }
  917. bool SdoProfile::getValue(ATTRIBUTEID id, bool& value) const
  918. {
  919. Sdo sdo(getExisting(id));
  920. return sdo ? sdo.getValue(PROPERTY_ATTRIBUTE_VALUE, value), true : false;
  921. }
  922. bool SdoProfile::getValue(ATTRIBUTEID id, LONG& value) const
  923. {
  924. Sdo sdo(getExisting(id));
  925. return sdo ? sdo.getValue(PROPERTY_ATTRIBUTE_VALUE, value), true : false;
  926. }
  927. bool SdoProfile::getValue(ATTRIBUTEID id, CComBSTR& value) const
  928. {
  929. Sdo sdo(getExisting(id));
  930. return sdo ? sdo.getValue(PROPERTY_ATTRIBUTE_VALUE, value), true : false;
  931. }
  932. bool SdoProfile::getValue(ATTRIBUTEID id, VARIANT& value) const
  933. {
  934. Sdo sdo(getExisting(id));
  935. return sdo ? sdo.getValue(PROPERTY_ATTRIBUTE_VALUE, value), true : false;
  936. }
  937. void SdoProfile::setValue(ATTRIBUTEID id, bool value)
  938. {
  939. Sdo(getAlways(id)).setValue(PROPERTY_ATTRIBUTE_VALUE, value);
  940. }
  941. void SdoProfile::setValue(ATTRIBUTEID id, LONG value)
  942. {
  943. Sdo(getAlways(id)).setValue(PROPERTY_ATTRIBUTE_VALUE, value);
  944. }
  945. void SdoProfile::setValue(ATTRIBUTEID id, BSTR value)
  946. {
  947. Sdo(getAlways(id)).setValue(PROPERTY_ATTRIBUTE_VALUE, value);
  948. }
  949. void SdoProfile::setValue(ATTRIBUTEID id, const VARIANT& val)
  950. {
  951. Sdo(getAlways(id)).setValue(PROPERTY_ATTRIBUTE_VALUE, val);
  952. }
  953. ISdo* SdoProfile::getAlways(ATTRIBUTEID id)
  954. {
  955. // Does it already exist ?
  956. ISdo* sdo = getExisting(id);
  957. if (sdo) { return sdo; }
  958. // No, so create a new one
  959. Sdo attr = cxn.getDictionary().createAttribute(id);
  960. self.add(attr);
  961. attrs.push_back(attr);
  962. return attr;
  963. }
  964. ISdo* SdoProfile::getExisting(ATTRIBUTEID key) const
  965. {
  966. // Iterate through the attributes.
  967. for (SdoVector::iterator i = attrs.begin(); i != attrs.end(); ++i)
  968. {
  969. // Get the attribute ID.
  970. LONG id;
  971. Sdo(*i).getValue(PROPERTY_ATTRIBUTE_ID, id);
  972. // Does it match the key ?
  973. if (id == key) { return *i; }
  974. }
  975. return NULL;
  976. }
  977. void InterfaceStream::marshal(REFIID riid, LPUNKNOWN pUnk)
  978. {
  979. // Create the new stream.
  980. CComPtr<IStream> newStream;
  981. CheckError(CoMarshalInterThreadInterfaceInStream(
  982. riid,
  983. pUnk,
  984. &newStream
  985. ));
  986. // Release the old one if any.
  987. if (stream) { stream->Release(); }
  988. // Save the new one.
  989. stream = newStream.p;
  990. newStream.p = NULL;
  991. }
  992. void InterfaceStream::get(REFIID riid, LPVOID* ppv)
  993. {
  994. // Unmarshall the interface.
  995. HRESULT hr = CoGetInterfaceAndReleaseStream(
  996. stream,
  997. riid,
  998. ppv
  999. );
  1000. // The stream can only be used once even if the above fails.
  1001. stream = NULL;
  1002. // Check the result of CoGetInterfaceAndReleaseStream.
  1003. CheckError(hr);
  1004. }