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.

912 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 2000
  5. //
  6. // File: H N A P P P R T . C P P
  7. //
  8. // Contents: CHNetAppProtocol Implementation
  9. //
  10. // Notes:
  11. //
  12. // Author: jonburs 21 June 2000
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. //
  18. // ATL methods
  19. //
  20. HRESULT
  21. CHNetAppProtocol::FinalRelease()
  22. {
  23. if (m_piwsHomenet) m_piwsHomenet->Release();
  24. if (m_bstrProtocol) SysFreeString(m_bstrProtocol);
  25. return S_OK;
  26. }
  27. //
  28. // Object initialization
  29. //
  30. HRESULT
  31. CHNetAppProtocol::Initialize(
  32. IWbemServices *piwsNamespace,
  33. IWbemClassObject *pwcoInstance
  34. )
  35. {
  36. HRESULT hr = S_OK;
  37. _ASSERT(NULL == m_piwsHomenet);
  38. _ASSERT(NULL == m_bstrProtocol);
  39. _ASSERT(NULL != piwsNamespace);
  40. _ASSERT(NULL != pwcoInstance);
  41. //
  42. // Read and cache our builtin value
  43. //
  44. hr = GetBooleanValue(
  45. pwcoInstance,
  46. c_wszBuiltIn,
  47. &m_fBuiltIn
  48. );
  49. //
  50. // Store the path to the object
  51. //
  52. if (S_OK == hr)
  53. {
  54. hr = GetWmiPathFromObject(pwcoInstance, &m_bstrProtocol);
  55. }
  56. if (S_OK == hr)
  57. {
  58. m_piwsHomenet = piwsNamespace;
  59. m_piwsHomenet->AddRef();
  60. }
  61. return hr;
  62. }
  63. //
  64. // IHNetApplicationProtocol methods
  65. //
  66. STDMETHODIMP
  67. CHNetAppProtocol::GetName(
  68. OLECHAR **ppszwName
  69. )
  70. {
  71. HRESULT hr = S_OK;
  72. IWbemClassObject *pwcoProtocol;
  73. VARIANT vt;
  74. if (NULL == ppszwName)
  75. {
  76. hr = E_POINTER;
  77. }
  78. if (S_OK == hr)
  79. {
  80. *ppszwName = NULL;
  81. hr = GetProtocolObject(&pwcoProtocol);
  82. }
  83. if (S_OK == hr)
  84. {
  85. //
  86. // Read the name property from our instance
  87. //
  88. hr = pwcoProtocol->Get(
  89. c_wszName,
  90. NULL,
  91. &vt,
  92. NULL,
  93. NULL
  94. );
  95. pwcoProtocol->Release();
  96. }
  97. if (WBEM_S_NO_ERROR == hr)
  98. {
  99. _ASSERT(VT_BSTR == V_VT(&vt));
  100. //
  101. // Allocate memory for the return string
  102. //
  103. *ppszwName = reinterpret_cast<OLECHAR*>(
  104. CoTaskMemAlloc((SysStringLen(V_BSTR(&vt)) + 1)
  105. * sizeof(OLECHAR))
  106. );
  107. if (NULL != *ppszwName)
  108. {
  109. wcscpy(*ppszwName, V_BSTR(&vt));
  110. }
  111. else
  112. {
  113. hr = E_OUTOFMEMORY;
  114. }
  115. VariantClear(&vt);
  116. }
  117. return hr;
  118. }
  119. STDMETHODIMP
  120. CHNetAppProtocol::SetName(
  121. OLECHAR *pszwName
  122. )
  123. {
  124. HRESULT hr = S_OK;
  125. IWbemClassObject *pwcoProtocol;
  126. VARIANT vt;
  127. if (TRUE == m_fBuiltIn)
  128. {
  129. //
  130. // Can't change values for builtin protocols
  131. //
  132. hr = E_ACCESSDENIED;
  133. }
  134. else if (NULL == pszwName)
  135. {
  136. hr = E_INVALIDARG;
  137. }
  138. if (S_OK == hr)
  139. {
  140. hr = GetProtocolObject(&pwcoProtocol);
  141. }
  142. if (WBEM_S_NO_ERROR == hr)
  143. {
  144. //
  145. // Wrap the passed-in string in a BSTR and a variant
  146. //
  147. VariantInit(&vt);
  148. V_VT(&vt) = VT_BSTR;
  149. V_BSTR(&vt) = SysAllocString(pszwName);
  150. if (NULL == V_BSTR(&vt))
  151. {
  152. hr = E_OUTOFMEMORY;
  153. }
  154. if (S_OK == hr)
  155. {
  156. //
  157. // Set the property on the instance
  158. //
  159. hr = pwcoProtocol->Put(
  160. c_wszName,
  161. 0,
  162. &vt,
  163. NULL
  164. );
  165. VariantClear(&vt);
  166. }
  167. if (WBEM_S_NO_ERROR == hr)
  168. {
  169. //
  170. // Write the modified instance to the store
  171. //
  172. hr = m_piwsHomenet->PutInstance(
  173. pwcoProtocol,
  174. WBEM_FLAG_UPDATE_ONLY,
  175. NULL,
  176. NULL
  177. );
  178. }
  179. pwcoProtocol->Release();
  180. }
  181. return hr;
  182. }
  183. STDMETHODIMP
  184. CHNetAppProtocol::GetOutgoingIPProtocol(
  185. UCHAR *pucProtocol
  186. )
  187. {
  188. HRESULT hr = S_OK;
  189. IWbemClassObject *pwcoProtocol;
  190. VARIANT vt;
  191. if (NULL == pucProtocol)
  192. {
  193. hr = E_POINTER;
  194. }
  195. else
  196. {
  197. hr = GetProtocolObject(&pwcoProtocol);
  198. }
  199. if (S_OK == hr)
  200. {
  201. hr = pwcoProtocol->Get(
  202. c_wszOutgoingIPProtocol,
  203. 0,
  204. &vt,
  205. NULL,
  206. NULL
  207. );
  208. pwcoProtocol->Release();
  209. }
  210. if (WBEM_S_NO_ERROR == hr)
  211. {
  212. _ASSERT(VT_UI1 == V_VT(&vt));
  213. *pucProtocol = V_UI1(&vt);
  214. VariantClear(&vt);
  215. }
  216. return hr;
  217. }
  218. STDMETHODIMP
  219. CHNetAppProtocol::SetOutgoingIPProtocol(
  220. UCHAR ucProtocol
  221. )
  222. {
  223. HRESULT hr = S_OK;
  224. IWbemClassObject *pwcoProtocol;
  225. VARIANT vt;
  226. if (TRUE == m_fBuiltIn)
  227. {
  228. //
  229. // Can't change values for builtin protocols
  230. //
  231. hr = E_ACCESSDENIED;
  232. }
  233. else if (0 == ucProtocol)
  234. {
  235. hr = E_INVALIDARG;
  236. }
  237. else
  238. {
  239. BSTR bstrWQL;
  240. USHORT usPort;
  241. //
  242. // Make sure this change doesn't result in a duplicate
  243. //
  244. bstrWQL = SysAllocString(c_wszWQL);
  245. if (NULL != bstrWQL)
  246. {
  247. hr = GetOutgoingPort(&usPort);
  248. if (S_OK == hr)
  249. {
  250. if (ApplicationProtocolExists(
  251. m_piwsHomenet,
  252. bstrWQL,
  253. usPort,
  254. ucProtocol
  255. ))
  256. {
  257. hr = HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS);
  258. }
  259. }
  260. SysFreeString(bstrWQL);
  261. }
  262. else
  263. {
  264. hr = E_OUTOFMEMORY;
  265. }
  266. }
  267. if (S_OK == hr)
  268. {
  269. hr = GetProtocolObject(&pwcoProtocol);
  270. }
  271. if (S_OK == hr)
  272. {
  273. VariantInit(&vt);
  274. V_VT(&vt) = VT_UI1;
  275. V_UI1(&vt) = ucProtocol;
  276. hr = pwcoProtocol->Put(
  277. c_wszOutgoingIPProtocol,
  278. 0,
  279. &vt,
  280. NULL
  281. );
  282. if (WBEM_S_NO_ERROR == hr)
  283. {
  284. //
  285. // Write the modified instance to the store
  286. //
  287. hr = m_piwsHomenet->PutInstance(
  288. pwcoProtocol,
  289. WBEM_FLAG_UPDATE_ONLY,
  290. NULL,
  291. NULL
  292. );
  293. }
  294. pwcoProtocol->Release();
  295. }
  296. return hr;
  297. }
  298. STDMETHODIMP
  299. CHNetAppProtocol::GetOutgoingPort(
  300. USHORT *pusPort
  301. )
  302. {
  303. HRESULT hr = S_OK;
  304. IWbemClassObject *pwcoProtocol;
  305. VARIANT vt;
  306. if (NULL == pusPort)
  307. {
  308. hr = E_POINTER;
  309. }
  310. else
  311. {
  312. hr = GetProtocolObject(&pwcoProtocol);
  313. }
  314. if (S_OK == hr)
  315. {
  316. hr = pwcoProtocol->Get(
  317. c_wszOutgoingPort,
  318. 0,
  319. &vt,
  320. NULL,
  321. NULL
  322. );
  323. pwcoProtocol->Release();
  324. }
  325. if (WBEM_S_NO_ERROR == hr)
  326. {
  327. //
  328. // WMI uses V_I4 for it's uint16 type
  329. //
  330. _ASSERT(VT_I4 == V_VT(&vt));
  331. *pusPort = static_cast<USHORT>(V_I4(&vt));
  332. VariantClear(&vt);
  333. }
  334. return hr;
  335. }
  336. STDMETHODIMP
  337. CHNetAppProtocol::SetOutgoingPort(
  338. USHORT usPort
  339. )
  340. {
  341. HRESULT hr = S_OK;
  342. IWbemClassObject *pwcoProtocol;
  343. VARIANT vt;
  344. if (TRUE == m_fBuiltIn)
  345. {
  346. //
  347. // Can't change values for builtin protocols
  348. //
  349. hr = E_ACCESSDENIED;
  350. }
  351. else if (0 == usPort)
  352. {
  353. hr = E_INVALIDARG;
  354. }
  355. else
  356. {
  357. BSTR bstrWQL;
  358. UCHAR ucProtocol;
  359. //
  360. // Make sure this change doesn't result in a duplicate
  361. //
  362. bstrWQL = SysAllocString(c_wszWQL);
  363. if (NULL != bstrWQL)
  364. {
  365. hr = GetOutgoingIPProtocol(&ucProtocol);
  366. if (S_OK == hr)
  367. {
  368. if (ApplicationProtocolExists(
  369. m_piwsHomenet,
  370. bstrWQL,
  371. usPort,
  372. ucProtocol
  373. ))
  374. {
  375. hr = HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS);
  376. }
  377. }
  378. SysFreeString(bstrWQL);
  379. }
  380. else
  381. {
  382. hr = E_OUTOFMEMORY;
  383. }
  384. }
  385. if (S_OK == hr)
  386. {
  387. hr = GetProtocolObject(&pwcoProtocol);
  388. }
  389. if (S_OK == hr)
  390. {
  391. //
  392. // WMI uses V_I4 for it's uint16 type
  393. //
  394. VariantInit(&vt);
  395. V_VT(&vt) = VT_I4;
  396. V_I4(&vt) = usPort;
  397. hr = pwcoProtocol->Put(
  398. c_wszOutgoingPort,
  399. 0,
  400. &vt,
  401. NULL
  402. );
  403. if (WBEM_S_NO_ERROR == hr)
  404. {
  405. //
  406. // Write the modified instance to the store
  407. //
  408. hr = m_piwsHomenet->PutInstance(
  409. pwcoProtocol,
  410. WBEM_FLAG_UPDATE_ONLY,
  411. NULL,
  412. NULL
  413. );
  414. }
  415. pwcoProtocol->Release();
  416. }
  417. return hr;
  418. }
  419. STDMETHODIMP
  420. CHNetAppProtocol::GetResponseRanges(
  421. USHORT *puscResponses,
  422. HNET_RESPONSE_RANGE *prgResponseRange[]
  423. )
  424. {
  425. HRESULT hr = S_OK;
  426. IWbemClassObject *pwcoProtocol;
  427. USHORT usResponses;
  428. VARIANT vt;
  429. IUnknown **rgUnknown;
  430. IWbemClassObject *pObj;
  431. if (NULL != prgResponseRange)
  432. {
  433. *prgResponseRange = NULL;
  434. if (NULL != puscResponses)
  435. {
  436. *puscResponses = 0;
  437. }
  438. else
  439. {
  440. hr = E_POINTER;
  441. }
  442. }
  443. else
  444. {
  445. hr = E_POINTER;
  446. }
  447. if (S_OK == hr)
  448. {
  449. hr = GetProtocolObject(&pwcoProtocol);
  450. }
  451. if (S_OK == hr)
  452. {
  453. //
  454. // Get the number of response ranges
  455. //
  456. hr = pwcoProtocol->Get(
  457. c_wszResponseCount,
  458. 0,
  459. &vt,
  460. NULL,
  461. NULL
  462. );
  463. if (WBEM_S_NO_ERROR == hr)
  464. {
  465. //
  466. // WMI uses V_I4 for it's uint16 type
  467. //
  468. _ASSERT(VT_I4 == V_VT(&vt));
  469. usResponses = static_cast<USHORT>(V_I4(&vt));
  470. VariantClear(&vt);
  471. }
  472. if (WBEM_S_NO_ERROR == hr)
  473. {
  474. //
  475. // Allocate enough memory for the output array.
  476. //
  477. *prgResponseRange
  478. = reinterpret_cast<HNET_RESPONSE_RANGE*>(
  479. CoTaskMemAlloc(usResponses * sizeof(HNET_RESPONSE_RANGE))
  480. );
  481. if (NULL == *prgResponseRange)
  482. {
  483. hr = E_OUTOFMEMORY;
  484. }
  485. }
  486. if (WBEM_S_NO_ERROR == hr)
  487. {
  488. //
  489. // Retrieve the response array
  490. //
  491. hr = pwcoProtocol->Get(
  492. c_wszResponseArray,
  493. 0,
  494. &vt,
  495. NULL,
  496. NULL
  497. );
  498. }
  499. pwcoProtocol->Release();
  500. }
  501. if (WBEM_S_NO_ERROR == hr)
  502. {
  503. //
  504. // Process the array: for each element, QI for IWbemClassObject
  505. // and copy the range data into the return struct
  506. //
  507. _ASSERT((VT_ARRAY | VT_UNKNOWN) == V_VT(&vt));
  508. hr = SafeArrayAccessData(
  509. V_ARRAY(&vt),
  510. reinterpret_cast<void**>(&rgUnknown)
  511. );
  512. if (S_OK == hr)
  513. {
  514. for (USHORT i = 0; i < usResponses; i++)
  515. {
  516. hr = rgUnknown[i]->QueryInterface(
  517. IID_PPV_ARG(IWbemClassObject, &pObj)
  518. );
  519. _ASSERT(S_OK == hr);
  520. hr = CopyResponseInstanceToStruct(
  521. pObj,
  522. &(*prgResponseRange)[i]
  523. );
  524. pObj->Release();
  525. if (FAILED(hr))
  526. {
  527. break;
  528. }
  529. }
  530. SafeArrayUnaccessData(V_ARRAY(&vt));
  531. }
  532. VariantClear(&vt);
  533. }
  534. if (S_OK == hr)
  535. {
  536. *puscResponses = usResponses;
  537. }
  538. else if (prgResponseRange && *prgResponseRange)
  539. {
  540. CoTaskMemFree(*prgResponseRange);
  541. *prgResponseRange = NULL;
  542. }
  543. return hr;
  544. }
  545. STDMETHODIMP
  546. CHNetAppProtocol::SetResponseRanges(
  547. USHORT uscResponses,
  548. HNET_RESPONSE_RANGE rgResponseRange[]
  549. )
  550. {
  551. HRESULT hr = S_OK;
  552. IWbemClassObject *pwcoProtocol;
  553. VARIANT vt;
  554. if (TRUE == m_fBuiltIn)
  555. {
  556. //
  557. // Can't change values for builtin protocols
  558. //
  559. hr = E_ACCESSDENIED;
  560. }
  561. else if (0 == uscResponses || NULL == rgResponseRange)
  562. {
  563. hr = E_INVALIDARG;
  564. }
  565. else
  566. {
  567. hr = GetProtocolObject(&pwcoProtocol);
  568. }
  569. if (S_OK == hr)
  570. {
  571. VariantInit(&vt);
  572. V_VT(&vt) = VT_ARRAY | VT_UNKNOWN;
  573. hr = ConvertResponseRangeArrayToInstanceSafearray(
  574. m_piwsHomenet,
  575. uscResponses,
  576. rgResponseRange,
  577. &V_ARRAY(&vt)
  578. );
  579. if (SUCCEEDED(hr))
  580. {
  581. //
  582. // Put the array and count properties
  583. //
  584. hr = pwcoProtocol->Put(
  585. c_wszResponseArray,
  586. 0,
  587. &vt,
  588. NULL
  589. );
  590. VariantClear(&vt);
  591. if (WBEM_S_NO_ERROR == hr)
  592. {
  593. //
  594. // WMI uses V_I4 for it's uint16 type
  595. //
  596. V_VT(&vt) = VT_I4;
  597. V_I4(&vt) = uscResponses;
  598. hr = pwcoProtocol->Put(
  599. c_wszResponseCount,
  600. 0,
  601. &vt,
  602. NULL
  603. );
  604. }
  605. }
  606. if (WBEM_S_NO_ERROR == hr)
  607. {
  608. //
  609. // Write the instance back to the store
  610. //
  611. hr = m_piwsHomenet->PutInstance(
  612. pwcoProtocol,
  613. WBEM_FLAG_UPDATE_ONLY,
  614. NULL,
  615. NULL
  616. );
  617. }
  618. pwcoProtocol->Release();
  619. }
  620. return hr;
  621. }
  622. STDMETHODIMP
  623. CHNetAppProtocol::GetBuiltIn(
  624. BOOLEAN *pfBuiltIn
  625. )
  626. {
  627. HRESULT hr = S_OK;
  628. if (NULL != pfBuiltIn)
  629. {
  630. *pfBuiltIn = m_fBuiltIn;
  631. }
  632. else
  633. {
  634. hr = E_POINTER;
  635. }
  636. return hr;
  637. }
  638. STDMETHODIMP
  639. CHNetAppProtocol::GetEnabled(
  640. BOOLEAN *pfEnabled
  641. )
  642. {
  643. HRESULT hr = S_OK;
  644. IWbemClassObject *pwcoProtocol;
  645. if (NULL == pfEnabled)
  646. {
  647. hr = E_POINTER;
  648. }
  649. else
  650. {
  651. hr = GetProtocolObject(&pwcoProtocol);
  652. }
  653. if (S_OK == hr)
  654. {
  655. hr = GetBooleanValue(
  656. pwcoProtocol,
  657. c_wszEnabled,
  658. pfEnabled
  659. );
  660. pwcoProtocol->Release();
  661. }
  662. return hr;
  663. }
  664. STDMETHODIMP
  665. CHNetAppProtocol::SetEnabled(
  666. BOOLEAN fEnable
  667. )
  668. {
  669. HRESULT hr = S_OK;
  670. IWbemClassObject *pwcoProtocol;
  671. hr = GetProtocolObject(&pwcoProtocol);
  672. if (WBEM_S_NO_ERROR == hr)
  673. {
  674. hr = SetBooleanValue(
  675. pwcoProtocol,
  676. c_wszEnabled,
  677. fEnable
  678. );
  679. if (WBEM_S_NO_ERROR == hr)
  680. {
  681. //
  682. // Write the modified instance to the store
  683. //
  684. hr = m_piwsHomenet->PutInstance(
  685. pwcoProtocol,
  686. WBEM_FLAG_UPDATE_ONLY,
  687. NULL,
  688. NULL
  689. );
  690. }
  691. pwcoProtocol->Release();
  692. }
  693. if (WBEM_S_NO_ERROR == hr)
  694. {
  695. //
  696. // Notify service of update.
  697. //
  698. UpdateService(IPNATHLP_CONTROL_UPDATE_SETTINGS);
  699. }
  700. return hr;
  701. }
  702. STDMETHODIMP
  703. CHNetAppProtocol::Delete()
  704. {
  705. HRESULT hr = S_OK;
  706. if (TRUE == m_fBuiltIn)
  707. {
  708. //
  709. // Can't delete builtin protocols
  710. //
  711. hr = E_ACCESSDENIED;
  712. }
  713. else
  714. {
  715. hr = m_piwsHomenet->DeleteInstance(
  716. m_bstrProtocol,
  717. 0,
  718. NULL,
  719. NULL
  720. );
  721. if (WBEM_S_NO_ERROR == hr)
  722. {
  723. //
  724. // Notify service of update.
  725. //
  726. UpdateService(IPNATHLP_CONTROL_UPDATE_SETTINGS);
  727. }
  728. }
  729. return hr;
  730. }
  731. HRESULT
  732. CHNetAppProtocol::GetProtocolObject(
  733. IWbemClassObject **ppwcoInstance
  734. )
  735. {
  736. _ASSERT(NULL != ppwcoInstance);
  737. return GetWmiObjectFromPath(
  738. m_piwsHomenet,
  739. m_bstrProtocol,
  740. ppwcoInstance
  741. );
  742. }