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.

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