Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2226 lines
63 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. hr = SearchPortMapping(m_IcsSettingsp,
  727. ulIndex,
  728. 0,
  729. 0,
  730. &MappingProtocolp);
  731. if ( FAILED(hr) )
  732. {
  733. DBG_SPEW(TM_INFO, TL_ERROR,
  734. L"Enum - Seeking the port has failed E(%X)", hr);
  735. SetUPnPError(L"713");
  736. break;
  737. }
  738. //
  739. // Getting the binding - is this how it should be?
  740. //
  741. hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(MappingProtocolp,
  742. &Bindingp);
  743. if ( FAILED(hr) )
  744. {
  745. DBG_SPEW(TM_INFO, TL_ERROR,
  746. L"Enum - Error In Getting Binding for Protocol E(%X)", hr);
  747. break;
  748. }
  749. hr = FillStaticMappingInformation(MappingProtocolp,
  750. Bindingp,
  751. &BoundaryPort,
  752. Protocolp,
  753. &InternalPort,
  754. InternalClientp,
  755. bEnabledp,
  756. Descriptionp);
  757. _ASSERT( SUCCEEDED(hr) );
  758. if ( SUCCEEDED(hr) ) // correct the port Byte Ordering
  759. {
  760. *uExternalPortp = ntohs( BoundaryPort );
  761. *uInternalPortp = ntohs( InternalPort );
  762. }
  763. else
  764. {
  765. DBG_SPEW(TM_INFO, TL_ERROR,
  766. L"Enum - Error In Getting Binding for Protocol E(%X)" , hr);
  767. }
  768. } while ( FALSE );
  769. if ( MappingProtocolp != NULL) MappingProtocolp->Release();
  770. if ( Bindingp != NULL ) Bindingp->Release();
  771. if ( FAILED(hr) )
  772. {
  773. DBG_SPEW(TM_INFO, TL_ERROR,
  774. L"Enum - GetGenericEntry has failed with E(%X)", hr);
  775. }
  776. return hr;
  777. } // GetArrayEntry
  778. HRESULT
  779. CWANConnectionBase::GetSpecificPortMappingEntry(
  780. IN BSTR RemoteHost,
  781. IN USHORT uwExternalPort,
  782. IN BSTR Protocol,
  783. OUT USHORT* puwInternalPort,
  784. OUT BSTR* InternalClientp,
  785. OUT VARIANT_BOOL* pbEnabled,
  786. OUT BSTR* Descriptionp,
  787. OUT ULONG* pulLeaseDuration
  788. )
  789. //
  790. // Note that every port is expected to arrive in HOST order
  791. // and will be returned in HOST order
  792. //
  793. {
  794. HRESULT hr = S_OK;
  795. IHNetPortMappingProtocol* MappingProtocolp = NULL;
  796. IHNetPortMappingBinding* Bindingp = NULL;
  797. USHORT tempExtPort = 0, tempIntPort = 0;
  798. UCHAR searchProtocol = NULL;
  799. _ASSERT( RemoteHost != NULL );
  800. _ASSERT( uwExternalPort != 0 );
  801. _ASSERT( Protocol != NULL );
  802. SysFreeString( *InternalClientp );
  803. SysFreeString( *Descriptionp );
  804. *InternalClientp = NULL;
  805. *Descriptionp = NULL;
  806. tempExtPort = htons( uwExternalPort ); // flip to Network order
  807. DBG_SPEW(TM_INFO, TL_TRACE, L"> GetSpecificPortMapping");
  808. //
  809. // check for access
  810. hr = this->ControlEnabled();
  811. if ( FAILED(hr) )
  812. {
  813. DBG_SPEW(TM_INFO, TL_ERROR, L"Control is Disabled E(%X)", hr);
  814. return hr;
  815. }
  816. if ( 0 == uwExternalPort)
  817. {
  818. DBG_SPEW(TM_INFO, TL_ERROR, L"Parameters Incorrect Port(%hu)", uwExternalPort );
  819. SetUPnPError(L"402");
  820. return E_INVALIDARG;
  821. }
  822. do
  823. {
  824. //
  825. // Resolve the Protocol to the appropriate enum.
  826. //
  827. RESOLVE_PROTOCOL_TYPE(searchProtocol, Protocol);
  828. DBG_SPEW(TM_INFO, TL_INFO,
  829. L"Search Specific - ExtPort (%hu) Protocol (%s)",
  830. htons( tempExtPort ),
  831. (NAT_PROTOCOL_TCP == searchProtocol)?L"TCP":L"UDP");
  832. hr = SearchPortMapping(m_IcsSettingsp,
  833. 0,
  834. tempExtPort,
  835. searchProtocol,
  836. &MappingProtocolp);
  837. if ( FAILED(hr))
  838. {
  839. DBG_SPEW(TM_INFO, TL_ERROR, L"Error or can't get Search E(%X)", hr);
  840. SetUPnPError(L"714");
  841. break;
  842. }
  843. //
  844. // Getting the binding
  845. //
  846. hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(MappingProtocolp,
  847. &Bindingp);
  848. if ( FAILED(hr) )
  849. {
  850. DBG_SPEW(TM_INFO, TL_ERROR,
  851. L"Error In Getting Binding for Protocol E(%X)", hr);
  852. break;
  853. }
  854. hr = FillStaticMappingInformation(MappingProtocolp,
  855. Bindingp,
  856. &tempExtPort,
  857. &Protocol,
  858. &tempIntPort,
  859. InternalClientp,
  860. pbEnabled,
  861. Descriptionp);
  862. _ASSERT( SUCCEEDED(hr) );
  863. *puwInternalPort = ntohs( tempIntPort );
  864. DBG_SPEW(TM_INFO, TL_TRACE,
  865. L"Returning IntClient (%s) IntPort (%hu) IntProtocol (%s), Enabled (%s), Desc (%s)",
  866. *InternalClientp,
  867. *puwInternalPort,
  868. Protocol,
  869. (*pbEnabled == VARIANT_TRUE)?L"TRUE":L"FALSE",
  870. *Descriptionp);
  871. } while ( FALSE );
  872. if ( MappingProtocolp != NULL) MappingProtocolp->Release();
  873. if ( Bindingp != NULL ) Bindingp->Release();
  874. if ( FAILED(hr) )
  875. {
  876. DBG_SPEW(TM_INFO, TL_ERROR, L"Error or can't get Search Done E(%X)", hr);
  877. }
  878. return hr;
  879. }
  880. HRESULT
  881. CWANConnectionBase::AddPortMapping(
  882. BSTR RemoteHost,
  883. USHORT uwExternalPort,
  884. BSTR Protocol,
  885. USHORT uwInternalPort,
  886. BSTR InternalClient,
  887. VARIANT_BOOL bEnabled,
  888. BSTR Description,
  889. ULONG ulLeaseDuration
  890. )
  891. {
  892. HRESULT hr = S_OK;
  893. MAPPING_TYPE MappingType = ePortMappingInvalid;
  894. DBG_SPEW(TM_STATIC, TL_TRACE, L"> AddPortMapping");
  895. //
  896. // Check for Access status
  897. hr = this->ControlEnabled();
  898. if ( SUCCEEDED(hr) )
  899. {
  900. hr = ValidatePortMappingParameters(RemoteHost,
  901. uwExternalPort,
  902. Protocol,
  903. uwInternalPort,
  904. InternalClient,
  905. bEnabled,
  906. Description,
  907. ulLeaseDuration,
  908. &MappingType);
  909. if ( SUCCEEDED(hr) )
  910. {
  911. DBG_SPEW(TM_STATIC, TL_TRACE,
  912. L"Add PortMapping - ExtPort (%hu) Protocol (%s)",
  913. uwExternalPort, Protocol);
  914. DBG_SPEW(TM_STATIC, TL_TRACE,
  915. L"IntClient (%s) IntPort (%hu) Enabled (%s), Desc (%s)",
  916. InternalClient,
  917. uwInternalPort,
  918. (bEnabled == VARIANT_TRUE)?L"TRUE":L"FALSE",
  919. Description);
  920. if ( ePortMappingStatic == MappingType )
  921. {
  922. //
  923. // SECURITY - SECURITY - SECURITY
  924. // Here we're allowing the out-of-proc COM call
  925. // into our service to have SYSTEM access rights.
  926. //
  927. // REASON: UPnP works in LOCAL_SERVICE and COM
  928. // Calls into our service which modify
  929. // the WMI repository will FAIL. This
  930. // Call alleviates that problem by changing
  931. // The Security to that of the SYSTEM
  932. // and is reverted back when the class
  933. // is out of scope by the destructor of.
  934. // CSwitchSecurityContext
  935. //
  936. CSwitchSecurityContext SwSecCxt;
  937. hr = AddStaticPortMapping(RemoteHost,
  938. uwExternalPort,
  939. Protocol,
  940. uwInternalPort,
  941. InternalClient,
  942. bEnabled,
  943. Description,
  944. ulLeaseDuration);
  945. }
  946. else
  947. {
  948. hr = AddDynamicPortMapping(RemoteHost,
  949. uwExternalPort,
  950. Protocol,
  951. uwInternalPort,
  952. InternalClient,
  953. bEnabled,
  954. Description,
  955. ulLeaseDuration);
  956. }
  957. }
  958. }
  959. else
  960. {
  961. DBG_SPEW(TM_STATIC, TL_ERROR, L"Control Disabled E(%X)", hr);
  962. }
  963. return hr;
  964. }
  965. HRESULT
  966. CWANConnectionBase::AddDynamicPortMapping(
  967. BSTR RemoteHost,
  968. USHORT uwExternalPort,
  969. BSTR Protocol,
  970. USHORT uwInternalPort,
  971. BSTR InternalClient,
  972. VARIANT_BOOL bEnabled,
  973. BSTR Description,
  974. ULONG ulLeaseDuration
  975. )
  976. {
  977. //
  978. // We currently don't handle any Dynamic Port Redirections.
  979. //
  980. DBG_SPEW(TM_DYNAMIC, TL_ERROR, L"Only Static Mappings are allowed [Lease]");
  981. SetUPnPError(L"725");
  982. return E_INVALIDARG;
  983. }
  984. HRESULT
  985. CWANConnectionBase::AddStaticPortMapping(
  986. BSTR RemoteHost,
  987. USHORT uwExternalPort,
  988. BSTR Protocol,
  989. USHORT uwInternalPort,
  990. BSTR InternalClient,
  991. VARIANT_BOOL bEnabled,
  992. BSTR Description,
  993. ULONG ulLeaseDuration
  994. )
  995. {
  996. HRESULT hr = S_OK;
  997. UCHAR ProtocolType = 0;
  998. IHNetProtocolSettings* ProtocolSettingsp = NULL;
  999. IHNetPortMappingProtocol* PortMappingProtocolp = NULL;
  1000. IHNetPortMappingBinding* PortMappingBindingp = NULL;
  1001. ULONG ClientAddr = 0;
  1002. BOOLEAN bLetsEnable = FALSE;
  1003. BOOLEAN bCreatedProtocol = FALSE;
  1004. ULONG tempStrLen = 0;
  1005. WCHAR tempPortStr[] = L"00000";
  1006. LPOLESTR tempStr = NULL;
  1007. USHORT tempExtPort = 0, tempIntPort = 0;
  1008. BSTR ProtocolFromBinding = NULL;
  1009. BSTR ClientFromBinding = NULL;
  1010. BSTR DescriptionFromBinding = NULL;
  1011. VARIANT_BOOL boolEnabled;
  1012. _ASSERT( uwExternalPort );
  1013. _ASSERT( uwInternalPort );
  1014. //
  1015. // Convert both ends to Network Order
  1016. //
  1017. tempExtPort = htons( uwExternalPort );
  1018. tempIntPort = htons( uwInternalPort );
  1019. //
  1020. // Convert VARIANT_BOOL to boolean
  1021. //
  1022. bLetsEnable = ( bEnabled == VARIANT_TRUE );
  1023. //
  1024. // Process the Operation
  1025. //
  1026. do
  1027. {
  1028. RESOLVE_PROTOCOL_TYPE(ProtocolType, Protocol);
  1029. //
  1030. // IF there is no description crate one
  1031. // using PORT and PROTOCOL
  1032. //
  1033. if ( wcscmp(Description, L"\0") == 0 )
  1034. {
  1035. // Get Internal ClientName + the seperator
  1036. tempStrLen = ( SysStringLen( InternalClient ) + 1 );
  1037. // Get port len + plus the seperator
  1038. _itow ( uwExternalPort, tempPortStr, 10);
  1039. tempStrLen += (wcslen (tempPortStr) + 1);
  1040. // Get Protocol Name
  1041. tempStrLen += SysStringLen( Protocol );
  1042. // Create out from these two
  1043. tempStr = (LPOLESTR)CoTaskMemAlloc( (tempStrLen + 1) * sizeof(WCHAR) );
  1044. if ( tempStr != NULL )
  1045. {
  1046. _snwprintf(tempStr, tempStrLen, L"%s-%s-%s",
  1047. InternalClient, tempPortStr, Protocol);
  1048. tempStr[ tempStrLen ] = L'\0';
  1049. Description = SysAllocString ( tempStr );
  1050. }
  1051. if ( (tempStr == NULL) || (Description == NULL) )
  1052. {
  1053. DBG_SPEW(TM_STATIC, TL_ERROR, L"Can't Initialize Strings - out of mem");
  1054. hr = E_OUTOFMEMORY;
  1055. break;
  1056. }
  1057. }
  1058. //
  1059. // Find Existing Mapping
  1060. //
  1061. hr = SearchPortMapping(m_IcsSettingsp,
  1062. 0,
  1063. tempExtPort,
  1064. ProtocolType,
  1065. &PortMappingProtocolp);
  1066. //
  1067. // if found it is in Edit Mode.
  1068. //
  1069. if ( SUCCEEDED(hr) )
  1070. {
  1071. hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(PortMappingProtocolp,
  1072. &PortMappingBindingp);
  1073. _ASSERT( SUCCEEDED(hr) );
  1074. if ( FAILED(hr) )
  1075. {
  1076. DBG_SPEW(TM_STATIC, TL_ERROR,
  1077. L"Can't get Binding for Port Mapping E(X)", hr);
  1078. _ASSERT( FALSE );
  1079. break;
  1080. }
  1081. //
  1082. // Fill the information
  1083. //
  1084. hr = FillStaticMappingInformation(PortMappingProtocolp,
  1085. PortMappingBindingp,
  1086. &tempExtPort,
  1087. &ProtocolFromBinding,
  1088. &tempIntPort,
  1089. &ClientFromBinding,
  1090. &boolEnabled,
  1091. &DescriptionFromBinding);
  1092. if ( FAILED(hr) )
  1093. {
  1094. DBG_SPEW(TM_STATIC, TL_ERROR,
  1095. L"Filling has failed for Mapping Information E(%X)", hr);
  1096. break;
  1097. }
  1098. //
  1099. // If the existin Mapping was disabled we should be able to change
  1100. // the Internal Client
  1101. //
  1102. if ( boolEnabled == VARIANT_TRUE )
  1103. {
  1104. if ( _wcsicmp( InternalClient, ClientFromBinding) != 0 ) // if diff then error
  1105. {
  1106. hr = E_INVALIDARG;
  1107. DBG_SPEW(TM_STATIC, TL_ERROR,
  1108. L"Will not change the internal client for an enabled PortMapping");
  1109. SetUPnPError(L"718");
  1110. break;
  1111. }
  1112. }
  1113. //
  1114. // if the Internal Port has changed reflect the change
  1115. //
  1116. if ( tempIntPort != htons( uwInternalPort ) )
  1117. {
  1118. tempIntPort = htons( uwInternalPort );
  1119. hr = PortMappingBindingp->SetTargetPort( tempIntPort );
  1120. _ASSERT( SUCCEEDED(hr) );
  1121. if ( FAILED(hr) )
  1122. {
  1123. DBG_SPEW(TM_STATIC, TL_ERROR, L"Changin Internal Port has Failed E(%X)", hr);
  1124. break;
  1125. }
  1126. }
  1127. //
  1128. // Set the description if changed
  1129. //
  1130. if ( _wcsicmp(DescriptionFromBinding, Description) != 0)
  1131. {
  1132. hr = PortMappingProtocolp->SetName(Description);
  1133. if ( FAILED(hr) )
  1134. {
  1135. hr = E_INVALIDARG;
  1136. DBG_SPEW(TM_STATIC, TL_ERROR, L"Set Name has failed E(%X)", hr);
  1137. break;
  1138. }
  1139. }
  1140. }
  1141. else
  1142. {
  1143. //
  1144. // Start Getting the Interface
  1145. //
  1146. hr = m_IcsSettingsp->QueryInterface(IID_IHNetProtocolSettings,
  1147. reinterpret_cast<void**>(&ProtocolSettingsp));
  1148. if ( SUCCEEDED(hr) )
  1149. {
  1150. hr = ProtocolSettingsp->CreatePortMappingProtocol(Description,
  1151. ProtocolType,
  1152. tempExtPort,
  1153. &PortMappingProtocolp);
  1154. if ( SUCCEEDED(hr) )
  1155. {
  1156. hr = m_pHomenetConnection->GetBindingForPortMappingProtocol(PortMappingProtocolp,
  1157. &PortMappingBindingp);
  1158. if ( SUCCEEDED(hr) )
  1159. {
  1160. hr = PortMappingBindingp->SetTargetPort( tempIntPort );
  1161. _ASSERT( SUCCEEDED(hr) );
  1162. if ( FAILED(hr) )
  1163. {
  1164. DBG_SPEW(TM_STATIC, TL_ERROR, L"Set Target Port has Failed E(%X)", hr);
  1165. }
  1166. bCreatedProtocol = TRUE;
  1167. }
  1168. else
  1169. {
  1170. DBG_SPEW(TM_STATIC, TL_ERROR,
  1171. L"Getting Binding has Failed E(X)", hr);
  1172. PortMappingProtocolp->Delete();
  1173. break;
  1174. }
  1175. }
  1176. else
  1177. {
  1178. DBG_SPEW(TM_STATIC, TL_ERROR,
  1179. L"Creating the PortMapping has Failed E(%X)", hr);
  1180. break;
  1181. }
  1182. }
  1183. else
  1184. {
  1185. DBG_SPEW(TM_STATIC, TL_ERROR,
  1186. L"Getting the Protocol Settings has failed E(X)", hr);
  1187. break;
  1188. }
  1189. }
  1190. //
  1191. // Setting the Client name / address
  1192. // For Edit mode we already checked wether this code will be run or not.
  1193. //
  1194. if (
  1195. ( wcscmp(L"0.0.0.0", InternalClient) != 0 ) &&
  1196. ( InternalClient[0] != L'\0' )
  1197. )
  1198. {
  1199. ClientAddr = INET_ADDR((LPOLESTR) InternalClient );
  1200. //
  1201. // if the address is not valid (INADDR_NONE)
  1202. // and if the address is different than Broadcast address (which also is INADDR_NONE)
  1203. //
  1204. if ( (ClientAddr == INADDR_NONE) && wcscmp(L"255.255.255.255", InternalClient) )
  1205. {
  1206. hr = PortMappingBindingp->SetTargetComputerName( InternalClient );
  1207. }
  1208. else
  1209. {
  1210. hr = PortMappingBindingp->SetTargetComputerAddress( ClientAddr );
  1211. }
  1212. _ASSERT( SUCCEEDED(hr) );
  1213. if ( SUCCEEDED(hr) )
  1214. {
  1215. hr = PortMappingBindingp->SetEnabled( bLetsEnable );
  1216. }
  1217. if ( FAILED(hr) ) DBG_SPEW(TM_STATIC, TL_ERROR, L"Client Add/Edit IntClient failed - E(%X)", hr);
  1218. }
  1219. if ( FAILED(hr) && (TRUE == bCreatedProtocol) )
  1220. {
  1221. DBG_SPEW(TM_STATIC, TL_ERROR, L"Client Add / Edit failed - E(%X)", hr);
  1222. hr = PortMappingProtocolp->Delete();
  1223. }
  1224. } while ( FALSE );
  1225. if ( tempStr != NULL)
  1226. {
  1227. CoTaskMemFree ( tempStr );
  1228. SysFreeString ( Description ); // you can free a NULL string.
  1229. }
  1230. if ( ProtocolFromBinding ) SysFreeString(ProtocolFromBinding);
  1231. if ( ClientFromBinding ) SysFreeString(ClientFromBinding);
  1232. if ( DescriptionFromBinding ) SysFreeString(DescriptionFromBinding);
  1233. if ( PortMappingBindingp != NULL ) PortMappingBindingp->Release();
  1234. if ( PortMappingProtocolp != NULL ) PortMappingProtocolp->Release();
  1235. if ( ProtocolSettingsp != NULL ) ProtocolSettingsp->Release();
  1236. if ( FAILED(hr) ) { DBG_SPEW(TM_STATIC, TL_ERROR, L"Error Returning hr (%X)", hr); }
  1237. return hr;
  1238. } // CWANConnectionBase :: AddStaticPortMapping
  1239. HRESULT
  1240. CWANConnectionBase::DeletePortMapping(
  1241. BSTR RemoteHost,
  1242. USHORT uwExternalPort,
  1243. BSTR Protocol
  1244. )
  1245. {
  1246. HRESULT hr = S_OK;
  1247. UCHAR ProtocolType = 0;
  1248. IHNetPortMappingProtocol* PortMappingProtocolp = NULL;
  1249. USHORT tempExtPort = 0;
  1250. //
  1251. // SECURITY - SECURITY - SECURITY
  1252. // Here we're allowing the out-of-proc COM call
  1253. // into our service to have SYSTEM access rights.
  1254. //
  1255. // REASON: UPnP works in LOCAL_SERVICE and COM
  1256. // Calls into our service which modify
  1257. // the WMI repository will FAIL. This
  1258. // Call alleviates that problem by changing
  1259. // The Security to that of the SYSTEM
  1260. // and is reverted back when the class
  1261. // is out of scope by the destructor of.
  1262. // CSwitchSecurityContext
  1263. //
  1264. CSwitchSecurityContext SwSecCxt;
  1265. _ASSERT( RemoteHost != NULL );
  1266. _ASSERT( uwExternalPort != 0 );
  1267. _ASSERT( Protocol != NULL );
  1268. DBG_SPEW(TM_STATIC, TL_TRACE, L"> DeletePortMapping");
  1269. //
  1270. // check for access
  1271. hr = this->ControlEnabled();
  1272. if ( FAILED(hr) ) { return hr; }
  1273. //
  1274. // Convert to Network order
  1275. //
  1276. tempExtPort = htons(uwExternalPort );
  1277. DBG_SPEW(TM_STATIC, TL_INFO,
  1278. L"Search Specific - ExtPort (%hu) Protocol (%s)",
  1279. uwExternalPort, Protocol);
  1280. do
  1281. {
  1282. RESOLVE_PROTOCOL_TYPE( ProtocolType, Protocol );
  1283. hr = SearchPortMapping(m_IcsSettingsp,
  1284. 0,
  1285. tempExtPort,
  1286. ProtocolType,
  1287. &PortMappingProtocolp);
  1288. if ( FAILED(hr) )
  1289. {
  1290. DBG_SPEW(TM_STATIC, TL_ERROR, L"Error in Searching E(%X)", hr );
  1291. SetUPnPError(L"714");
  1292. break;
  1293. }
  1294. hr = PortMappingProtocolp->Delete();
  1295. if ( FAILED(hr) )
  1296. {
  1297. DBG_SPEW(TM_STATIC, TL_ERROR,
  1298. L"ProtocolMapping deletion failure, Might be Built in E(%X)", hr );
  1299. }
  1300. PortMappingProtocolp->Release();
  1301. } while ( FALSE );
  1302. if ( FAILED(hr) ) DBG_SPEW(TM_STATIC, TL_ERROR, L"Delete failed with hr - %X", hr);
  1303. return hr;
  1304. }
  1305. HRESULT CWANConnectionBase::GetExternalIPAddress(BSTR* pExternalIPAddress)
  1306. {
  1307. HRESULT hr = S_OK;
  1308. SysFreeString(*pExternalIPAddress);
  1309. *pExternalIPAddress = NULL;
  1310. hr = get_ExternalIPAddress(pExternalIPAddress);
  1311. return hr;
  1312. }
  1313. HRESULT CWANConnectionBase::ControlEnabled()
  1314. {
  1315. HRESULT hr = S_OK;
  1316. // check the reg key. Only disable if key exists and is 0.
  1317. HKEY hKey;
  1318. DWORD dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_SHAREDACCESSCLIENTKEYPATH, 0, KEY_QUERY_VALUE, &hKey);
  1319. if(ERROR_SUCCESS == dwError) // if this fails we assume it is on, set the box, and commit on apply
  1320. {
  1321. DWORD dwType;
  1322. DWORD dwData = 0;
  1323. DWORD dwSize = sizeof(dwData);
  1324. dwError = RegQueryValueEx(hKey, REGVAL_SHAREDACCESSCLIENTENABLECONTROL, 0, &dwType, reinterpret_cast<LPBYTE>(&dwData), &dwSize);
  1325. if(ERROR_SUCCESS == dwError && REG_DWORD == dwType && 0 == dwData)
  1326. {
  1327. hr = E_ACCESSDENIED;
  1328. }
  1329. RegCloseKey(hKey);
  1330. }
  1331. return hr;
  1332. }
  1333. HRESULT
  1334. SearchPortMapping(
  1335. IN IHNetIcsSettings* IcsSettingsp,
  1336. IN OPTIONAL ULONG searchIndex,
  1337. IN OPTIONAL USHORT searchPort,
  1338. IN OPTIONAL UCHAR searchProtocol,
  1339. OUT IHNetPortMappingProtocol **Protocolpp
  1340. )
  1341. //
  1342. // Two ways of Seeking an entry..
  1343. // 1) By Index.. Enumerate until you hit the giventh Index.
  1344. // 2) Seeks and retrieves Port and ProtocolType
  1345. //
  1346. {
  1347. HRESULT hr = S_OK;
  1348. IHNetProtocolSettings* ProtocolSettingsp = NULL;
  1349. IEnumHNetPortMappingProtocols* EnumProtocolsp = NULL;
  1350. IHNetPortMappingProtocol* tempProtocolp = NULL;
  1351. USHORT ProtocolPort = 0;
  1352. UCHAR ProtocolType = 0;
  1353. BOOLEAN bFound = FALSE;
  1354. ULONG iIndex = 0;
  1355. DBG_SPEW(TM_STATIC, TL_ERROR, L" > SearchPortMapping ");
  1356. //
  1357. // Index = 0 is a valid search
  1358. // searchPort and searcProtocol should exist both or not.
  1359. //
  1360. _ASSERT( !((searchPort == NULL) ^ (searchProtocol == 0)) );
  1361. _ASSERT( IcsSettingsp != NULL );
  1362. _ASSERT( Protocolpp != NULL );
  1363. do
  1364. {
  1365. hr = IcsSettingsp->QueryInterface(IID_IHNetProtocolSettings,
  1366. reinterpret_cast<void**>(&ProtocolSettingsp));
  1367. if( FAILED(hr) )
  1368. {
  1369. DBG_SPEW(TM_STATIC, TL_ERROR,
  1370. L"Query Interface failed for ProtocolSettingsp E(%X)", hr);
  1371. break;
  1372. }
  1373. hr = ProtocolSettingsp->EnumPortMappingProtocols(&EnumProtocolsp);
  1374. if ( FAILED(hr) )
  1375. {
  1376. DBG_SPEW(TM_STATIC, TL_ERROR,
  1377. L"Enum Interface can't be retrieved E(%X)", hr);
  1378. break;
  1379. }
  1380. while( (FALSE == bFound) &&
  1381. (S_OK == EnumProtocolsp->Next(1, &tempProtocolp, NULL)) )
  1382. {
  1383. if ( searchPort != 0 )
  1384. {
  1385. hr = tempProtocolp->GetPort( &ProtocolPort );
  1386. if ( SUCCEEDED(hr) )
  1387. {
  1388. hr = tempProtocolp->GetIPProtocol(&ProtocolType);
  1389. }
  1390. if( FAILED(hr) )
  1391. {
  1392. DBG_SPEW(TM_STATIC, TL_ERROR, L"Search info Failure E(%X)", hr);
  1393. }
  1394. else if((searchPort == ProtocolPort) &&
  1395. (ProtocolType == searchProtocol))
  1396. {
  1397. bFound = TRUE;
  1398. }
  1399. }
  1400. else // if the search key == the Index
  1401. {
  1402. if ( iIndex == searchIndex )
  1403. {
  1404. bFound = TRUE;
  1405. }
  1406. }
  1407. //
  1408. // if Nothing is found
  1409. if (FALSE == bFound)
  1410. {
  1411. tempProtocolp->Release();
  1412. }
  1413. iIndex++;
  1414. }
  1415. EnumProtocolsp->Release();
  1416. } while ( FALSE );
  1417. if(ProtocolSettingsp != NULL)
  1418. {
  1419. ProtocolSettingsp->Release();
  1420. }
  1421. if( (bFound == TRUE) &&
  1422. (tempProtocolp != NULL))
  1423. {
  1424. *Protocolpp = tempProtocolp;
  1425. }
  1426. else
  1427. {
  1428. return E_INVALIDARG;
  1429. }
  1430. return hr;
  1431. }
  1432. HRESULT
  1433. FillStaticMappingInformation(
  1434. IN IHNetPortMappingProtocol* MappingProtocolp,
  1435. IN OPTIONAL IHNetPortMappingBinding* Bindingp,
  1436. OUT PUSHORT uExternalPortp,
  1437. OUT BSTR* Protocolp,
  1438. OUT PUSHORT uInternalPortp,
  1439. OUT BSTR* InternalClientp,
  1440. OUT VARIANT_BOOL* bEnabledp,
  1441. OUT BSTR* Descriptionp
  1442. )
  1443. //
  1444. // Note that Will return the port in Network Byte Order
  1445. //
  1446. {
  1447. HRESULT hr = S_OK;
  1448. UCHAR ProtocolType = NULL;
  1449. LPOLESTR szInternalHostAddr = NULL;
  1450. LPOLESTR szDescription = NULL;
  1451. BOOLEAN bEnabled = FALSE;
  1452. BOOLEAN bUseName = FALSE;
  1453. ULONG InternalHostAddr = 0;
  1454. _ASSERT ( uExternalPortp != NULL );
  1455. _ASSERT ( Protocolp != NULL );
  1456. _ASSERT ( InternalClientp != NULL );
  1457. _ASSERT ( bEnabledp != NULL );
  1458. _ASSERT ( Descriptionp != NULL );
  1459. _ASSERT ( MappingProtocolp != NULL );
  1460. _ASSERT ( Bindingp != NULL );
  1461. *uExternalPortp = 0;
  1462. *Protocolp = NULL;
  1463. *InternalClientp = NULL;
  1464. *bEnabledp = VARIANT_FALSE;
  1465. *Descriptionp = NULL;
  1466. DBG_SPEW(TM_STATIC, TL_TRACE, L"> FillStaticMappingInformation");
  1467. do
  1468. {
  1469. //
  1470. // Description
  1471. //
  1472. hr = MappingProtocolp->GetName(&szDescription);
  1473. if ( FAILED(hr) )
  1474. {
  1475. DBG_SPEW(TM_STATIC, TL_ERROR, L"Getting the Name has failed E(%X)", hr);
  1476. break;
  1477. }
  1478. BOOLEAN fBuiltin = FALSE;
  1479. hr = MappingProtocolp->GetBuiltIn( &fBuiltin );
  1480. _ASSERT( SUCCEEDED(hr) );
  1481. if ( fBuiltin )
  1482. {
  1483. #define BUILTIN_KEY L" [MICROSOFT]"
  1484. UINT uiLength = wcslen(szDescription );
  1485. uiLength += wcslen(BUILTIN_KEY);
  1486. *Descriptionp = SysAllocStringLen(NULL, uiLength);
  1487. if ( *Descriptionp )
  1488. {
  1489. wcscpy (*Descriptionp, szDescription);
  1490. wcscat (*Descriptionp, BUILTIN_KEY);
  1491. }
  1492. }
  1493. else
  1494. {
  1495. *Descriptionp = SysAllocString(szDescription);
  1496. }
  1497. if(*Descriptionp == NULL)
  1498. {
  1499. DBG_SPEW(TM_STATIC, TL_ERROR,
  1500. L"Memory Allocation for Description has Failed");
  1501. hr = E_OUTOFMEMORY;
  1502. break;
  1503. }
  1504. //
  1505. // Protocol
  1506. //
  1507. hr = MappingProtocolp->GetIPProtocol(&ProtocolType);
  1508. _ASSERT( SUCCEEDED(hr) );
  1509. if ( ProtocolType == NAT_PROTOCOL_TCP )
  1510. {
  1511. *Protocolp = SysAllocString(L"TCP");
  1512. }
  1513. else if ( ProtocolType == NAT_PROTOCOL_UDP )
  1514. {
  1515. *Protocolp = SysAllocString(L"UDP");
  1516. }
  1517. else
  1518. {
  1519. _ASSERT( FALSE );
  1520. }
  1521. if (*Protocolp == NULL)
  1522. {
  1523. DBG_SPEW(TM_STATIC, TL_ERROR,
  1524. L"Memory Allocation for Description has Failed");
  1525. hr = E_OUTOFMEMORY;
  1526. break;
  1527. }
  1528. //
  1529. // External Port
  1530. //
  1531. hr = MappingProtocolp->GetPort( uExternalPortp );
  1532. _ASSERT( SUCCEEDED(hr) );
  1533. if ( FAILED(hr) )
  1534. {
  1535. DBG_SPEW(TM_STATIC, TL_ERROR,
  1536. L"GetPort for Protocol has failed E(%X)", hr);
  1537. break;
  1538. }
  1539. // Getting the Binding Information
  1540. if ( Bindingp != NULL )
  1541. {
  1542. //
  1543. // Enabled
  1544. hr = Bindingp->GetEnabled(&bEnabled);
  1545. _ASSERT( SUCCEEDED(hr) );
  1546. if ( bEnabled == TRUE)
  1547. {
  1548. *bEnabledp = VARIANT_TRUE;
  1549. }
  1550. else
  1551. {
  1552. *bEnabledp = VARIANT_FALSE;
  1553. }
  1554. hr = Bindingp->GetTargetPort( uInternalPortp );
  1555. _ASSERT( SUCCEEDED(hr) );
  1556. if ( FAILED(hr) )
  1557. {
  1558. DBG_SPEW(TM_STATIC, TL_ERROR,
  1559. L"GetPort for Binding has failed E(%X)", hr);
  1560. break;
  1561. }
  1562. //
  1563. // InternalClient
  1564. hr = Bindingp->GetCurrentMethod(&bUseName);
  1565. if( SUCCEEDED(hr) )
  1566. {
  1567. if ( bUseName == TRUE)
  1568. {
  1569. hr = Bindingp->GetTargetComputerName(&szInternalHostAddr);
  1570. if ( FAILED(hr) )
  1571. {
  1572. break;
  1573. }
  1574. _ASSERT( SUCCEEDED(hr) );
  1575. }
  1576. else
  1577. {
  1578. hr = Bindingp->GetTargetComputerAddress(&InternalHostAddr);
  1579. _ASSERT( SUCCEEDED(hr) );
  1580. if ( FAILED(hr) )
  1581. {
  1582. break;
  1583. }
  1584. //
  1585. // IF the address is Loopback change it to a name which would make more
  1586. // sense to any client who sees it.
  1587. //
  1588. if ( INADDR_LOOPBACK == htonl(InternalHostAddr) )
  1589. {
  1590. ULONG uCount = 0;
  1591. if ( 0 == GetComputerNameEx( ComputerNameDnsHostname, NULL, &uCount) )
  1592. {
  1593. if ( (ERROR_MORE_DATA == GetLastError()) )
  1594. {
  1595. szInternalHostAddr =
  1596. (LPOLESTR) CoTaskMemAlloc( uCount * sizeof(WCHAR) );
  1597. if ( NULL != szInternalHostAddr )
  1598. {
  1599. if (!GetComputerNameEx(ComputerNameDnsHostname,
  1600. szInternalHostAddr,
  1601. &uCount))
  1602. {
  1603. hr = HRESULT_FROM_WIN32( GetLastError() );
  1604. break;
  1605. }
  1606. }
  1607. else
  1608. {
  1609. hr = E_OUTOFMEMORY;
  1610. break;
  1611. }
  1612. }
  1613. else
  1614. {
  1615. hr = E_FAIL;
  1616. break;
  1617. }
  1618. }
  1619. }
  1620. else if ( 0 != InternalHostAddr )
  1621. {
  1622. szInternalHostAddr = INET_NTOW_TS( InternalHostAddr );
  1623. }
  1624. else
  1625. {
  1626. szInternalHostAddr = (LPOLESTR) CoTaskMemAlloc( sizeof(WCHAR) );
  1627. if ( NULL != szInternalHostAddr) szInternalHostAddr[0] = 0;
  1628. }
  1629. if ( szInternalHostAddr == NULL )
  1630. {
  1631. hr = E_OUTOFMEMORY;
  1632. break;
  1633. }
  1634. } // if Name method
  1635. }
  1636. *InternalClientp = SysAllocString( szInternalHostAddr );
  1637. if ( *InternalClientp == NULL)
  1638. {
  1639. DBG_SPEW(TM_STATIC, TL_ERROR, L"Mem Allocation for Internal Client Name");
  1640. hr = E_OUTOFMEMORY;
  1641. break;
  1642. }
  1643. } // if bindingp
  1644. } while ( FALSE );
  1645. if ( szDescription ) CoTaskMemFree( szDescription );
  1646. if ( szInternalHostAddr ) CoTaskMemFree( szInternalHostAddr );
  1647. if ( FAILED(hr) )
  1648. {
  1649. if(*Protocolp) { SysFreeString(*Protocolp); *Protocolp = NULL; }
  1650. if(*InternalClientp) { SysFreeString(*InternalClientp); *InternalClientp = NULL;}
  1651. if(*Descriptionp) { SysFreeString(*Descriptionp); *Descriptionp = NULL;}
  1652. }
  1653. return hr;
  1654. }
  1655. inline HRESULT
  1656. ValidatePortMappingParameters
  1657. (
  1658. IN BSTR RemoteHost,
  1659. IN USHORT uwExternalPort,
  1660. IN BSTR Protocol,
  1661. IN USHORT uwInternalPort,
  1662. IN BSTR InternalClient,
  1663. IN VARIANT_BOOL bEnabled,
  1664. IN BSTR Description,
  1665. IN ULONG ulLeaseDuration,
  1666. OUT MAPPING_TYPE* pMappingType
  1667. )
  1668. //
  1669. // Decide wether a Mapping is to be dynamic or static
  1670. // Validate the parameters pre-emptively
  1671. //
  1672. {
  1673. MAPPING_TYPE MappingType = ePortMappingInvalid;
  1674. _ASSERT( RemoteHost != NULL );
  1675. _ASSERT( Protocol != NULL );
  1676. _ASSERT( Protocol[0] != 0 );
  1677. _ASSERT( Description != NULL );
  1678. _ASSERT( uwInternalPort != 0 );
  1679. _ASSERT( pMappingType != NULL );
  1680. _ASSERT( InternalClient != NULL );
  1681. _ASSERT( RemoteHost[0] == 0 );
  1682. //
  1683. // An Internal Port as well as an external Port should exist all time
  1684. //
  1685. if ( (0 == uwInternalPort) || (0 == uwExternalPort) )
  1686. {
  1687. SetUPnPError(L"716");
  1688. return E_INVALIDARG;
  1689. }
  1690. //
  1691. // is this a dynamic request?
  1692. //
  1693. if ( 0 != ulLeaseDuration )
  1694. {
  1695. MappingType = ePortMappingDynamic;
  1696. }
  1697. else
  1698. {
  1699. MappingType = ePortMappingStatic;
  1700. }
  1701. //
  1702. // A Dynamic Port Mapping needs to be with
  1703. // an Internal Client
  1704. //
  1705. if (
  1706. ( ePortMappingDynamic == MappingType ) &&
  1707. ( InternalClient[0] == L'\0' )
  1708. )
  1709. {
  1710. SetUPnPError(L"402");
  1711. return E_INVALIDARG;
  1712. }
  1713. //
  1714. // A remote Host is defined.. we can't process this
  1715. //
  1716. if ( RemoteHost[0] != L'\0' )
  1717. {
  1718. SetUPnPError(L"726");
  1719. return E_INVALIDARG;
  1720. }
  1721. //
  1722. // Check the bEnabled bool value
  1723. //
  1724. if ( (bEnabled != VARIANT_TRUE) && (bEnabled != VARIANT_FALSE) )
  1725. {
  1726. SetUPnPError(L"402");
  1727. return E_INVALIDARG;
  1728. }
  1729. *pMappingType = MappingType;
  1730. return S_OK;
  1731. }