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.

419 lines
14 KiB

  1. #include "stdafx.h"
  2. #include <windows.h>
  3. #include "client.h"
  4. #include "trayicon.h"
  5. #include "resource.h"
  6. #include "util.h"
  7. #include "shellapi.h"
  8. #include "winsock2.h"
  9. static const LPTSTR g_szWindowTitle = TEXT("Internet Gateway Status");
  10. static const LPWSTR g_szWANIPConnectionService = L"urn:schemas-upnp-org:service:WANIPConnection:1";
  11. static const LPWSTR g_szWANPPPConnectionService = L"urn:schemas-upnp-org:service:WANPPPConnection:1";
  12. void CALLBACK ICSClient(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
  13. {
  14. HRESULT hr = S_OK;
  15. // first see if app is already running and if so activate status window
  16. HWND hExistingWindow = FindWindow(NULL, g_szWindowTitle); // check only current winstation, every login session can have an instance
  17. if(NULL != hExistingWindow)
  18. {
  19. if(0 == lstrcmp(lpszCmdLine, TEXT("/force"))) // secret command line to close existing instance and run new one instead
  20. {
  21. ::PostMessage(hExistingWindow, WM_CLOSE, NULL, NULL);
  22. }
  23. else if(0 == lstrcmp(lpszCmdLine, TEXT("/close"))) // secret command line to close existing instance
  24. {
  25. ::PostMessage(hExistingWindow, WM_CLOSE, NULL, NULL);
  26. hr = E_FAIL;
  27. }
  28. else
  29. {
  30. DWORD dwProcessId = NULL;
  31. GetWindowThreadProcessId(hExistingWindow, &dwProcessId); // no documented error return
  32. HMODULE hUser32 = GetModuleHandle(TEXT("user32.dll"));
  33. if(NULL != hUser32)
  34. {
  35. BOOL (WINAPI *pAllowSetForegroundWindow)(DWORD);
  36. pAllowSetForegroundWindow = reinterpret_cast<BOOL (WINAPI*)(DWORD)>(GetProcAddress(hUser32, "AllowSetForegroundWindow"));
  37. if(NULL != pAllowSetForegroundWindow)
  38. {
  39. pAllowSetForegroundWindow(dwProcessId);
  40. }
  41. }
  42. ::PostMessage(hExistingWindow, WM_COMMAND, IDM_TRAYICON_STATUS, NULL);
  43. hr = E_FAIL;
  44. }
  45. }
  46. // if this is first instance then start up the main apartment
  47. if(SUCCEEDED(hr))
  48. {
  49. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  50. if(SUCCEEDED(hr))
  51. {
  52. WSADATA SocketVersionData;
  53. if(0 == WSAStartup(MAKEWORD(2,2), &SocketVersionData))
  54. {
  55. CICSTrayIcon TrayIcon;
  56. HWND hWindow = TrayIcon.Create(NULL, CWindow::rcDefault, g_szWindowTitle, WS_OVERLAPPEDWINDOW);
  57. if(NULL != hWindow)
  58. {
  59. BOOL bGetMessage;
  60. MSG Message;
  61. while(bGetMessage = GetMessage(&Message, NULL, 0, 0) && -1 != bGetMessage)
  62. {
  63. DispatchMessage(&Message);
  64. }
  65. }
  66. WSACleanup();
  67. }
  68. CoUninitialize();
  69. }
  70. }
  71. return;
  72. }
  73. CBeaconFinder::CBeaconFinder()
  74. {
  75. m_hCallbackWindow = NULL;
  76. }
  77. HRESULT CBeaconFinder::Initialize(HWND hCallbackWindow)
  78. {
  79. HRESULT hr = S_OK;
  80. m_hCallbackWindow = hCallbackWindow;
  81. return hr;
  82. }
  83. HRESULT CBeaconFinder::DeviceAdded(LONG lFindData, IUPnPDevice* pDevice)
  84. {
  85. HRESULT hr = S_OK;
  86. if(SUCCEEDED(hr))
  87. {
  88. IInternetGateway* pInternetGateway;
  89. hr = GetServices(pDevice, &pInternetGateway);
  90. if(SUCCEEDED(hr))
  91. {
  92. SendMessage(m_hCallbackWindow, WM_APP_ADDBEACON, 0, reinterpret_cast<LPARAM>(pInternetGateway));
  93. pInternetGateway->Release();
  94. }
  95. }
  96. return hr;
  97. }
  98. HRESULT CBeaconFinder::DeviceRemoved(LONG lFindData, BSTR bstrUDN)
  99. {
  100. SendMessage(m_hCallbackWindow, WM_APP_REMOVEBEACON, 0, reinterpret_cast<LPARAM>(bstrUDN));
  101. return S_OK;
  102. }
  103. HRESULT CBeaconFinder::SearchComplete(LONG lFindData)
  104. {
  105. HRESULT hr = S_OK;
  106. // don't care
  107. return hr;
  108. }
  109. HRESULT CBeaconFinder::GetServices(IUPnPDevice* pDevice, IInternetGateway** ppInternetGateway)
  110. {
  111. HRESULT hr = S_OK;
  112. *ppInternetGateway = NULL;
  113. CComObject<CInternetGateway>* pInternetGateway;
  114. hr = CComObject<CInternetGateway>::CreateInstance(&pInternetGateway);
  115. if(SUCCEEDED(hr))
  116. {
  117. pInternetGateway->AddRef();
  118. BSTR pUniqueDeviceName;
  119. hr = pDevice->get_UniqueDeviceName(&pUniqueDeviceName);
  120. if(SUCCEEDED(hr))
  121. {
  122. hr = pInternetGateway->SetUniqueDeviceName(pUniqueDeviceName);
  123. SysFreeString(pUniqueDeviceName);
  124. }
  125. if(SUCCEEDED(hr))
  126. {
  127. IUPnPService* pOSInfoService;
  128. hr = FindService(pDevice, L"urn:schemas-microsoft-com:service:OSInfo:1", &pOSInfoService); // this service is not required
  129. if(SUCCEEDED(hr))
  130. {
  131. pInternetGateway->SetService(SAHOST_SERVICE_OSINFO, pOSInfoService);
  132. pOSInfoService->Release();
  133. }
  134. IUPnPDevice* pWANDevice;
  135. hr = FindChildDevice(pDevice, L"urn:schemas-upnp-org:device:WANDevice:1", &pWANDevice);
  136. if(SUCCEEDED(hr))
  137. {
  138. IUPnPService* pWANCommonInterfaceConfigService;
  139. hr = FindService(pWANDevice, L"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", &pWANCommonInterfaceConfigService);
  140. if(SUCCEEDED(hr))
  141. {
  142. pInternetGateway->SetService(SAHOST_SERVICE_WANCOMMONINTERFACECONFIG, pWANCommonInterfaceConfigService);
  143. IUPnPDevice* pWANCommonDevice;
  144. hr = FindChildDevice(pWANDevice, L"urn:schemas-upnp-org:device:WANConnectionDevice:1", &pWANCommonDevice);
  145. if(SUCCEEDED(hr))
  146. {
  147. IUPnPService* pWANConnectionService;
  148. hr = FindService(pWANCommonDevice, NULL, &pWANConnectionService);
  149. if(SUCCEEDED(hr))
  150. {
  151. BSTR ServiceType;
  152. hr = pWANConnectionService->get_ServiceTypeIdentifier(&ServiceType);
  153. if(SUCCEEDED(hr))
  154. {
  155. if(0 == wcscmp(ServiceType, g_szWANPPPConnectionService))
  156. {
  157. pInternetGateway->SetMediaType(NCM_SHAREDACCESSHOST_RAS);
  158. pInternetGateway->SetService(SAHOST_SERVICE_WANPPPCONNECTION, pWANConnectionService);
  159. }
  160. else // we can assume this is WANPPPConnectionService
  161. {
  162. pInternetGateway->SetMediaType(NCM_SHAREDACCESSHOST_LAN);
  163. pInternetGateway->SetService(SAHOST_SERVICE_WANIPCONNECTION, pWANConnectionService);
  164. }
  165. SysFreeString(ServiceType);
  166. }
  167. pWANConnectionService->Release();
  168. }
  169. pWANCommonDevice->Release();
  170. }
  171. pWANCommonInterfaceConfigService->Release();
  172. }
  173. pWANDevice->Release();
  174. }
  175. }
  176. if(SUCCEEDED(hr))
  177. {
  178. *ppInternetGateway = static_cast<IInternetGateway*>(pInternetGateway);
  179. (*ppInternetGateway)->AddRef();
  180. }
  181. pInternetGateway->Release();
  182. }
  183. return hr;
  184. }
  185. HRESULT CBeaconFinder::FindChildDevice(IUPnPDevice* pDevice, LPWSTR pszDeviceType, IUPnPDevice** ppChildDevice)
  186. {
  187. HRESULT hr = S_OK;
  188. IUPnPDevices* pDevices;
  189. hr = pDevice->get_Children(&pDevices);
  190. if(SUCCEEDED(hr))
  191. {
  192. hr = FindDevice(pDevices, pszDeviceType, ppChildDevice);
  193. pDevices->Release();
  194. }
  195. return hr;
  196. }
  197. HRESULT CBeaconFinder::FindDevice(IUPnPDevices* pDevices, LPWSTR pszDeviceType, IUPnPDevice** ppChildDevice)
  198. {
  199. HRESULT hr = S_OK;
  200. *ppChildDevice = NULL;
  201. IUnknown* pEnumerator;
  202. hr = pDevices->get__NewEnum(&pEnumerator);
  203. if (SUCCEEDED(hr))
  204. {
  205. IEnumVARIANT* pVariantEnumerator;
  206. hr = pEnumerator->QueryInterface(IID_IEnumVARIANT, reinterpret_cast<void**>(&pVariantEnumerator));
  207. if (SUCCEEDED(hr))
  208. {
  209. VARIANT DeviceVariant;
  210. VariantInit(&DeviceVariant);
  211. pVariantEnumerator->Reset();
  212. // Traverse the collection.
  213. while (NULL == *ppChildDevice && S_OK == pVariantEnumerator->Next(1, &DeviceVariant, NULL))
  214. {
  215. IDispatch * pDeviceDispatch = NULL;
  216. IUPnPDevice * pDevice = NULL;
  217. pDeviceDispatch = V_DISPATCH(&DeviceVariant);
  218. hr = pDeviceDispatch->QueryInterface(IID_IUPnPDevice, reinterpret_cast<void **>(&pDevice));
  219. if (SUCCEEDED(hr))
  220. {
  221. BSTR Type;
  222. hr = pDevice->get_Type(&Type);
  223. if(SUCCEEDED(hr))
  224. {
  225. if(0 == wcscmp(Type, pszDeviceType))
  226. {
  227. *ppChildDevice = pDevice;
  228. pDevice->AddRef();
  229. }
  230. SysFreeString(Type);
  231. }
  232. pDevice->Release();
  233. }
  234. VariantClear(&DeviceVariant);
  235. };
  236. if(NULL == *ppChildDevice)
  237. {
  238. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  239. }
  240. pVariantEnumerator->Release();
  241. }
  242. pEnumerator->Release();
  243. }
  244. return hr;
  245. }
  246. HRESULT CBeaconFinder::FindService(IUPnPDevice* pDevice, LPWSTR pszServiceName, IUPnPService** ppICSService)
  247. {
  248. HRESULT hr;
  249. *ppICSService = NULL;
  250. IUPnPServices* pServices;
  251. hr = pDevice->get_Services(&pServices);
  252. if (SUCCEEDED(hr))
  253. {
  254. IUnknown* pEnumerator;
  255. hr = pServices->get__NewEnum(&pEnumerator);
  256. if (SUCCEEDED(hr))
  257. {
  258. IEnumVARIANT* pVariantEnumerator;
  259. hr = pEnumerator->QueryInterface(IID_IEnumVARIANT, reinterpret_cast<void**>(&pVariantEnumerator));
  260. if (SUCCEEDED(hr))
  261. {
  262. VARIANT ServiceVariant;
  263. VariantInit(&ServiceVariant);
  264. while (NULL == *ppICSService && S_OK == pVariantEnumerator->Next(1, &ServiceVariant, NULL))
  265. {
  266. IDispatch * pServiceDispatch = NULL;
  267. IUPnPService * pService = NULL;
  268. pServiceDispatch = V_DISPATCH(&ServiceVariant);
  269. hr = pServiceDispatch->QueryInterface(IID_IUPnPService, reinterpret_cast<void **>(&pService));
  270. if (SUCCEEDED(hr))
  271. {
  272. BOOL bMatch;
  273. hr = IsServiceMatch(pService, pszServiceName, &bMatch);
  274. if(SUCCEEDED(hr) && TRUE == bMatch)
  275. {
  276. *ppICSService = pService;
  277. pService->AddRef();
  278. }
  279. pService->Release();
  280. }
  281. VariantClear(&ServiceVariant);
  282. }
  283. if(NULL == *ppICSService)
  284. {
  285. hr = E_FAIL;
  286. }
  287. pVariantEnumerator->Release();
  288. }
  289. pEnumerator->Release();
  290. }
  291. pServices->Release();
  292. }
  293. return hr;
  294. }
  295. HRESULT CBeaconFinder::IsServiceMatch(IUPnPService* pService, BSTR SearchCriteria, BOOL* pbMatch)
  296. {
  297. HRESULT hr = S_OK;
  298. *pbMatch = FALSE;
  299. BSTR ServiceType;
  300. hr = pService->get_ServiceTypeIdentifier(&ServiceType);
  301. if(SUCCEEDED(hr))
  302. {
  303. if(NULL != SearchCriteria) // if the caller provides a name then we search for it
  304. {
  305. if(0 == wcscmp(ServiceType, SearchCriteria))
  306. {
  307. *pbMatch = TRUE;
  308. }
  309. }
  310. else // otherwise we enter the special search case
  311. {
  312. if(0 == wcscmp(ServiceType, g_szWANIPConnectionService) || 0 == wcscmp(ServiceType, g_szWANPPPConnectionService))
  313. {
  314. VARIANT OutArgsGetConnectionTypeInfo;
  315. hr = InvokeVoidAction(pService, L"GetConnectionTypeInfo", &OutArgsGetConnectionTypeInfo);
  316. if(SUCCEEDED(hr))
  317. {
  318. VARIANT ConnectionType;
  319. LONG lIndex = 0;
  320. hr = SafeArrayGetElement(V_ARRAY(&OutArgsGetConnectionTypeInfo), &lIndex, &ConnectionType);
  321. if(SUCCEEDED(hr))
  322. {
  323. if(V_VT(&ConnectionType) == VT_BSTR)
  324. {
  325. if(0 == wcscmp(V_BSTR(&ConnectionType), L"IP_Routed"))
  326. {
  327. VARIANT OutArgsGetNATRSIPStatus;
  328. hr = InvokeVoidAction(pService, L"GetNATRSIPStatus", &OutArgsGetNATRSIPStatus);
  329. if(SUCCEEDED(hr))
  330. {
  331. VARIANT NATEnabled;
  332. lIndex = 1;
  333. hr = SafeArrayGetElement(V_ARRAY(&OutArgsGetNATRSIPStatus), &lIndex, &NATEnabled);
  334. if(SUCCEEDED(hr))
  335. {
  336. if(V_VT(&NATEnabled) == VT_BOOL)
  337. {
  338. if(VARIANT_TRUE == V_BOOL(&NATEnabled))
  339. {
  340. *pbMatch = TRUE;
  341. }
  342. }
  343. VariantClear(&NATEnabled);
  344. }
  345. VariantClear(&OutArgsGetNATRSIPStatus);
  346. }
  347. }
  348. }
  349. VariantClear(&ConnectionType);
  350. }
  351. VariantClear(&OutArgsGetConnectionTypeInfo);
  352. }
  353. }
  354. }
  355. SysFreeString(ServiceType);
  356. }
  357. return hr;
  358. }