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.

496 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000
  5. //
  6. // File: ac_CTrayUiCpp.h
  7. //
  8. // Contents: Home Networking Auto Config Tray Icon UI code
  9. //
  10. // Author: jeffsp 9/27/2000
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "pch.h"
  14. #pragma hdrstop
  15. #include "ac_CTrayUi.h"
  16. #include "foldinc.h" // Standard shell\tray includes
  17. #include <nsres.h>
  18. #include "foldres.h"
  19. #include "traymsgs.h"
  20. #include <dbt.h>
  21. #include <ndisguid.h>
  22. #include "lm.h"
  23. UINT g_uWindowRefCount = 0;
  24. HWND g_hwndHnAcTray = NULL;
  25. UINT_PTR g_HnAcTimerHandle = NULL;
  26. HDEVNOTIFY g_hDeviceChangeNotify = NULL;
  27. CRITICAL_SECTION g_WindowCriticalSection;
  28. const WCHAR c_szHnAcTrayClass[] = L"Home Net Auto Config Tray";
  29. const DWORD c_dwAutoConfigBalloonTimeoutSeconds = 15;
  30. static const WCHAR c_szRunDll32[] = L"rundll32.exe";
  31. static const WCHAR c_szRunHomeNetworkWizard[] = L"hnetwiz.dll,HomeNetWizardRunDll";
  32. DWORD WINAPI ac_AsyncDeviceChange(LPVOID lpParam);
  33. HRESULT IsAdapterPhysical(GUID* pGuid, BOOL* bPhysical);
  34. LRESULT
  35. CALLBACK
  36. CHnAcTrayUI_WndProc (
  37. HWND hwnd, // window handle
  38. UINT uiMessage, // type of message
  39. WPARAM wParam, // additional information
  40. LPARAM lParam) // additional information
  41. {
  42. switch (uiMessage)
  43. {
  44. case WM_CREATE:
  45. return OnHnAcTrayWmCreate(hwnd);
  46. case MYWM_NOTIFYICON:
  47. return OnHnAcMyWMNotifyIcon(hwnd, uiMessage, wParam, lParam);
  48. case WM_DESTROY:
  49. g_hwndHnAcTray = NULL;
  50. PostQuitMessage(0);
  51. break;
  52. default: // Passes it on if unproccessed
  53. return (DefWindowProc (hwnd, uiMessage, wParam, lParam));
  54. }
  55. return (0);
  56. }
  57. HRESULT ac_CreateHnAcTrayUIWindow()
  58. {
  59. HRESULT hr = S_OK;
  60. // create a hidden window
  61. //
  62. WNDCLASS wndclass;
  63. ZeroMemory (&wndclass, sizeof(wndclass));
  64. wndclass.lpfnWndProc = CHnAcTrayUI_WndProc;
  65. wndclass.hInstance = _Module.GetResourceInstance();
  66. wndclass.lpszClassName = c_szHnAcTrayClass;
  67. RegisterClass (&wndclass);
  68. EnterCriticalSection(&g_WindowCriticalSection); // we have to protect this since we are on a thread pool callback
  69. if(0 == g_uWindowRefCount++)
  70. {
  71. CreateWindow(c_szHnAcTrayClass,
  72. c_szHnAcTrayClass,
  73. WS_OVERLAPPEDWINDOW,
  74. CW_USEDEFAULT,
  75. CW_USEDEFAULT,
  76. CW_USEDEFAULT,
  77. CW_USEDEFAULT,
  78. NULL,
  79. NULL,
  80. _Module.GetResourceInstance(),
  81. NULL);
  82. }
  83. LeaveCriticalSection(&g_WindowCriticalSection);
  84. BOOL bGetMessage;
  85. MSG Message;
  86. while(bGetMessage = GetMessage(&Message, g_hwndHnAcTray, 0, 0) && -1 != bGetMessage)
  87. {
  88. DispatchMessage(&Message);
  89. }
  90. return hr;
  91. }
  92. LRESULT OnHnAcTrayWmCreate(HWND hwnd)
  93. {
  94. g_hwndHnAcTray = hwnd;
  95. HICON hiconTray;
  96. HRESULT hr = S_OK;
  97. hiconTray = LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_CONFOLD_HOMENET_WIZARD));
  98. if (hiconTray)
  99. {
  100. NOTIFYICONDATA nid;
  101. ZeroMemory (&nid, sizeof(nid));
  102. nid.cbSize = sizeof(NOTIFYICONDATA);
  103. nid.hWnd = g_hwndHnAcTray;
  104. nid.uID = 9998;
  105. nid.uFlags = NIF_MESSAGE | NIF_ICON; // | NIF_STATE;
  106. nid.uCallbackMessage = MYWM_NOTIFYICON;
  107. nid.hIcon = hiconTray;
  108. // nid.dwState = NIS_HIDDEN;
  109. // nid.dwStateMask = nid.dwState;
  110. // Configure the balloon tip
  111. {
  112. nid.uFlags |= NIF_INFO;
  113. nid.dwInfoFlags = NIIF_INFO;
  114. nid.uTimeout = c_dwAutoConfigBalloonTimeoutSeconds * 1000;
  115. // WARNING these fields are 64 and 256 chars max
  116. lstrcpyW(nid.szInfoTitle, SzLoadIds(IDS_AUTOCONFIGTRAY_RUN_HOME_NET_WIZARD_BALLOON_TITLE));
  117. lstrcpyW(nid.szInfo, SzLoadIds(IDS_AUTOCONFIGTRAY_RUN_HOME_NET_WIZARD_BALLOON));
  118. }
  119. hr = HrShell_NotifyIcon(NIM_ADD, &nid);
  120. nid.uVersion = NOTIFYICON_VERSION;
  121. nid.uFlags = 0;
  122. hr = HrShell_NotifyIcon(NIM_SETVERSION, &nid);
  123. }
  124. return 0;
  125. }
  126. LRESULT OnHnAcTrayWmNotify(
  127. HWND hwnd,
  128. WPARAM wParam,
  129. LPARAM lParam )
  130. {
  131. return (DefWindowProc (hwnd, WM_NOTIFY, wParam, lParam));
  132. }
  133. LRESULT OnHnAcMyWMNotifyIcon(HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
  134. {
  135. UINT uiIcon;
  136. UINT uiMouseMsg;
  137. uiIcon = (UINT) wParam;
  138. uiMouseMsg = (UINT) lParam;
  139. switch (uiMouseMsg)
  140. {
  141. case NIN_BALLOONTIMEOUT:
  142. ac_DestroyHnAcTrayUIWindow();
  143. break;
  144. case NIN_BALLOONHIDE:
  145. break;
  146. case NIN_BALLOONSHOW:
  147. break;
  148. case NIN_BALLOONUSERCLICK:
  149. HrRunHomeNetworkWizard(hwnd);
  150. ac_DestroyHnAcTrayUIWindow();
  151. break;
  152. case NIN_KEYSELECT:
  153. break;
  154. case NIN_SELECT:
  155. break;
  156. }
  157. return 0;
  158. }
  159. HRESULT HrRunHomeNetworkWizard(
  160. HWND hwndOwner)
  161. {
  162. TraceFileFunc(ttidShellFolder);
  163. HRESULT hr = S_OK;
  164. WCHAR szPath[MAX_PATH];
  165. hr = SHGetFolderPath(
  166. hwndOwner,
  167. CSIDL_SYSTEM,
  168. NULL,
  169. SHGFP_TYPE_CURRENT,
  170. szPath);
  171. if (SUCCEEDED(hr))
  172. {
  173. HINSTANCE hInst = ::ShellExecute(hwndOwner, NULL, c_szRunDll32, c_szRunHomeNetworkWizard, szPath, SW_SHOW );
  174. if (hInst <= reinterpret_cast<HINSTANCE>(32))
  175. {
  176. hr = HRESULT_FROM_WIN32(static_cast<DWORD>(reinterpret_cast<DWORD_PTR>(hInst)));
  177. }
  178. }
  179. TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrRunHomeNetworkWizard");
  180. return hr;
  181. }
  182. LRESULT ac_DestroyHnAcTrayUIWindow()
  183. {
  184. HRESULT hr = S_OK;
  185. NOTIFYICONDATA nid;
  186. ZeroMemory (&nid, sizeof(nid));
  187. nid.cbSize = sizeof(NOTIFYICONDATA);
  188. nid.hWnd = g_hwndHnAcTray;
  189. nid.uID = 9998;
  190. nid.uFlags = 0;
  191. nid.uCallbackMessage = MYWM_NOTIFYICON;
  192. nid.hIcon = 0;
  193. hr = HrShell_NotifyIcon(NIM_DELETE, &nid);
  194. #if 0
  195. if (!SUCCEEDED(hr)){
  196. MessageBox( NULL,
  197. L"NotifyIcon DELETE failed",
  198. L"This is a test...",
  199. MB_OK | MB_ICONERROR);
  200. }
  201. #endif
  202. EnterCriticalSection(&g_WindowCriticalSection);
  203. if(0 == --g_uWindowRefCount)
  204. {
  205. DestroyWindow(g_hwndHnAcTray);
  206. }
  207. LeaveCriticalSection(&g_WindowCriticalSection);
  208. return 0;
  209. }
  210. LRESULT ac_DeviceChange(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
  211. {
  212. // COM is initialized
  213. if(NULL != g_hDeviceChangeNotify)
  214. {
  215. HRESULT hr;
  216. if(DBT_DEVICEARRIVAL == wParam)
  217. {
  218. DEV_BROADCAST_DEVICEINTERFACE* pInfo = (DEV_BROADCAST_DEVICEINTERFACE*)lParam;
  219. if (DBT_DEVTYP_DEVICEINTERFACE == pInfo->dbcc_devicetype)
  220. {
  221. LPWSTR pszNetDeviceGuid = wcsrchr(pInfo->dbcc_name, L'\\'); // need a better way to do this, but shouldn't crash
  222. if(NULL != pszNetDeviceGuid)
  223. {
  224. GUID* pDeviceGuid = reinterpret_cast<GUID*>(CoTaskMemAlloc(sizeof(GUID)));
  225. if(NULL != pDeviceGuid)
  226. {
  227. hr = CLSIDFromString(pszNetDeviceGuid + 1, pDeviceGuid); // +1 is safe, at worst it will point to L'\0'
  228. if(SUCCEEDED(hr))
  229. {
  230. // we have to move this off-uithread
  231. if(0 == QueueUserWorkItem(ac_AsyncDeviceChange, pDeviceGuid, WT_EXECUTELONGFUNCTION))
  232. {
  233. hr = E_FAIL;
  234. }
  235. }
  236. if(FAILED(hr))
  237. {
  238. CoTaskMemFree(pDeviceGuid);
  239. }
  240. }
  241. }
  242. }
  243. }
  244. }
  245. return TRUE;
  246. }
  247. HRESULT ac_Register(HWND hWindow)
  248. {
  249. HRESULT hr = S_OK;
  250. #ifdef _WIN64
  251. // The autoconfig service is not available on IA64 (since the homenet wizard
  252. // isn't present)
  253. hr = E_FAIL;
  254. #else
  255. //if the machine is a server SKU we don't create the autocfg stuff
  256. OSVERSIONINFOEXW verInfo = {0};
  257. ULONGLONG ConditionMask = 0;
  258. verInfo.dwOSVersionInfoSize = sizeof(verInfo);
  259. verInfo.wProductType = VER_NT_SERVER;
  260. VER_SET_CONDITION(ConditionMask, VER_PRODUCT_TYPE, VER_GREATER_EQUAL);
  261. if(TRUE == (VerifyVersionInfo(&verInfo, VER_PRODUCT_TYPE, ConditionMask)))
  262. {
  263. hr = E_FAIL;
  264. }
  265. #endif
  266. if(SUCCEEDED(hr))
  267. {
  268. // if machine is joined to a domain don't create the autocfg stuff
  269. LPWSTR pszNameBuffer;
  270. NETSETUP_JOIN_STATUS BufferType;
  271. if(NERR_Success == NetGetJoinInformation(NULL, &pszNameBuffer, &BufferType))
  272. {
  273. NetApiBufferFree(pszNameBuffer);
  274. if(NetSetupDomainName == BufferType)
  275. {
  276. hr = E_FAIL;
  277. }
  278. }
  279. else
  280. {
  281. hr = E_FAIL;
  282. }
  283. }
  284. if(SUCCEEDED(hr))
  285. {
  286. DEV_BROADCAST_DEVICEINTERFACE PnpFilter; // device change notifications for homenet auto config service
  287. ZeroMemory (&PnpFilter, sizeof(PnpFilter));
  288. PnpFilter.dbcc_size = sizeof(PnpFilter);
  289. PnpFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  290. PnpFilter.dbcc_classguid = GUID_NDIS_LAN_CLASS;
  291. g_hDeviceChangeNotify = RegisterDeviceNotification( hWindow, &PnpFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
  292. if(NULL != g_hDeviceChangeNotify)
  293. {
  294. InitializeCriticalSection(&g_WindowCriticalSection); // REVIEW: no memory exception
  295. }
  296. }
  297. return hr;
  298. }
  299. HRESULT ac_Unregister(HWND hWindow)
  300. {
  301. if(NULL != g_hDeviceChangeNotify)
  302. {
  303. UnregisterDeviceNotification(g_hDeviceChangeNotify);
  304. g_hDeviceChangeNotify = NULL;
  305. DeleteCriticalSection(&g_WindowCriticalSection);
  306. }
  307. return S_OK;
  308. }
  309. DWORD WINAPI ac_AsyncDeviceChange(LPVOID lpParam)
  310. {
  311. HRESULT hr;
  312. GUID* pDeviceGuid = reinterpret_cast<GUID*>(lpParam);
  313. BOOL fUninitializeCOM = TRUE;
  314. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
  315. if (RPC_E_CHANGED_MODE == hr)
  316. {
  317. fUninitializeCOM = FALSE;
  318. hr = S_OK;
  319. }
  320. if(SUCCEEDED(hr))
  321. {
  322. BOOL fPhysical;
  323. hr = IsAdapterPhysical(pDeviceGuid, &fPhysical);
  324. if(SUCCEEDED(hr) && TRUE == fPhysical)
  325. {
  326. IHNetCfgMgr* pHomenetConfigManager;
  327. hr = HrCreateInstance(CLSID_HNetCfgMgr, CLSCTX_INPROC, &pHomenetConfigManager);
  328. if(SUCCEEDED(hr))
  329. {
  330. IHNetConnection* pHomenetConnection;
  331. hr = pHomenetConfigManager->GetIHNetConnectionForGuid(pDeviceGuid, TRUE, TRUE, &pHomenetConnection);
  332. if(SUCCEEDED(hr))
  333. {
  334. BOOLEAN fShowBalloon;
  335. hr = pHomenetConnection->ShowAutoconfigBalloon(&fShowBalloon);
  336. if(SUCCEEDED(hr) && fShowBalloon)
  337. {
  338. ac_CreateHnAcTrayUIWindow();
  339. }
  340. ReleaseObj(pHomenetConnection);
  341. }
  342. ReleaseObj(pHomenetConfigManager);
  343. }
  344. }
  345. if(TRUE == fUninitializeCOM)
  346. {
  347. CoUninitialize();
  348. }
  349. }
  350. CoTaskMemFree(pDeviceGuid);
  351. return hr;
  352. }
  353. HRESULT IsAdapterPhysical(GUID* pGuid, BOOL* bPhysical)
  354. {
  355. // com is initialized
  356. HRESULT hr;
  357. *bPhysical = FALSE;
  358. INetCfg* pNetConfig;
  359. hr = HrCreateInstance(CLSID_CNetCfg, CLSCTX_SERVER, &pNetConfig);
  360. if(SUCCEEDED(hr))
  361. {
  362. INetCfgLock* pNetConfigLock;
  363. hr = pNetConfig->QueryInterface(&pNetConfigLock);
  364. if(SUCCEEDED(hr))
  365. {
  366. hr = pNetConfig->Initialize(NULL);
  367. if(SUCCEEDED(hr))
  368. {
  369. GUID NetDevClass = GUID_DEVCLASS_NET;
  370. IEnumNetCfgComponent* pNetConfigComponentEnum;
  371. hr = pNetConfig->EnumComponents(&NetDevClass, &pNetConfigComponentEnum);
  372. if (SUCCEEDED(hr))
  373. {
  374. INetCfgComponent* pNetConfigComponent;
  375. BOOL fFound = FALSE;
  376. ULONG ulFetched;
  377. while (FALSE == fFound && S_OK == pNetConfigComponentEnum->Next(1, &pNetConfigComponent, &ulFetched))
  378. {
  379. Assert(1 == ulFetched);
  380. GUID DeviceGuid;
  381. hr = pNetConfigComponent->GetInstanceGuid( &DeviceGuid );
  382. if (SUCCEEDED(hr) && (InlineIsEqualGUID(DeviceGuid,*pGuid)))
  383. {
  384. fFound = TRUE;
  385. DWORD dwCharacteristics;
  386. hr = pNetConfigComponent->GetCharacteristics(&dwCharacteristics);
  387. if(SUCCEEDED(hr))
  388. {
  389. if(NCF_PHYSICAL & dwCharacteristics)
  390. {
  391. *bPhysical = TRUE;
  392. }
  393. }
  394. }
  395. ReleaseObj(pNetConfigComponent);
  396. }
  397. ReleaseObj(pNetConfigComponentEnum);
  398. }
  399. pNetConfig->Uninitialize();
  400. }
  401. ReleaseObj(pNetConfigLock);
  402. }
  403. ReleaseObj(pNetConfig);
  404. }
  405. return hr;
  406. }