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.

2258 lines
62 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #include "CWANConnectionBase.h"
  4. #include "beacon.h"
  5. #include <ipnat.h>
  6. #include <iphlpapi.h>
  7. #include <ntddip.h>
  8. #include <winsock.h>
  9. #include "debug.h"
  10. #include "util.h"
  11. extern "C"
  12. ULONG
  13. NhpAllocateAndGetInterfaceInfoFromStack(
  14. IP_INTERFACE_NAME_INFO** Table,
  15. PULONG Count,
  16. BOOL SortOutput,
  17. HANDLE AllocationHeap,
  18. ULONG AllocationFlags
  19. );
  20. CWANConnectionBase::CWANConnectionBase()
  21. {
  22. m_pConnectionPoint = NULL;
  23. m_pHomenetConnection = NULL;
  24. m_pEventSink = NULL;
  25. m_pStatisticsProvider = NULL;
  26. m_IcsSettingsp = NULL;
  27. m_hAdviseNATEventsResult = E_FAIL;
  28. }
  29. HRESULT CWANConnectionBase::FinalConstruct()
  30. {
  31. HRESULT hr = S_OK;
  32. hr = StartNetmanEvents(this);
  33. if(SUCCEEDED(hr))
  34. {
  35. hr = AdviseNATEvents(this);
  36. m_hAdviseNATEventsResult = hr;
  37. }
  38. return hr;
  39. }
  40. HRESULT CWANConnectionBase::FinalRelease()
  41. {
  42. if ( NULL != m_pHomenetConnection)
  43. {
  44. m_pHomenetConnection->Release();
  45. }
  46. if ( NULL != m_IcsSettingsp)
  47. {
  48. m_IcsSettingsp->Release();
  49. }
  50. if(NULL != m_pStatisticsProvider)
  51. {
  52. m_pStatisticsProvider->Release();
  53. }
  54. DestroyDebugger();
  55. return S_OK;
  56. }
  57. HRESULT CWANConnectionBase::StopListening()
  58. {
  59. HRESULT hr = S_OK;
  60. if(NULL != m_pConnectionPoint)
  61. {
  62. hr = m_pConnectionPoint->Unadvise(m_dwConnectionManagerConnectionPointCookie);
  63. m_pConnectionPoint->Release();
  64. m_pConnectionPoint = NULL;
  65. }
  66. if(SUCCEEDED(m_hAdviseNATEventsResult))
  67. {
  68. UnadviseNATEvents(this);
  69. }
  70. return hr;
  71. }
  72. HRESULT CWANConnectionBase::StartNetmanEvents(INetConnectionNotifySink* pSink)
  73. {
  74. HRESULT hr = S_OK;
  75. INetConnectionManager* pConnectionManager;
  76. hr = CoCreateInstance(CLSID_ConnectionManager, NULL, CLSCTX_SERVER, IID_INetConnectionManager, reinterpret_cast<void**>(&pConnectionManager));
  77. if SUCCEEDED(hr)
  78. {
  79. IConnectionPointContainer* pConnectionPointContainer;
  80. hr = pConnectionManager->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast<void**>(&pConnectionPointContainer));
  81. if(SUCCEEDED(hr))
  82. {
  83. hr = pConnectionPointContainer->FindConnectionPoint(IID_INetConnectionNotifySink, &m_pConnectionPoint);
  84. if(SUCCEEDED(hr))
  85. {
  86. hr = m_pConnectionPoint->Advise(pSink, &m_dwConnectionManagerConnectionPointCookie);
  87. if(FAILED(hr))
  88. {
  89. m_pConnectionPoint->Release();
  90. m_pConnectionPoint = NULL;
  91. }
  92. // release in stop listening on success
  93. }
  94. pConnectionPointContainer->Release();
  95. }
  96. pConnectionManager->Release();
  97. }
  98. return hr;
  99. }
  100. HRESULT
  101. CWANConnectionBase::Initialize(
  102. GUID* pGuid,
  103. IHNetConnection* pHomenetConnection,
  104. IStatisticsProvider* pStatisticsProvider
  105. )
  106. {
  107. HRESULT hr = S_OK;
  108. InitDebugger();
  109. DBG_SPEW(TM_STATIC, TL_INFO, L" > Initialize ");
  110. m_pStatisticsProvider = pStatisticsProvider;
  111. m_pStatisticsProvider->AddRef();
  112. m_pHomenetConnection = pHomenetConnection;
  113. m_pHomenetConnection->AddRef();
  114. CopyMemory(&m_SharedGuid, pGuid, sizeof(GUID));
  115. hr = CoCreateInstance(CLSID_HNetCfgMgr,
  116. NULL,
  117. CLSCTX_SERVER,
  118. IID_IHNetIcsSettings,
  119. reinterpret_cast<void**>(&m_IcsSettingsp));
  120. return hr;
  121. }
  122. HRESULT CWANConnectionBase::FireEvent(DISPID DispatchId)
  123. {
  124. HRESULT hr = S_OK;
  125. IUPnPEventSink* pEventSink = NULL;
  126. Lock();
  127. if(NULL != m_pEventSink)
  128. {
  129. pEventSink = m_pEventSink;
  130. pEventSink->AddRef();
  131. }
  132. Unlock();
  133. if(NULL != pEventSink)
  134. {
  135. hr = pEventSink->OnStateChanged(1, &DispatchId);
  136. pEventSink->Release();
  137. }
  138. return hr;
  139. }
  140. // IUPnPEventSource methods
  141. HRESULT CWANConnectionBase::Advise(IUPnPEventSink* pesSubscriber)
  142. {
  143. HRESULT hr = S_OK;
  144. Lock();
  145. m_pEventSink = pesSubscriber;
  146. m_pEventSink->AddRef();
  147. Unlock();
  148. return hr;
  149. }
  150. HRESULT CWANConnectionBase::Unadvise(IUPnPEventSink *pesSubscriber)
  151. {
  152. HRESULT hr = S_OK;
  153. Lock();
  154. m_pEventSink->Release();
  155. m_pEventSink = NULL;
  156. Unlock();
  157. return hr;
  158. }
  159. // INATEventsNotifySink
  160. HRESULT CWANConnectionBase::PublicIPAddressChanged(void)
  161. {
  162. return FireEvent(IWANIPCONNECTION_DISPID_EXTERNALIPADDRESS);
  163. }
  164. HRESULT CWANConnectionBase::PortMappingsChanged(void)
  165. {
  166. return FireEvent(IWANIPCONNECTION_DISPID_PORTMAPPINGNUMBEROFENTRIES);
  167. }
  168. // INetConnectionNotifySink methods
  169. HRESULT CWANConnectionBase::ConnectionAdded(const NETCON_PROPERTIES_EX* pProps)
  170. {
  171. HRESULT hr = S_OK;
  172. return hr;
  173. }
  174. HRESULT CWANConnectionBase::ConnectionBandWidthChange(const GUID* pguidId)
  175. {
  176. HRESULT hr = S_OK;
  177. return hr;
  178. }
  179. HRESULT CWANConnectionBase::ConnectionDeleted(const GUID* pguidId)
  180. {
  181. HRESULT hr = S_OK;
  182. return hr;
  183. }
  184. HRESULT CWANConnectionBase::ConnectionModified(const NETCON_PROPERTIES_EX* pProps)
  185. {
  186. HRESULT hr = S_OK;
  187. return hr;
  188. }
  189. HRESULT CWANConnectionBase::ConnectionRenamed(const GUID* pguidId, LPCWSTR pszwNewName)
  190. {
  191. HRESULT hr = S_OK;
  192. if(IsEqualGUID(*pguidId, m_SharedGuid))
  193. {
  194. hr = FireEvent(IWANIPCONNECTION_DISPID_NAME);
  195. }
  196. return hr;
  197. }
  198. HRESULT CWANConnectionBase::ConnectionStatusChange(const GUID* pguidId, NETCON_STATUS Status)
  199. {
  200. HRESULT hr = S_OK;
  201. if(IsEqualGUID(*pguidId, m_SharedGuid))
  202. {
  203. hr = FireEvent(IWANIPCONNECTION_DISPID_CONNECTIONSTATUS);
  204. }
  205. return hr;
  206. }
  207. HRESULT CWANConnectionBase::ConnectionAddressChange(const GUID* pguidId)
  208. {
  209. HRESULT hr = S_OK;
  210. if ( IsEqualGUID(*pguidId, m_SharedGuid) )
  211. {
  212. hr = FireEvent( IWANIPCONNECTION_DISPID_EXTERNALIPADDRESS );
  213. }
  214. return hr;
  215. }
  216. HRESULT CWANConnectionBase::ShowBalloon(const GUID* pguidId, const BSTR szCookie, const BSTR szBalloonText)
  217. {
  218. HRESULT hr = E_NOTIMPL;
  219. return hr;
  220. }
  221. HRESULT CWANConnectionBase::RefreshAll()
  222. {
  223. HRESULT hr = S_OK;
  224. return hr;
  225. }
  226. HRESULT CWANConnectionBase::DisableEvents(const BOOL fDisable, const ULONG ulDisableTimeout)
  227. {
  228. HRESULT hr = S_OK;
  229. return hr;
  230. }
  231. // IWANIPConnection and IWANPPPConnection methods
  232. HRESULT CWANConnectionBase::get_ConnectionType(BSTR *pConnectionType)
  233. {
  234. HRESULT hr = S_OK;
  235. *pConnectionType = SysAllocString(L"IP_Routed");
  236. if(NULL == *pConnectionType)
  237. {
  238. hr = E_OUTOFMEMORY;
  239. }
  240. return hr;
  241. }
  242. HRESULT CWANConnectionBase::get_PossibleConnectionTypes(BSTR *pPossibleConnectionTypes)
  243. {
  244. HRESULT hr = S_OK;
  245. *pPossibleConnectionTypes = SysAllocString(L"IP_Routed");
  246. if(NULL == *pPossibleConnectionTypes)
  247. {
  248. hr = E_OUTOFMEMORY;
  249. }
  250. return hr;
  251. }
  252. HRESULT CWANConnectionBase::get_ConnectionStatus(BSTR *pConnectionStatus)
  253. {
  254. HRESULT hr = S_OK;
  255. *pConnectionStatus = NULL;
  256. INetConnection* pNetConnection;
  257. hr = m_pHomenetConnection->GetINetConnection(&pNetConnection);
  258. if(SUCCEEDED(hr))
  259. {
  260. NETCON_PROPERTIES* pProperties;
  261. hr = pNetConnection->GetProperties(&pProperties);
  262. if(SUCCEEDED(hr))
  263. {
  264. LPWSTR pszStatus;
  265. switch(pProperties->Status)
  266. {
  267. case NCS_AUTHENTICATION_SUCCEEDED:
  268. case NCS_CONNECTED:
  269. pszStatus = L"Connected";
  270. break;
  271. case NCS_DISCONNECTED:
  272. pszStatus = L"Disconnected";
  273. break;
  274. case NCS_AUTHENTICATING:
  275. case NCS_CONNECTING:
  276. pszStatus = L"Connecting";
  277. break;
  278. case NCS_DISCONNECTING:
  279. pszStatus = L"Disconnecting";
  280. break;
  281. case NCS_INVALID_ADDRESS:
  282. case NCS_CREDENTIALS_REQUIRED:
  283. case NCS_AUTHENTICATION_FAILED:
  284. case NCS_HARDWARE_DISABLED:
  285. case NCS_HARDWARE_MALFUNCTION:
  286. case NCS_HARDWARE_NOT_PRESENT:
  287. default:
  288. pszStatus = L"Unconfigured";
  289. break;
  290. }
  291. *pConnectionStatus = SysAllocString(pszStatus);
  292. if(NULL == *pConnectionStatus)
  293. {
  294. hr = E_OUTOFMEMORY;
  295. }
  296. NcFreeNetconProperties(pProperties);
  297. }
  298. pNetConnection->Release();
  299. }
  300. return hr;
  301. }
  302. HRESULT CWANConnectionBase::get_Uptime(ULONG *pUptime)
  303. {
  304. HRESULT hr = S_OK;
  305. hr = m_pStatisticsProvider->GetStatistics(NULL, NULL, NULL, NULL, NULL, pUptime);
  306. return hr;
  307. }
  308. HRESULT CWANConnectionBase::get_UpstreamMaxBitRate(ULONG *pUpstreamMaxBitRate)
  309. {
  310. HRESULT hr = S_OK;
  311. hr = m_pStatisticsProvider->GetStatistics(NULL, NULL, NULL, NULL, pUpstreamMaxBitRate, NULL);
  312. return hr;
  313. }
  314. HRESULT CWANConnectionBase::get_DownstreamMaxBitRate(ULONG *pDownstreamMaxBitRate)
  315. {
  316. HRESULT hr = S_OK;
  317. hr = m_pStatisticsProvider->GetStatistics(NULL, NULL, NULL, NULL, pDownstreamMaxBitRate, NULL);
  318. return hr;
  319. }
  320. HRESULT CWANConnectionBase::get_RSIPAvailable(VARIANT_BOOL *pRSIPAvailable)
  321. {
  322. HRESULT hr = S_OK;
  323. *pRSIPAvailable = VARIANT_FALSE;
  324. return hr;
  325. }
  326. HRESULT CWANConnectionBase::get_NATEnabled(VARIANT_BOOL *pNATEnabled)
  327. {
  328. HRESULT hr = S_OK;
  329. *pNATEnabled = VARIANT_TRUE;
  330. return hr;
  331. }
  332. HRESULT CWANConnectionBase::get_X_Name(BSTR* pName)
  333. {
  334. HRESULT hr = S_OK;
  335. *pName = NULL;
  336. INetConnection* pNetConnection;
  337. hr = m_pHomenetConnection->GetINetConnection(&pNetConnection);
  338. if(SUCCEEDED(hr))
  339. {
  340. NETCON_PROPERTIES* pProperties;
  341. hr = pNetConnection->GetProperties(&pProperties);
  342. if(SUCCEEDED(hr))
  343. {
  344. *pName = SysAllocString(pProperties->pszwName);
  345. if(NULL == *pName)
  346. {
  347. hr = E_OUTOFMEMORY;
  348. }
  349. NcFreeNetconProperties(pProperties);
  350. }
  351. pNetConnection->Release();
  352. }
  353. return hr;
  354. }
  355. HRESULT
  356. get_HrLocalAdaptersInfo(PIP_ADAPTER_INFO* ppAdapter)
  357. {
  358. HRESULT hr = S_OK, dwErr = NO_ERROR;
  359. PIP_ADAPTER_INFO paAdapterInfo = NULL;
  360. ULONG uBufLen = (2 * BUF_SIZE);
  361. _ASSERT( ppAdapter != NULL );
  362. *ppAdapter = NULL;
  363. paAdapterInfo = (PIP_ADAPTER_INFO) CoTaskMemAlloc( uBufLen );
  364. if ( NULL == paAdapterInfo ) { return E_OUTOFMEMORY; }
  365. //
  366. // Discover How much Memory we need. If we need at all.
  367. // Note that paAdapterInfo may be non-NULL and that is desired.
  368. dwErr = GetAdaptersInfo( paAdapterInfo, &uBufLen );
  369. if ( ERROR_BUFFER_OVERFLOW == dwErr )
  370. {
  371. CoTaskMemFree( paAdapterInfo );
  372. paAdapterInfo = (PIP_ADAPTER_INFO) CoTaskMemAlloc( uBufLen );
  373. if ( paAdapterInfo != NULL)
  374. {
  375. dwErr = GetAdaptersInfo ( paAdapterInfo, &uBufLen );
  376. }
  377. }
  378. if ( paAdapterInfo == NULL)
  379. {
  380. return E_OUTOFMEMORY;
  381. }
  382. if ( ERROR_SUCCESS != dwErr )
  383. {
  384. DBG_SPEW( TM_INFO, TL_ERROR,
  385. L" GetAdapterInfo has failed with E(%u) BufSize(%u) ",
  386. dwErr, uBufLen );
  387. CoTaskMemFree(paAdapterInfo);
  388. return HRESULT_FROM_WIN32( dwErr );
  389. }
  390. if ( ppAdapter && paAdapterInfo ) { *ppAdapter = paAdapterInfo; }
  391. return hr;
  392. }
  393. // {c200e360-38c5-11ce-ae62-08002b2b79ef} - 38 chars
  394. #define GUID_STRING_LENGTH 38
  395. PIP_ADAPTER_INFO
  396. GetExternalAdapterInfo( GUID* pGUID )
  397. {
  398. HRESULT hr = S_OK;
  399. WCHAR szwGUID[ GUID_STRING_LENGTH + 1 ] = { 0 };
  400. char ascGUID[ GUID_STRING_LENGTH + 1 ] = { 0 };
  401. PIP_ADAPTER_INFO pRetAdapter = NULL;
  402. PIP_ADAPTER_INFO pAdapterList = NULL, pTempAdapter = NULL;
  403. _ASSERT( pGUID != NULL );
  404. //
  405. // Change the given GUID to a String
  406. if ( StringFromGUID2( *pGUID, szwGUID, GUID_STRING_LENGTH + 1 ) == 0 )
  407. { return NULL; }
  408. if ( WideCharToMultiByte( CP_ACP, 0, szwGUID, -1, ascGUID, sizeof(ascGUID), NULL, NULL) == 0 )
  409. { return NULL; }
  410. hr = get_HrLocalAdaptersInfo( &pAdapterList );
  411. if ( FAILED(hr) || (pAdapterList == NULL) ) { return NULL; }
  412. pTempAdapter = pAdapterList;
  413. while ( pAdapterList != NULL )
  414. {
  415. if ( 0 == strcmp(ascGUID, pAdapterList->AdapterName) )
  416. {
  417. pRetAdapter = (PIP_ADAPTER_INFO) CoTaskMemAlloc( sizeof(IP_ADAPTER_INFO) );
  418. if ( NULL != pRetAdapter )
  419. {
  420. memcpy( pRetAdapter, pAdapterList, sizeof(IP_ADAPTER_INFO) );
  421. pRetAdapter->Next = NULL;
  422. break;
  423. }
  424. }
  425. pAdapterList = pAdapterList->Next;
  426. }
  427. CoTaskMemFree( pTempAdapter );
  428. return pRetAdapter;
  429. }
  430. HRESULT CWANConnectionBase::get_ExternalIPAddress(BSTR *pExternalIPAddress)
  431. {
  432. HRESULT hr = S_OK;
  433. ULONG AddressCount = 0;
  434. LPOLESTR swAddr = NULL;
  435. PIP_ADAPTER_INFO pExternalAdapterInfo = NULL;
  436. ULONG numOfChar = 0, uTemp = 0, Error = NO_ERROR;
  437. WCHAR szwGUID[ GUID_STRING_LENGTH + 1 ] = { 0 };
  438. IP_INTERFACE_NAME_INFO* Table = NULL;
  439. ULONG Count = 0;
  440. _ASSERT( pExternalIPAddress != NULL );
  441. if ( pExternalIPAddress != NULL )
  442. {
  443. *pExternalIPAddress = NULL;
  444. }
  445. else
  446. {
  447. return E_POINTER;
  448. }
  449. _ASSERT( pExternalIPAddress != NULL );
  450. StringFromGUID2( m_SharedGuid, szwGUID, GUID_STRING_LENGTH + 1 );
  451. DBG_SPEW(TM_INFO, TL_TRACE, L"> get_ExternalIpAddress Looking for GUID %s", szwGUID);
  452. Error = NhpAllocateAndGetInterfaceInfoFromStack(&Table,
  453. &Count,
  454. FALSE,
  455. GetProcessHeap(),
  456. 0);
  457. if ( (NO_ERROR == Error) && (Table != NULL) )
  458. {
  459. for (ULONG i = 0; i < Count ; i++)
  460. {
  461. #if DBG
  462. StringFromGUID2( Table[i].DeviceGuid, szwGUID, GUID_STRING_LENGTH + 1 );
  463. DBG_SPEW(TM_INFO, TL_DUMP, L" DeviceGUID[%u] = %s", i, szwGUID);
  464. StringFromGUID2( Table[i].InterfaceGuid, szwGUID, GUID_STRING_LENGTH + 1 );
  465. DBG_SPEW(TM_INFO, TL_DUMP, L" DeviceGUID[%u] = %s", i, szwGUID);
  466. #endif
  467. if ( IsEqualGUID((Table[i].InterfaceGuid), m_SharedGuid) )
  468. {
  469. pExternalAdapterInfo = GetExternalAdapterInfo( &Table[i].DeviceGuid );
  470. break;
  471. }
  472. }
  473. HeapFree(GetProcessHeap(), 0, Table);
  474. }
  475. if ( pExternalAdapterInfo == NULL )
  476. {
  477. pExternalAdapterInfo = GetExternalAdapterInfo( &m_SharedGuid );
  478. }
  479. if ( pExternalAdapterInfo != NULL )
  480. {
  481. if ( strcmp("0.0.0.0", pExternalAdapterInfo->IpAddressList.IpAddress.String) )
  482. {
  483. numOfChar = strlen( pExternalAdapterInfo->IpAddressList.IpAddress.String );
  484. swAddr = (LPOLESTR) CoTaskMemAlloc( (numOfChar + 1) * sizeof(WCHAR) );
  485. if ( swAddr != NULL )
  486. {
  487. memset( swAddr, 0, (numOfChar + 1) * sizeof(WCHAR));
  488. uTemp = _snwprintf( swAddr, numOfChar, L"%S",
  489. pExternalAdapterInfo->IpAddressList.IpAddress.String );
  490. _ASSERT( numOfChar == uTemp );
  491. swAddr[ numOfChar] = L'\0';
  492. *pExternalIPAddress = SysAllocString( swAddr );
  493. CoTaskMemFree( swAddr );
  494. }
  495. }
  496. else
  497. {
  498. *pExternalIPAddress = SysAllocString( L"" );
  499. }
  500. CoTaskMemFree( pExternalAdapterInfo );
  501. }
  502. else
  503. {
  504. *pExternalIPAddress = SysAllocString( L"" );
  505. }
  506. if ( *pExternalIPAddress == NULL )
  507. {
  508. hr = E_OUTOFMEMORY;
  509. }
  510. else
  511. {
  512. DBG_SPEW(TM_INFO, TL_INFO, L"Returning IP String (%s)", *pExternalIPAddress);
  513. }
  514. return hr;
  515. }
  516. HRESULT CWANConnectionBase::get_RemoteHost(BSTR *pRemoteHost)
  517. {
  518. HRESULT hr = E_NOTIMPL;
  519. return hr;
  520. }
  521. HRESULT CWANConnectionBase::get_ExternalPort(USHORT *pExternalPort)
  522. {
  523. HRESULT hr = E_NOTIMPL;
  524. return hr;
  525. }
  526. HRESULT CWANConnectionBase::get_InternalPort(USHORT *pInternalPort)
  527. {
  528. HRESULT hr = E_NOTIMPL;
  529. return hr;
  530. }
  531. HRESULT CWANConnectionBase::get_PortMappingProtocol(BSTR *pProtocol)
  532. {
  533. HRESULT hr = E_NOTIMPL;
  534. return hr;
  535. }
  536. HRESULT CWANConnectionBase::get_InternalClient(BSTR *pInternalClient)
  537. {
  538. HRESULT hr = E_NOTIMPL;
  539. return hr;
  540. }
  541. HRESULT CWANConnectionBase::get_PortMappingDescription(BSTR *pDescription)
  542. {
  543. HRESULT hr = E_NOTIMPL;
  544. return hr;
  545. }
  546. HRESULT CWANConnectionBase::get_PortMappingEnabled(VARIANT_BOOL *pEnabled)
  547. {
  548. HRESULT hr = E_NOTIMPL;
  549. return hr;
  550. }
  551. HRESULT CWANConnectionBase::get_PortMappingLeaseDuration(ULONG *LeaseDuration)
  552. {
  553. HRESULT hr = E_NOTIMPL;
  554. return hr;
  555. }
  556. HRESULT CWANConnectionBase::get_PortMappingNumberOfEntries(USHORT *pNumberOfEntries)
  557. {
  558. HRESULT hr = S_OK;
  559. IHNetPortMappingProtocol* MappingProtocolp = NULL;
  560. IHNetProtocolSettings* ProtocolSettingsp = NULL;
  561. IEnumHNetPortMappingProtocols* EnumProtocolsp = NULL;
  562. _ASSERT( pNumberOfEntries != NULL );
  563. *pNumberOfEntries = 0;
  564. do
  565. {
  566. hr = m_IcsSettingsp->QueryInterface(IID_IHNetProtocolSettings,
  567. reinterpret_cast<void**>(&ProtocolSettingsp));
  568. if( FAILED(hr) )
  569. {
  570. DBG_SPEW(TM_STATIC, TL_ERROR,
  571. L"Query Interface failed for ProtocolSettingsp E:(%X)", hr);
  572. break;
  573. }
  574. hr = ProtocolSettingsp->EnumPortMappingProtocols(&EnumProtocolsp);
  575. if ( FAILED(hr) )
  576. {
  577. DBG_SPEW(TM_STATIC, TL_ERROR,
  578. L"Enum Interface can't be retrieved E(%X)", hr);
  579. break;
  580. }
  581. while( S_OK == EnumProtocolsp->Next(1, &MappingProtocolp, NULL) )
  582. {
  583. (*pNumberOfEntries)++;
  584. _ASSERT( MappingProtocolp != NULL );
  585. MappingProtocolp->Release();
  586. }
  587. } while ( FALSE );
  588. if ( ProtocolSettingsp != NULL ) { ProtocolSettingsp->Release(); }
  589. if ( EnumProtocolsp != NULL) { EnumProtocolsp->Release(); }
  590. return hr;
  591. }
  592. HRESULT CWANConnectionBase::SetConnectionType(BSTR NewConnectionType)
  593. {
  594. HRESULT hr = S_OK;
  595. if(0 != lstrcmp(NewConnectionType, L"IP_Routed"))
  596. {
  597. hr = E_FAIL; // we only support IP_Routed
  598. }
  599. return hr;
  600. }
  601. HRESULT CWANConnectionBase::GetConnectionTypeInfo(BSTR* pNewConnectionType, BSTR* pNewPossibleConnectionTypes)
  602. {
  603. HRESULT hr = S_OK;
  604. SysFreeString(*pNewConnectionType);
  605. SysFreeString(*pNewPossibleConnectionTypes);
  606. *pNewConnectionType = NULL;
  607. *pNewPossibleConnectionTypes = NULL;
  608. hr = get_ConnectionType(pNewConnectionType);
  609. if(SUCCEEDED(hr))
  610. {
  611. hr = get_PossibleConnectionTypes(pNewPossibleConnectionTypes);
  612. }
  613. if(FAILED(hr))
  614. {
  615. if(NULL != *pNewConnectionType)
  616. {
  617. SysFreeString(*pNewConnectionType);
  618. *pNewConnectionType = NULL;
  619. }
  620. }
  621. return hr;
  622. }
  623. HRESULT CWANConnectionBase::GetStatusInfo(BSTR* pNewConnectionStatus, BSTR* pNewLastConnectionError, ULONG* pNewUptime)
  624. {
  625. HRESULT hr = S_OK;
  626. SysFreeString(*pNewConnectionStatus);
  627. SysFreeString(*pNewLastConnectionError);
  628. *pNewConnectionStatus = NULL;
  629. *pNewLastConnectionError = NULL;
  630. hr = get_ConnectionStatus(pNewConnectionStatus);
  631. if(SUCCEEDED(hr))
  632. {
  633. hr = get_LastConnectionError(pNewLastConnectionError);
  634. }
  635. if(SUCCEEDED(hr) && 0 == lstrcmp(L"Connected", *pNewConnectionStatus))
  636. {
  637. hr = get_Uptime(pNewUptime);
  638. }
  639. else
  640. {
  641. *pNewUptime = 0;
  642. }
  643. if(FAILED(hr))
  644. {
  645. if(NULL != *pNewConnectionStatus)
  646. {
  647. SysFreeString(*pNewConnectionStatus);
  648. *pNewConnectionStatus = NULL;
  649. }
  650. if(NULL != *pNewLastConnectionError)
  651. {
  652. SysFreeString(*pNewLastConnectionError);
  653. *pNewLastConnectionError = NULL;
  654. }
  655. }
  656. return hr;
  657. }
  658. HRESULT CWANConnectionBase::GetNATRSIPStatus(VARIANT_BOOL* pNewRSIPAvailable, VARIANT_BOOL* pNewNATEnabled)
  659. {
  660. HRESULT hr = S_OK;
  661. hr = get_RSIPAvailable(pNewRSIPAvailable);
  662. if(SUCCEEDED(hr))
  663. {
  664. hr = get_NATEnabled(pNewNATEnabled);
  665. }
  666. return hr;
  667. }
  668. HRESULT CWANConnectionBase::GetLinkLayerMaxBitRates(ULONG* pNewUpstreamMaxBitRate, ULONG* pNewDownstreamMaxBitRate)
  669. {
  670. HRESULT hr = S_OK;
  671. hr = get_UpstreamMaxBitRate(pNewUpstreamMaxBitRate);
  672. if(SUCCEEDED(hr))
  673. {
  674. hr = get_DownstreamMaxBitRate(pNewDownstreamMaxBitRate);
  675. }
  676. return hr;
  677. }
  678. HRESULT
  679. CWANConnectionBase::GetGenericPortMappingEntry(
  680. USHORT ulIndex,
  681. BSTR* RemoteHostp,
  682. USHORT* uExternalPortp,
  683. BSTR* Protocolp,
  684. USHORT* uInternalPortp,
  685. BSTR* InternalClientp,
  686. VARIANT_BOOL* bEnabledp,
  687. BSTR* Descriptionp,
  688. ULONG* ulLeaseDurationp
  689. )
  690. {
  691. HRESULT hr = S_OK;
  692. IHNetPortMappingProtocol* MappingProtocolp = NULL;
  693. IHNetPortMappingBinding* Bindingp = NULL;
  694. USHORT BoundaryPort = 0, InternalPort = 0;
  695. _ASSERT ( RemoteHostp != NULL );
  696. _ASSERT ( uExternalPortp != NULL );
  697. _ASSERT ( Protocolp != NULL );
  698. _ASSERT ( uInternalPortp != NULL );
  699. _ASSERT ( InternalClientp != NULL );
  700. _ASSERT ( bEnabledp != NULL );
  701. _ASSERT ( Descriptionp != NULL );
  702. _ASSERT ( ulLeaseDurationp != NULL );
  703. //
  704. // In/Out Parameters to COM Interfaces needs cleanup
  705. //
  706. SysFreeString(*RemoteHostp);
  707. SysFreeString(*Protocolp);
  708. SysFreeString(*InternalClientp);
  709. SysFreeString(*Descriptionp);
  710. *RemoteHostp = NULL;
  711. *Protocolp = NULL;
  712. *InternalClientp = NULL;
  713. *Descriptionp = NULL;
  714. *ulLeaseDurationp = 0;
  715. DBG_SPEW(TM_INFO, TL_TRACE, L"> GetGenericPortMapping");
  716. //
  717. // check for access
  718. hr = this->ControlEnabled();
  719. if ( FAILED(hr) )
  720. {
  721. DBG_SPEW(TM_INFO, TL_ERROR, L"Control Disabled returning E(%X)", hr);
  722. return hr;
  723. }
  724. do
  725. {
  726. //
  727. // SECURITY - SECURITY - SECURITY
  728. // Here we're allowing the out-of-proc COM call
  729. // into our service to have SYSTEM access rights.
  730. //
  731. // REASON: UPnP works in LOCAL_SERVICE and COM
  732. // Calls into our service which modify
  733. // the WMI repository will FAIL. This
  734. // Call alleviates that problem by changing
  735. // The Security to that of the SYSTEM
  736. // and is reverted back when the class
  737. // is out of scope by the destructor of.
  738. // CSwitchSecurityContext
  739. //
  740. CSwitchSecurityContext SwSecCxt;
  741. hr = SearchPortMapping(m_IcsSettingsp,
  742. ulIndex,
  743. 0,
  744. 0,
  745. &MappingProtocolp);
  746. if ( FAILED(hr) )
  747. {
  748. DBG_SPEW(TM_INFO, TL_ERROR,
  749. L"Enum - Seeking the port has failed E(%X)", hr);
  750. SetUPnPError(L"713");
  751. break;
  752. }
  753. //
  754. // Getting the binding - is this how it should be?
  755. //
  756. hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(MappingProtocolp,
  757. &Bindingp);
  758. if ( FAILED(hr) )
  759. {
  760. DBG_SPEW(TM_INFO, TL_ERROR,
  761. L"Enum - Error In Getting Binding for Protocol E(%X)", hr);
  762. break;
  763. }
  764. hr = FillStaticMappingInformation(MappingProtocolp,
  765. Bindingp,
  766. &BoundaryPort,
  767. Protocolp,
  768. &InternalPort,
  769. InternalClientp,
  770. bEnabledp,
  771. Descriptionp);
  772. _ASSERT( SUCCEEDED(hr) );
  773. if ( SUCCEEDED(hr) ) // correct the port Byte Ordering
  774. {
  775. *uExternalPortp = ntohs( BoundaryPort );
  776. *uInternalPortp = ntohs( InternalPort );
  777. }
  778. else
  779. {
  780. DBG_SPEW(TM_INFO, TL_ERROR,
  781. L"Enum - Error In Getting Binding for Protocol E(%X)" , hr);
  782. }
  783. } while ( FALSE );
  784. if ( MappingProtocolp != NULL) MappingProtocolp->Release();
  785. if ( Bindingp != NULL ) Bindingp->Release();
  786. if ( FAILED(hr) )
  787. {
  788. DBG_SPEW(TM_INFO, TL_ERROR,
  789. L"Enum - GetGenericEntry has failed with E(%X)", hr);
  790. }
  791. return hr;
  792. } // GetArrayEntry
  793. HRESULT
  794. CWANConnectionBase::GetSpecificPortMappingEntry(
  795. IN BSTR RemoteHost,
  796. IN USHORT uwExternalPort,
  797. IN BSTR Protocol,
  798. OUT USHORT* puwInternalPort,
  799. OUT BSTR* InternalClientp,
  800. OUT VARIANT_BOOL* pbEnabled,
  801. OUT BSTR* Descriptionp,
  802. OUT ULONG* pulLeaseDuration
  803. )
  804. //
  805. // Note that every port is expected to arrive in HOST order
  806. // and will be returned in HOST order
  807. //
  808. {
  809. HRESULT hr = S_OK;
  810. IHNetPortMappingProtocol* MappingProtocolp = NULL;
  811. IHNetPortMappingBinding* Bindingp = NULL;
  812. USHORT tempExtPort = 0, tempIntPort = 0;
  813. UCHAR searchProtocol = NULL;
  814. _ASSERT( RemoteHost != NULL );
  815. _ASSERT( uwExternalPort != 0 );
  816. _ASSERT( Protocol != NULL );
  817. SysFreeString( *InternalClientp );
  818. SysFreeString( *Descriptionp );
  819. *InternalClientp = NULL;
  820. *Descriptionp = NULL;
  821. tempExtPort = htons( uwExternalPort ); // flip to Network order
  822. DBG_SPEW(TM_INFO, TL_TRACE, L"> GetSpecificPortMapping");
  823. //
  824. // check for access
  825. hr = this->ControlEnabled();
  826. if ( FAILED(hr) )
  827. {
  828. DBG_SPEW(TM_INFO, TL_ERROR, L"Control is Disabled E(%X)", hr);
  829. return hr;
  830. }
  831. if ( 0 == uwExternalPort)
  832. {
  833. DBG_SPEW(TM_INFO, TL_ERROR, L"Parameters Incorrect Port(%hu)", uwExternalPort );
  834. SetUPnPError(L"402");
  835. return E_INVALIDARG;
  836. }
  837. do
  838. {
  839. //
  840. // SECURITY - SECURITY - SECURITY
  841. // Here we're allowing the out-of-proc COM call
  842. // into our service to have SYSTEM access rights.
  843. //
  844. // REASON: UPnP works in LOCAL_SERVICE and COM
  845. // Calls into our service which modify
  846. // the WMI repository will FAIL. This
  847. // Call alleviates that problem by changing
  848. // The Security to that of the SYSTEM
  849. // and is reverted back when the class
  850. // is out of scope by the destructor of.
  851. // CSwitchSecurityContext
  852. //
  853. CSwitchSecurityContext SwSecCxt;
  854. //
  855. // Resolve the Protocol to the appropriate enum.
  856. //
  857. RESOLVE_PROTOCOL_TYPE(searchProtocol, Protocol);
  858. DBG_SPEW(TM_INFO, TL_INFO,
  859. L"Search Specific - ExtPort (%hu) Protocol (%s)",
  860. htons( tempExtPort ),
  861. (NAT_PROTOCOL_TCP == searchProtocol)?L"TCP":L"UDP");
  862. hr = SearchPortMapping(m_IcsSettingsp,
  863. 0,
  864. tempExtPort,
  865. searchProtocol,
  866. &MappingProtocolp);
  867. if ( FAILED(hr))
  868. {
  869. DBG_SPEW(TM_INFO, TL_ERROR, L"Error or can't get Search E(%X)", hr);
  870. SetUPnPError(L"714");
  871. break;
  872. }
  873. //
  874. // Getting the binding
  875. //
  876. hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(MappingProtocolp,
  877. &Bindingp);
  878. if ( FAILED(hr) )
  879. {
  880. DBG_SPEW(TM_INFO, TL_ERROR,
  881. L"Error In Getting Binding for Protocol E(%X)", hr);
  882. break;
  883. }
  884. hr = FillStaticMappingInformation(MappingProtocolp,
  885. Bindingp,
  886. &tempExtPort,
  887. &Protocol,
  888. &tempIntPort,
  889. InternalClientp,
  890. pbEnabled,
  891. Descriptionp);
  892. _ASSERT( SUCCEEDED(hr) );
  893. *puwInternalPort = ntohs( tempIntPort );
  894. DBG_SPEW(TM_INFO, TL_TRACE,
  895. L"Returning IntClient (%s) IntPort (%hu) IntProtocol (%s), Enabled (%s), Desc (%s)",
  896. *InternalClientp,
  897. *puwInternalPort,
  898. Protocol,
  899. (*pbEnabled == VARIANT_TRUE)?L"TRUE":L"FALSE",
  900. *Descriptionp);
  901. } while ( FALSE );
  902. if ( MappingProtocolp != NULL) MappingProtocolp->Release();
  903. if ( Bindingp != NULL ) Bindingp->Release();
  904. if ( FAILED(hr) )
  905. {
  906. DBG_SPEW(TM_INFO, TL_ERROR, L"Error or can't get Search Done E(%X)", hr);
  907. }
  908. return hr;
  909. }
  910. HRESULT
  911. CWANConnectionBase::AddPortMapping(
  912. BSTR RemoteHost,
  913. USHORT uwExternalPort,
  914. BSTR Protocol,
  915. USHORT uwInternalPort,
  916. BSTR InternalClient,
  917. VARIANT_BOOL bEnabled,
  918. BSTR Description,
  919. ULONG ulLeaseDuration
  920. )
  921. {
  922. HRESULT hr = S_OK;
  923. MAPPING_TYPE MappingType = ePortMappingInvalid;
  924. DBG_SPEW(TM_STATIC, TL_TRACE, L"> AddPortMapping");
  925. //
  926. // Check for Access status
  927. hr = this->ControlEnabled();
  928. if ( SUCCEEDED(hr) )
  929. {
  930. hr = ValidatePortMappingParameters(RemoteHost,
  931. uwExternalPort,
  932. Protocol,
  933. uwInternalPort,
  934. InternalClient,
  935. bEnabled,
  936. Description,
  937. ulLeaseDuration,
  938. &MappingType);
  939. if ( SUCCEEDED(hr) )
  940. {
  941. DBG_SPEW(TM_STATIC, TL_TRACE,
  942. L"Add PortMapping - ExtPort (%hu) Protocol (%s)",
  943. uwExternalPort, Protocol);
  944. DBG_SPEW(TM_STATIC, TL_TRACE,
  945. L"IntClient (%s) IntPort (%hu) Enabled (%s), Desc (%s)",
  946. InternalClient,
  947. uwInternalPort,
  948. (bEnabled == VARIANT_TRUE)?L"TRUE":L"FALSE",
  949. Description);
  950. if ( ePortMappingStatic == MappingType )
  951. {
  952. //
  953. // SECURITY - SECURITY - SECURITY
  954. // Here we're allowing the out-of-proc COM call
  955. // into our service to have SYSTEM access rights.
  956. //
  957. // REASON: UPnP works in LOCAL_SERVICE and COM
  958. // Calls into our service which modify
  959. // the WMI repository will FAIL. This
  960. // Call alleviates that problem by changing
  961. // The Security to that of the SYSTEM
  962. // and is reverted back when the class
  963. // is out of scope by the destructor of.
  964. // CSwitchSecurityContext
  965. //
  966. CSwitchSecurityContext SwSecCxt;
  967. hr = AddStaticPortMapping(RemoteHost,
  968. uwExternalPort,
  969. Protocol,
  970. uwInternalPort,
  971. InternalClient,
  972. bEnabled,
  973. Description,
  974. ulLeaseDuration);
  975. }
  976. else
  977. {
  978. hr = AddDynamicPortMapping(RemoteHost,
  979. uwExternalPort,
  980. Protocol,
  981. uwInternalPort,
  982. InternalClient,
  983. bEnabled,
  984. Description,
  985. ulLeaseDuration);
  986. }
  987. }
  988. }
  989. else
  990. {
  991. DBG_SPEW(TM_STATIC, TL_ERROR, L"Control Disabled E(%X)", hr);
  992. }
  993. return hr;
  994. }
  995. HRESULT
  996. CWANConnectionBase::AddDynamicPortMapping(
  997. BSTR RemoteHost,
  998. USHORT uwExternalPort,
  999. BSTR Protocol,
  1000. USHORT uwInternalPort,
  1001. BSTR InternalClient,
  1002. VARIANT_BOOL bEnabled,
  1003. BSTR Description,
  1004. ULONG ulLeaseDuration
  1005. )
  1006. {
  1007. //
  1008. // We currently don't handle any Dynamic Port Redirections.
  1009. //
  1010. DBG_SPEW(TM_DYNAMIC, TL_ERROR, L"Only Static Mappings are allowed [Lease]");
  1011. SetUPnPError(L"725");
  1012. return E_INVALIDARG;
  1013. }
  1014. HRESULT
  1015. CWANConnectionBase::AddStaticPortMapping(
  1016. BSTR RemoteHost,
  1017. USHORT uwExternalPort,
  1018. BSTR Protocol,
  1019. USHORT uwInternalPort,
  1020. BSTR InternalClient,
  1021. VARIANT_BOOL bEnabled,
  1022. BSTR Description,
  1023. ULONG ulLeaseDuration
  1024. )
  1025. {
  1026. HRESULT hr = S_OK;
  1027. UCHAR ProtocolType = 0;
  1028. IHNetProtocolSettings* ProtocolSettingsp = NULL;
  1029. IHNetPortMappingProtocol* PortMappingProtocolp = NULL;
  1030. IHNetPortMappingBinding* PortMappingBindingp = NULL;
  1031. ULONG ClientAddr = 0;
  1032. BOOLEAN bLetsEnable = FALSE;
  1033. BOOLEAN bCreatedProtocol = FALSE;
  1034. ULONG tempStrLen = 0;
  1035. WCHAR tempPortStr[] = L"00000";
  1036. LPOLESTR tempStr = NULL;
  1037. USHORT tempExtPort = 0, tempIntPort = 0;
  1038. BSTR ProtocolFromBinding = NULL;
  1039. BSTR ClientFromBinding = NULL;
  1040. BSTR DescriptionFromBinding = NULL;
  1041. VARIANT_BOOL boolEnabled;
  1042. _ASSERT( uwExternalPort );
  1043. _ASSERT( uwInternalPort );
  1044. //
  1045. // Convert both ends to Network Order
  1046. //
  1047. tempExtPort = htons( uwExternalPort );
  1048. tempIntPort = htons( uwInternalPort );
  1049. //
  1050. // Convert VARIANT_BOOL to boolean
  1051. //
  1052. bLetsEnable = ( bEnabled == VARIANT_TRUE );
  1053. //
  1054. // Process the Operation
  1055. //
  1056. do
  1057. {
  1058. RESOLVE_PROTOCOL_TYPE(ProtocolType, Protocol);
  1059. //
  1060. // IF there is no description crate one
  1061. // using PORT and PROTOCOL
  1062. //
  1063. if ( wcscmp(Description, L"\0") == 0 )
  1064. {
  1065. // Get Internal ClientName + the seperator
  1066. tempStrLen = ( SysStringLen( InternalClient ) + 1 );
  1067. // Get port len + plus the seperator
  1068. _itow ( uwExternalPort, tempPortStr, 10);
  1069. tempStrLen += (wcslen (tempPortStr) + 1);
  1070. // Get Protocol Name
  1071. tempStrLen += SysStringLen( Protocol );
  1072. // Create out from these two
  1073. tempStr = (LPOLESTR)CoTaskMemAlloc( (tempStrLen + 1) * sizeof(WCHAR) );
  1074. if ( tempStr != NULL )
  1075. {
  1076. _snwprintf(tempStr, tempStrLen, L"%s-%s-%s",
  1077. InternalClient, tempPortStr, Protocol);
  1078. tempStr[ tempStrLen ] = L'\0';
  1079. Description = SysAllocString ( tempStr );
  1080. }
  1081. if ( (tempStr == NULL) || (Description == NULL) )
  1082. {
  1083. DBG_SPEW(TM_STATIC, TL_ERROR, L"Can't Initialize Strings - out of mem");
  1084. hr = E_OUTOFMEMORY;
  1085. break;
  1086. }
  1087. }
  1088. //
  1089. // Find Existing Mapping
  1090. //
  1091. hr = SearchPortMapping(m_IcsSettingsp,
  1092. 0,
  1093. tempExtPort,
  1094. ProtocolType,
  1095. &PortMappingProtocolp);
  1096. //
  1097. // if found it is in Edit Mode.
  1098. //
  1099. if ( SUCCEEDED(hr) )
  1100. {
  1101. hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(PortMappingProtocolp,
  1102. &PortMappingBindingp);
  1103. _ASSERT( SUCCEEDED(hr) );
  1104. if ( FAILED(hr) )
  1105. {
  1106. DBG_SPEW(TM_STATIC, TL_ERROR,
  1107. L"Can't get Binding for Port Mapping E(X)", hr);
  1108. _ASSERT( FALSE );
  1109. break;
  1110. }
  1111. //
  1112. // Fill the information
  1113. //
  1114. hr = FillStaticMappingInformation(PortMappingProtocolp,
  1115. PortMappingBindingp,
  1116. &tempExtPort,
  1117. &ProtocolFromBinding,
  1118. &tempIntPort,
  1119. &ClientFromBinding,
  1120. &boolEnabled,
  1121. &DescriptionFromBinding);
  1122. if ( FAILED(hr) )
  1123. {
  1124. DBG_SPEW(TM_STATIC, TL_ERROR,
  1125. L"Filling has failed for Mapping Information E(%X)", hr);
  1126. break;
  1127. }
  1128. //
  1129. // If the existin Mapping was disabled we should be able to change
  1130. // the Internal Client
  1131. //
  1132. if ( boolEnabled == VARIANT_TRUE )
  1133. {
  1134. if ( _wcsicmp( InternalClient, ClientFromBinding) != 0 ) // if diff then error
  1135. {
  1136. hr = E_INVALIDARG;
  1137. DBG_SPEW(TM_STATIC, TL_ERROR,
  1138. L"Will not change the internal client for an enabled PortMapping");
  1139. SetUPnPError(L"718");
  1140. break;
  1141. }
  1142. }
  1143. //
  1144. // if the Internal Port has changed reflect the change
  1145. //
  1146. if ( tempIntPort != htons( uwInternalPort ) )
  1147. {
  1148. tempIntPort = htons( uwInternalPort );
  1149. hr = PortMappingBindingp->SetTargetPort( tempIntPort );
  1150. _ASSERT( SUCCEEDED(hr) );
  1151. if ( FAILED(hr) )
  1152. {
  1153. DBG_SPEW(TM_STATIC, TL_ERROR, L"Changin Internal Port has Failed E(%X)", hr);
  1154. break;
  1155. }
  1156. }
  1157. //
  1158. // Set the description if changed
  1159. //
  1160. if ( _wcsicmp(DescriptionFromBinding, Description) != 0)
  1161. {
  1162. hr = PortMappingProtocolp->SetName(Description);
  1163. if ( FAILED(hr) )
  1164. {
  1165. hr = E_INVALIDARG;
  1166. DBG_SPEW(TM_STATIC, TL_ERROR, L"Set Name has failed E(%X)", hr);
  1167. break;
  1168. }
  1169. }
  1170. }
  1171. else
  1172. {
  1173. //
  1174. // Start Getting the Interface
  1175. //
  1176. hr = m_IcsSettingsp->QueryInterface(IID_IHNetProtocolSettings,
  1177. reinterpret_cast<void**>(&ProtocolSettingsp));
  1178. if ( SUCCEEDED(hr) )
  1179. {
  1180. hr = ProtocolSettingsp->CreatePortMappingProtocol(Description,
  1181. ProtocolType,
  1182. tempExtPort,
  1183. &PortMappingProtocolp);
  1184. if ( SUCCEEDED(hr) )
  1185. {
  1186. hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(PortMappingProtocolp,
  1187. &PortMappingBindingp);
  1188. if ( SUCCEEDED(hr) )
  1189. {
  1190. hr = PortMappingBindingp->SetTargetPort( tempIntPort );
  1191. _ASSERT( SUCCEEDED(hr) );
  1192. if ( FAILED(hr) )
  1193. {
  1194. DBG_SPEW(TM_STATIC, TL_ERROR, L"Set Target Port has Failed E(%X)", hr);
  1195. }
  1196. bCreatedProtocol = TRUE;
  1197. }
  1198. else
  1199. {
  1200. DBG_SPEW(TM_STATIC, TL_ERROR,
  1201. L"Getting Binding has Failed E(X)", hr);
  1202. PortMappingProtocolp->Delete();
  1203. break;
  1204. }
  1205. }
  1206. else
  1207. {
  1208. DBG_SPEW(TM_STATIC, TL_ERROR,
  1209. L"Creating the PortMapping has Failed E(%X)", hr);
  1210. break;
  1211. }
  1212. }
  1213. else
  1214. {
  1215. DBG_SPEW(TM_STATIC, TL_ERROR,
  1216. L"Getting the Protocol Settings has failed E(X)", hr);
  1217. break;
  1218. }
  1219. }
  1220. //
  1221. // Setting the Client name / address
  1222. // For Edit mode we already checked wether this code will be run or not.
  1223. //
  1224. if (
  1225. ( wcscmp(L"0.0.0.0", InternalClient) != 0 ) &&
  1226. ( InternalClient[0] != L'\0' )
  1227. )
  1228. {
  1229. ClientAddr = INET_ADDR((LPOLESTR) InternalClient );
  1230. //
  1231. // if the address is not valid (INADDR_NONE)
  1232. // and if the address is different than Broadcast address (which also is INADDR_NONE)
  1233. //
  1234. if ( (ClientAddr == INADDR_NONE) && wcscmp(L"255.255.255.255", InternalClient) )
  1235. {
  1236. hr = PortMappingBindingp->SetTargetComputerName( InternalClient );
  1237. }
  1238. else
  1239. {
  1240. hr = PortMappingBindingp->SetTargetComputerAddress( ClientAddr );
  1241. }
  1242. _ASSERT( SUCCEEDED(hr) );
  1243. if ( SUCCEEDED(hr) )
  1244. {
  1245. hr = PortMappingBindingp->SetEnabled( bLetsEnable );
  1246. }
  1247. if ( FAILED(hr) ) DBG_SPEW(TM_STATIC, TL_ERROR, L"Client Add/Edit IntClient failed - E(%X)", hr);
  1248. }
  1249. if ( FAILED(hr) && (TRUE == bCreatedProtocol) )
  1250. {
  1251. DBG_SPEW(TM_STATIC, TL_ERROR, L"Client Add / Edit failed - E(%X)", hr);
  1252. hr = PortMappingProtocolp->Delete();
  1253. }
  1254. } while ( FALSE );
  1255. if ( tempStr != NULL)
  1256. {
  1257. CoTaskMemFree ( tempStr );
  1258. SysFreeString ( Description ); // you can free a NULL string.
  1259. }
  1260. if ( ProtocolFromBinding ) SysFreeString(ProtocolFromBinding);
  1261. if ( ClientFromBinding ) SysFreeString(ClientFromBinding);
  1262. if ( DescriptionFromBinding ) SysFreeString(DescriptionFromBinding);
  1263. if ( PortMappingBindingp != NULL ) PortMappingBindingp->Release();
  1264. if ( PortMappingProtocolp != NULL ) PortMappingProtocolp->Release();
  1265. if ( ProtocolSettingsp != NULL ) ProtocolSettingsp->Release();
  1266. if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Error Returning hr (%X)", hr); }
  1267. return hr;
  1268. } // CWANConnectionBase :: AddStaticPortMapping
  1269. HRESULT
  1270. CWANConnectionBase::DeletePortMapping(
  1271. BSTR RemoteHost,
  1272. USHORT uwExternalPort,
  1273. BSTR Protocol
  1274. )
  1275. {
  1276. HRESULT hr = S_OK;
  1277. UCHAR ProtocolType = 0;
  1278. IHNetPortMappingProtocol* PortMappingProtocolp = NULL;
  1279. USHORT tempExtPort = 0;
  1280. //
  1281. // SECURITY - SECURITY - SECURITY
  1282. // Here we're allowing the out-of-proc COM call
  1283. // into our service to have SYSTEM access rights.
  1284. //
  1285. // REASON: UPnP works in LOCAL_SERVICE and COM
  1286. // Calls into our service which modify
  1287. // the WMI repository will FAIL. This
  1288. // Call alleviates that problem by changing
  1289. // The Security to that of the SYSTEM
  1290. // and is reverted back when the class
  1291. // is out of scope by the destructor of.
  1292. // CSwitchSecurityContext
  1293. //
  1294. CSwitchSecurityContext SwSecCxt;
  1295. _ASSERT( RemoteHost != NULL );
  1296. _ASSERT( uwExternalPort != 0 );
  1297. _ASSERT( Protocol != NULL );
  1298. DBG_SPEW(TM_STATIC, TL_TRACE, L"> DeletePortMapping");
  1299. //
  1300. // check for access
  1301. hr = this->ControlEnabled();
  1302. if ( FAILED(hr) ) { return hr; }
  1303. //
  1304. // Convert to Network order
  1305. //
  1306. tempExtPort = htons(uwExternalPort );
  1307. DBG_SPEW(TM_STATIC, TL_INFO,
  1308. L"Search Specific - ExtPort (%hu) Protocol (%s)",
  1309. uwExternalPort, Protocol);
  1310. do
  1311. {
  1312. RESOLVE_PROTOCOL_TYPE( ProtocolType, Protocol );
  1313. hr = SearchPortMapping(m_IcsSettingsp,
  1314. 0,
  1315. tempExtPort,
  1316. ProtocolType,
  1317. &PortMappingProtocolp);
  1318. if ( FAILED(hr) )
  1319. {
  1320. DBG_SPEW(TM_STATIC, TL_ERROR, L"Error in Searching E(%X)", hr );
  1321. SetUPnPError(L"714");
  1322. break;
  1323. }
  1324. hr = PortMappingProtocolp->Delete();
  1325. if ( FAILED(hr) )
  1326. {
  1327. DBG_SPEW(TM_STATIC, TL_ERROR,
  1328. L"ProtocolMapping deletion failure, Might be Built in E(%X)", hr );
  1329. }
  1330. PortMappingProtocolp->Release();
  1331. } while ( FALSE );
  1332. if ( FAILED(hr) ) DBG_SPEW(TM_STATIC, TL_ERROR, L"Delete failed with hr - %X", hr);
  1333. return hr;
  1334. }
  1335. HRESULT CWANConnectionBase::GetExternalIPAddress(BSTR* pExternalIPAddress)
  1336. {
  1337. HRESULT hr = S_OK;
  1338. SysFreeString(*pExternalIPAddress);
  1339. *pExternalIPAddress = NULL;
  1340. hr = get_ExternalIPAddress(pExternalIPAddress);
  1341. return hr;
  1342. }
  1343. HRESULT CWANConnectionBase::ControlEnabled()
  1344. {
  1345. HRESULT hr = S_OK;
  1346. // check the reg key. Only disable if key exists and is 0.
  1347. HKEY hKey;
  1348. DWORD dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_SHAREDACCESSCLIENTKEYPATH, 0, KEY_QUERY_VALUE, &hKey);
  1349. if(ERROR_SUCCESS == dwError) // if this fails we assume it is on, set the box, and commit on apply
  1350. {
  1351. DWORD dwType;
  1352. DWORD dwData = 0;
  1353. DWORD dwSize = sizeof(dwData);
  1354. dwError = RegQueryValueEx(hKey, REGVAL_SHAREDACCESSCLIENTENABLECONTROL, 0, &dwType, reinterpret_cast<LPBYTE>(&dwData), &dwSize);
  1355. if(ERROR_SUCCESS == dwError && REG_DWORD == dwType && 0 == dwData)
  1356. {
  1357. hr = E_ACCESSDENIED;
  1358. }
  1359. RegCloseKey(hKey);
  1360. }
  1361. return hr;
  1362. }
  1363. HRESULT
  1364. SearchPortMapping(
  1365. IN IHNetIcsSettings* IcsSettingsp,
  1366. IN OPTIONAL ULONG searchIndex,
  1367. IN OPTIONAL USHORT searchPort,
  1368. IN OPTIONAL UCHAR searchProtocol,
  1369. OUT IHNetPortMappingProtocol **Protocolpp
  1370. )
  1371. //
  1372. // Two ways of Seeking an entry..
  1373. // 1) By Index.. Enumerate until you hit the giventh Index.
  1374. // 2) Seeks and retrieves Port and ProtocolType
  1375. //
  1376. {
  1377. HRESULT hr = S_OK;
  1378. IHNetProtocolSettings* ProtocolSettingsp = NULL;
  1379. IEnumHNetPortMappingProtocols* EnumProtocolsp = NULL;
  1380. IHNetPortMappingProtocol* tempProtocolp = NULL;
  1381. USHORT ProtocolPort = 0;
  1382. UCHAR ProtocolType = 0;
  1383. BOOLEAN bFound = FALSE;
  1384. ULONG iIndex = 0;
  1385. DBG_SPEW(TM_STATIC, TL_ERROR, L" > SearchPortMapping ");
  1386. //
  1387. // Index = 0 is a valid search
  1388. // searchPort and searcProtocol should exist both or not.
  1389. //
  1390. _ASSERT( !((searchPort == NULL) ^ (searchProtocol == 0)) );
  1391. _ASSERT( IcsSettingsp != NULL );
  1392. _ASSERT( Protocolpp != NULL );
  1393. do
  1394. {
  1395. hr = IcsSettingsp->QueryInterface(IID_IHNetProtocolSettings,
  1396. reinterpret_cast<void**>(&ProtocolSettingsp));
  1397. if( FAILED(hr) )
  1398. {
  1399. DBG_SPEW(TM_STATIC, TL_ERROR,
  1400. L"Query Interface failed for ProtocolSettingsp E(%X)", hr);
  1401. break;
  1402. }
  1403. hr = ProtocolSettingsp->EnumPortMappingProtocols(&EnumProtocolsp);
  1404. if ( FAILED(hr) )
  1405. {
  1406. DBG_SPEW(TM_STATIC, TL_ERROR,
  1407. L"Enum Interface can't be retrieved E(%X)", hr);
  1408. break;
  1409. }
  1410. while( (FALSE == bFound) &&
  1411. (S_OK == EnumProtocolsp->Next(1, &tempProtocolp, NULL)) )
  1412. {
  1413. if ( searchPort != 0 )
  1414. {
  1415. hr = tempProtocolp->GetPort( &ProtocolPort );
  1416. if ( SUCCEEDED(hr) )
  1417. {
  1418. hr = tempProtocolp->GetIPProtocol(&ProtocolType);
  1419. }
  1420. if( FAILED(hr) )
  1421. {
  1422. DBG_SPEW(TM_STATIC, TL_ERROR, L"Search info Failure E(%X)", hr);
  1423. }
  1424. else if((searchPort == ProtocolPort) &&
  1425. (ProtocolType == searchProtocol))
  1426. {
  1427. bFound = TRUE;
  1428. }
  1429. }
  1430. else // if the search key == the Index
  1431. {
  1432. if ( iIndex == searchIndex )
  1433. {
  1434. bFound = TRUE;
  1435. }
  1436. }
  1437. //
  1438. // if Nothing is found
  1439. if (FALSE == bFound)
  1440. {
  1441. tempProtocolp->Release();
  1442. }
  1443. iIndex++;
  1444. }
  1445. EnumProtocolsp->Release();
  1446. } while ( FALSE );
  1447. if(ProtocolSettingsp != NULL)
  1448. {
  1449. ProtocolSettingsp->Release();
  1450. }
  1451. if( (bFound == TRUE) &&
  1452. (tempProtocolp != NULL))
  1453. {
  1454. *Protocolpp = tempProtocolp;
  1455. }
  1456. else
  1457. {
  1458. return E_INVALIDARG;
  1459. }
  1460. return hr;
  1461. }
  1462. HRESULT
  1463. FillStaticMappingInformation(
  1464. IN IHNetPortMappingProtocol* MappingProtocolp,
  1465. IN OPTIONAL IHNetPortMappingBinding* Bindingp,
  1466. OUT PUSHORT uExternalPortp,
  1467. OUT BSTR* Protocolp,
  1468. OUT PUSHORT uInternalPortp,
  1469. OUT BSTR* InternalClientp,
  1470. OUT VARIANT_BOOL* bEnabledp,
  1471. OUT BSTR* Descriptionp
  1472. )
  1473. //
  1474. // Note that Will return the port in Network Byte Order
  1475. //
  1476. {
  1477. HRESULT hr = S_OK;
  1478. UCHAR ProtocolType = NULL;
  1479. LPOLESTR szInternalHostAddr = NULL;
  1480. LPOLESTR szDescription = NULL;
  1481. BOOLEAN bEnabled = FALSE;
  1482. BOOLEAN bUseName = FALSE;
  1483. ULONG InternalHostAddr = 0;
  1484. _ASSERT ( uExternalPortp != NULL );
  1485. _ASSERT ( Protocolp != NULL );
  1486. _ASSERT ( InternalClientp != NULL );
  1487. _ASSERT ( bEnabledp != NULL );
  1488. _ASSERT ( Descriptionp != NULL );
  1489. _ASSERT ( MappingProtocolp != NULL );
  1490. _ASSERT ( Bindingp != NULL );
  1491. *uExternalPortp = 0;
  1492. *Protocolp = NULL;
  1493. *InternalClientp = NULL;
  1494. *bEnabledp = VARIANT_FALSE;
  1495. *Descriptionp = NULL;
  1496. DBG_SPEW(TM_STATIC, TL_TRACE, L"> FillStaticMappingInformation");
  1497. do
  1498. {
  1499. //
  1500. // Description
  1501. //
  1502. hr = MappingProtocolp->GetName(&szDescription);
  1503. if ( FAILED(hr) )
  1504. {
  1505. DBG_SPEW(TM_STATIC, TL_ERROR, L"Getting the Name has failed E(%X)", hr);
  1506. break;
  1507. }
  1508. BOOLEAN fBuiltin = FALSE;
  1509. hr = MappingProtocolp->GetBuiltIn( &fBuiltin );
  1510. _ASSERT( SUCCEEDED(hr) );
  1511. if ( fBuiltin )
  1512. {
  1513. #define BUILTIN_KEY L" [MICROSOFT]"
  1514. UINT uiLength = wcslen(szDescription );
  1515. uiLength += wcslen(BUILTIN_KEY);
  1516. *Descriptionp = SysAllocStringLen(NULL, uiLength);
  1517. if ( *Descriptionp )
  1518. {
  1519. wcscpy (*Descriptionp, szDescription);
  1520. wcscat (*Descriptionp, BUILTIN_KEY);
  1521. }
  1522. }
  1523. else
  1524. {
  1525. *Descriptionp = SysAllocString(szDescription);
  1526. }
  1527. if(*Descriptionp == NULL)
  1528. {
  1529. DBG_SPEW(TM_STATIC, TL_ERROR,
  1530. L"Memory Allocation for Description has Failed");
  1531. hr = E_OUTOFMEMORY;
  1532. break;
  1533. }
  1534. //
  1535. // Protocol
  1536. //
  1537. hr = MappingProtocolp->GetIPProtocol(&ProtocolType);
  1538. _ASSERT( SUCCEEDED(hr) );
  1539. if ( ProtocolType == NAT_PROTOCOL_TCP )
  1540. {
  1541. *Protocolp = SysAllocString(L"TCP");
  1542. }
  1543. else if ( ProtocolType == NAT_PROTOCOL_UDP )
  1544. {
  1545. *Protocolp = SysAllocString(L"UDP");
  1546. }
  1547. else
  1548. {
  1549. _ASSERT( FALSE );
  1550. }
  1551. if (*Protocolp == NULL)
  1552. {
  1553. DBG_SPEW(TM_STATIC, TL_ERROR,
  1554. L"Memory Allocation for Description has Failed");
  1555. hr = E_OUTOFMEMORY;
  1556. break;
  1557. }
  1558. //
  1559. // External Port
  1560. //
  1561. hr = MappingProtocolp->GetPort( uExternalPortp );
  1562. _ASSERT( SUCCEEDED(hr) );
  1563. if ( FAILED(hr) )
  1564. {
  1565. DBG_SPEW(TM_STATIC, TL_ERROR,
  1566. L"GetPort for Protocol has failed E(%X)", hr);
  1567. break;
  1568. }
  1569. // Getting the Binding Information
  1570. if ( Bindingp != NULL )
  1571. {
  1572. //
  1573. // Enabled
  1574. hr = Bindingp->GetEnabled(&bEnabled);
  1575. _ASSERT( SUCCEEDED(hr) );
  1576. if ( bEnabled == TRUE)
  1577. {
  1578. *bEnabledp = VARIANT_TRUE;
  1579. }
  1580. else
  1581. {
  1582. *bEnabledp = VARIANT_FALSE;
  1583. }
  1584. hr = Bindingp->GetTargetPort( uInternalPortp );
  1585. _ASSERT( SUCCEEDED(hr) );
  1586. if ( FAILED(hr) )
  1587. {
  1588. DBG_SPEW(TM_STATIC, TL_ERROR,
  1589. L"GetPort for Binding has failed E(%X)", hr);
  1590. break;
  1591. }
  1592. //
  1593. // InternalClient
  1594. hr = Bindingp->GetCurrentMethod(&bUseName);
  1595. if( SUCCEEDED(hr) )
  1596. {
  1597. if ( bUseName == TRUE)
  1598. {
  1599. hr = Bindingp->GetTargetComputerName(&szInternalHostAddr);
  1600. if ( FAILED(hr) )
  1601. {
  1602. break;
  1603. }
  1604. _ASSERT( SUCCEEDED(hr) );
  1605. }
  1606. else
  1607. {
  1608. hr = Bindingp->GetTargetComputerAddress(&InternalHostAddr);
  1609. _ASSERT( SUCCEEDED(hr) );
  1610. if ( FAILED(hr) )
  1611. {
  1612. break;
  1613. }
  1614. //
  1615. // IF the address is Loopback change it to a name which would make more
  1616. // sense to any client who sees it.
  1617. //
  1618. if ( INADDR_LOOPBACK == htonl(InternalHostAddr) )
  1619. {
  1620. ULONG uCount = 0;
  1621. if ( 0 == GetComputerNameEx( ComputerNameDnsHostname, NULL, &uCount) )
  1622. {
  1623. if ( (ERROR_MORE_DATA == GetLastError()) )
  1624. {
  1625. szInternalHostAddr =
  1626. (LPOLESTR) CoTaskMemAlloc( uCount * sizeof(WCHAR) );
  1627. if ( NULL != szInternalHostAddr )
  1628. {
  1629. if (!GetComputerNameEx(ComputerNameDnsHostname,
  1630. szInternalHostAddr,
  1631. &uCount))
  1632. {
  1633. hr = HRESULT_FROM_WIN32( GetLastError() );
  1634. break;
  1635. }
  1636. }
  1637. else
  1638. {
  1639. hr = E_OUTOFMEMORY;
  1640. break;
  1641. }
  1642. }
  1643. else
  1644. {
  1645. hr = E_FAIL;
  1646. break;
  1647. }
  1648. }
  1649. }
  1650. else if ( 0 != InternalHostAddr )
  1651. {
  1652. szInternalHostAddr = INET_NTOW_TS( InternalHostAddr );
  1653. }
  1654. else
  1655. {
  1656. szInternalHostAddr = (LPOLESTR) CoTaskMemAlloc( sizeof(WCHAR) );
  1657. if ( NULL != szInternalHostAddr) szInternalHostAddr[0] = 0;
  1658. }
  1659. if ( szInternalHostAddr == NULL )
  1660. {
  1661. hr = E_OUTOFMEMORY;
  1662. break;
  1663. }
  1664. } // if Name method
  1665. }
  1666. *InternalClientp = SysAllocString( szInternalHostAddr );
  1667. if ( *InternalClientp == NULL)
  1668. {
  1669. DBG_SPEW(TM_STATIC, TL_ERROR, L"Mem Allocation for Internal Client Name");
  1670. hr = E_OUTOFMEMORY;
  1671. break;
  1672. }
  1673. } // if bindingp
  1674. } while ( FALSE );
  1675. if ( szDescription ) CoTaskMemFree( szDescription );
  1676. if ( szInternalHostAddr ) CoTaskMemFree( szInternalHostAddr );
  1677. if ( FAILED(hr) )
  1678. {
  1679. if(*Protocolp) { SysFreeString(*Protocolp); *Protocolp = NULL; }
  1680. if(*InternalClientp) { SysFreeString(*InternalClientp); *InternalClientp = NULL;}
  1681. if(*Descriptionp) { SysFreeString(*Descriptionp); *Descriptionp = NULL;}
  1682. }
  1683. return hr;
  1684. }
  1685. inline HRESULT
  1686. ValidatePortMappingParameters
  1687. (
  1688. IN BSTR RemoteHost,
  1689. IN USHORT uwExternalPort,
  1690. IN BSTR Protocol,
  1691. IN USHORT uwInternalPort,
  1692. IN BSTR InternalClient,
  1693. IN VARIANT_BOOL bEnabled,
  1694. IN BSTR Description,
  1695. IN ULONG ulLeaseDuration,
  1696. OUT MAPPING_TYPE* pMappingType
  1697. )
  1698. //
  1699. // Decide wether a Mapping is to be dynamic or static
  1700. // Validate the parameters pre-emptively
  1701. //
  1702. {
  1703. MAPPING_TYPE MappingType = ePortMappingInvalid;
  1704. _ASSERT( RemoteHost != NULL );
  1705. _ASSERT( Protocol != NULL );
  1706. _ASSERT( Protocol[0] != 0 );
  1707. _ASSERT( Description != NULL );
  1708. _ASSERT( uwInternalPort != 0 );
  1709. _ASSERT( pMappingType != NULL );
  1710. _ASSERT( InternalClient != NULL );
  1711. _ASSERT( RemoteHost[0] == 0 );
  1712. //
  1713. // An Internal Port as well as an external Port should exist all time
  1714. //
  1715. if ( (0 == uwInternalPort) || (0 == uwExternalPort) )
  1716. {
  1717. SetUPnPError(L"716");
  1718. return E_INVALIDARG;
  1719. }
  1720. //
  1721. // is this a dynamic request?
  1722. //
  1723. if ( 0 != ulLeaseDuration )
  1724. {
  1725. MappingType = ePortMappingDynamic;
  1726. }
  1727. else
  1728. {
  1729. MappingType = ePortMappingStatic;
  1730. }
  1731. //
  1732. // A Dynamic Port Mapping needs to be with
  1733. // an Internal Client
  1734. //
  1735. if (
  1736. ( ePortMappingDynamic == MappingType ) &&
  1737. ( InternalClient[0] == L'\0' )
  1738. )
  1739. {
  1740. SetUPnPError(L"402");
  1741. return E_INVALIDARG;
  1742. }
  1743. //
  1744. // A remote Host is defined.. we can't process this
  1745. //
  1746. if ( RemoteHost[0] != L'\0' )
  1747. {
  1748. SetUPnPError(L"726");
  1749. return E_INVALIDARG;
  1750. }
  1751. //
  1752. // Check the bEnabled bool value
  1753. //
  1754. if ( (bEnabled != VARIANT_TRUE) && (bEnabled != VARIANT_FALSE) )
  1755. {
  1756. SetUPnPError(L"402");
  1757. return E_INVALIDARG;
  1758. }
  1759. *pMappingType = MappingType;
  1760. return S_OK;
  1761. }