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.

501 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(IN TAKEOWNERSHIP LPVOID lpParam);
  33. HRESULT IsAdapterPhysical(IN const GUID* pGuid, OUT BOOL* bPhysical);
  34. LRESULT
  35. CALLBACK
  36. CHnAcTrayUI_WndProc (
  37. IN HWND hwnd, // window handle
  38. IN UINT uiMessage, // type of message
  39. IN WPARAM wParam, // additional information
  40. IN 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(IN 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. IN HWND hwnd,
  128. IN WPARAM wParam,
  129. IN LPARAM lParam )
  130. {
  131. return (DefWindowProc (hwnd, WM_NOTIFY, wParam, lParam));
  132. }
  133. LRESULT OnHnAcMyWMNotifyIcon(IN HWND hwnd,
  134. IN UINT uiMessage,
  135. IN WPARAM wParam,
  136. IN LPARAM lParam)
  137. {
  138. UINT uiIcon;
  139. UINT uiMouseMsg;
  140. uiIcon = (UINT) wParam;
  141. uiMouseMsg = (UINT) lParam;
  142. switch (uiMouseMsg)
  143. {
  144. case NIN_BALLOONTIMEOUT:
  145. ac_DestroyHnAcTrayUIWindow();
  146. break;
  147. case NIN_BALLOONHIDE:
  148. break;
  149. case NIN_BALLOONSHOW:
  150. break;
  151. case NIN_BALLOONUSERCLICK:
  152. HrRunHomeNetworkWizard(hwnd);
  153. ac_DestroyHnAcTrayUIWindow();
  154. break;
  155. case NIN_KEYSELECT:
  156. break;
  157. case NIN_SELECT:
  158. break;
  159. }
  160. return 0;
  161. }
  162. HRESULT HrRunHomeNetworkWizard(
  163. HWND hwndOwner)
  164. {
  165. TraceFileFunc(ttidShellFolder);
  166. HRESULT hr = S_OK;
  167. WCHAR szPath[MAX_PATH];
  168. hr = SHGetFolderPath(
  169. hwndOwner,
  170. CSIDL_SYSTEM,
  171. NULL,
  172. SHGFP_TYPE_CURRENT,
  173. szPath);
  174. if (SUCCEEDED(hr))
  175. {
  176. HINSTANCE hInst = ::ShellExecute(hwndOwner, NULL, c_szRunDll32, c_szRunHomeNetworkWizard, szPath, SW_SHOW );
  177. if (hInst <= reinterpret_cast<HINSTANCE>(32))
  178. {
  179. hr = HRESULT_FROM_WIN32(static_cast<DWORD>(reinterpret_cast<DWORD_PTR>(hInst)));
  180. }
  181. }
  182. TraceHr(ttidShellFolder, FAL, hr, FALSE, "HrRunHomeNetworkWizard");
  183. return hr;
  184. }
  185. LRESULT ac_DestroyHnAcTrayUIWindow()
  186. {
  187. HRESULT hr = S_OK;
  188. NOTIFYICONDATA nid;
  189. ZeroMemory (&nid, sizeof(nid));
  190. nid.cbSize = sizeof(NOTIFYICONDATA);
  191. nid.hWnd = g_hwndHnAcTray;
  192. nid.uID = 9998;
  193. nid.uFlags = 0;
  194. nid.uCallbackMessage = MYWM_NOTIFYICON;
  195. nid.hIcon = 0;
  196. hr = HrShell_NotifyIcon(NIM_DELETE, &nid);
  197. #if 0
  198. if (!SUCCEEDED(hr)){
  199. MessageBox( NULL,
  200. L"NotifyIcon DELETE failed",
  201. L"This is a test...",
  202. MB_OK | MB_ICONERROR);
  203. }
  204. #endif
  205. EnterCriticalSection(&g_WindowCriticalSection);
  206. if (0 == --g_uWindowRefCount)
  207. {
  208. DestroyWindow(g_hwndHnAcTray);
  209. }
  210. LeaveCriticalSection(&g_WindowCriticalSection);
  211. return 0;
  212. }
  213. LRESULT ac_DeviceChange(IN HWND hWnd,
  214. IN UINT uMessage,
  215. IN WPARAM wParam,
  216. IN LPARAM lParam)
  217. {
  218. // COM is initialized
  219. if(NULL != g_hDeviceChangeNotify)
  220. {
  221. HRESULT hr;
  222. if(DBT_DEVICEARRIVAL == wParam)
  223. {
  224. DEV_BROADCAST_DEVICEINTERFACE* pInfo = (DEV_BROADCAST_DEVICEINTERFACE*)lParam;
  225. if (DBT_DEVTYP_DEVICEINTERFACE == pInfo->dbcc_devicetype)
  226. {
  227. LPWSTR pszNetDeviceGuid = wcsrchr(pInfo->dbcc_name, L'\\'); // need a better way to do this, but shouldn't crash
  228. if(NULL != pszNetDeviceGuid)
  229. {
  230. GUID* pDeviceGuid = reinterpret_cast<GUID*>(CoTaskMemAlloc(sizeof(GUID)));
  231. if(NULL != pDeviceGuid)
  232. {
  233. hr = CLSIDFromString(pszNetDeviceGuid + 1, pDeviceGuid); // +1 is safe, at worst it will point to L'\0'
  234. if(SUCCEEDED(hr))
  235. {
  236. // we have to move this off-uithread
  237. if(0 == QueueUserWorkItem(ac_AsyncDeviceChange, pDeviceGuid, WT_EXECUTELONGFUNCTION))
  238. {
  239. hr = E_FAIL;
  240. }
  241. }
  242. if(FAILED(hr))
  243. {
  244. CoTaskMemFree(pDeviceGuid);
  245. }
  246. }
  247. }
  248. }
  249. }
  250. }
  251. return TRUE;
  252. }
  253. HRESULT ac_Register(IN HWND hWindow)
  254. {
  255. HRESULT hr = S_OK;
  256. #ifdef _WIN64
  257. // The autoconfig service is not available on IA64 (since the homenet wizard
  258. // isn't present)
  259. hr = E_FAIL;
  260. #else
  261. //if the machine is a server SKU we don't create the autocfg stuff
  262. OSVERSIONINFOEXW verInfo = {0};
  263. ULONGLONG ConditionMask = 0;
  264. verInfo.dwOSVersionInfoSize = sizeof(verInfo);
  265. verInfo.wProductType = VER_NT_SERVER;
  266. VER_SET_CONDITION(ConditionMask, VER_PRODUCT_TYPE, VER_GREATER_EQUAL);
  267. if (TRUE == (VerifyVersionInfo(&verInfo, VER_PRODUCT_TYPE, ConditionMask)))
  268. {
  269. hr = E_FAIL;
  270. }
  271. #endif
  272. if(SUCCEEDED(hr))
  273. {
  274. // if machine is joined to a domain don't create the autocfg stuff
  275. LPWSTR pszNameBuffer;
  276. NETSETUP_JOIN_STATUS BufferType;
  277. if (NERR_Success == NetGetJoinInformation(NULL, &pszNameBuffer, &BufferType))
  278. {
  279. NetApiBufferFree(pszNameBuffer);
  280. if(NetSetupDomainName == BufferType)
  281. {
  282. hr = E_FAIL;
  283. }
  284. }
  285. else
  286. {
  287. hr = E_FAIL;
  288. }
  289. }
  290. if(SUCCEEDED(hr))
  291. {
  292. DEV_BROADCAST_DEVICEINTERFACE PnpFilter; // device change notifications for homenet auto config service
  293. ZeroMemory (&PnpFilter, sizeof(PnpFilter));
  294. PnpFilter.dbcc_size = sizeof(PnpFilter);
  295. PnpFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  296. PnpFilter.dbcc_classguid = GUID_NDIS_LAN_CLASS;
  297. g_hDeviceChangeNotify = RegisterDeviceNotification( hWindow, &PnpFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
  298. if(NULL != g_hDeviceChangeNotify)
  299. {
  300. InitializeCriticalSection(&g_WindowCriticalSection); // REVIEW: no memory exception
  301. }
  302. }
  303. return hr;
  304. }
  305. HRESULT ac_Unregister(IN HWND hWindow)
  306. {
  307. if(NULL != g_hDeviceChangeNotify)
  308. {
  309. UnregisterDeviceNotification(g_hDeviceChangeNotify);
  310. g_hDeviceChangeNotify = NULL;
  311. DeleteCriticalSection(&g_WindowCriticalSection);
  312. }
  313. return S_OK;
  314. }
  315. DWORD WINAPI ac_AsyncDeviceChange(IN TAKEOWNERSHIP LPVOID lpParam)
  316. {
  317. HRESULT hr;
  318. GUID* pDeviceGuid = reinterpret_cast<GUID*>(lpParam);
  319. BOOL fUninitializeCOM = TRUE;
  320. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
  321. if (RPC_E_CHANGED_MODE == hr)
  322. {
  323. fUninitializeCOM = FALSE;
  324. hr = S_OK;
  325. }
  326. if(SUCCEEDED(hr))
  327. {
  328. BOOL fPhysical;
  329. hr = IsAdapterPhysical(pDeviceGuid, &fPhysical);
  330. if ( (SUCCEEDED(hr)) && (TRUE == fPhysical) )
  331. {
  332. IHNetCfgMgr* pHomenetConfigManager;
  333. hr = HrCreateInstance(CLSID_HNetCfgMgr, CLSCTX_INPROC, &pHomenetConfigManager);
  334. if (SUCCEEDED(hr))
  335. {
  336. IHNetConnection* pHomenetConnection;
  337. hr = pHomenetConfigManager->GetIHNetConnectionForGuid(pDeviceGuid, TRUE, TRUE, &pHomenetConnection);
  338. if(SUCCEEDED(hr))
  339. {
  340. BOOLEAN fShowBalloon;
  341. hr = pHomenetConnection->ShowAutoconfigBalloon(&fShowBalloon);
  342. if(SUCCEEDED(hr) && fShowBalloon)
  343. {
  344. ac_CreateHnAcTrayUIWindow();
  345. }
  346. ReleaseObj(pHomenetConnection);
  347. }
  348. ReleaseObj(pHomenetConfigManager);
  349. }
  350. }
  351. if(TRUE == fUninitializeCOM)
  352. {
  353. CoUninitialize();
  354. }
  355. }
  356. CoTaskMemFree(pDeviceGuid);
  357. return hr;
  358. }
  359. HRESULT IsAdapterPhysical(IN const GUID* pGuid, OUT BOOL* bPhysical)
  360. {
  361. // com is initialized
  362. HRESULT hr;
  363. *bPhysical = FALSE;
  364. INetCfg* pNetConfig;
  365. hr = HrCreateInstance(CLSID_CNetCfg, CLSCTX_SERVER, &pNetConfig);
  366. if(SUCCEEDED(hr))
  367. {
  368. INetCfgLock* pNetConfigLock;
  369. hr = pNetConfig->QueryInterface(&pNetConfigLock);
  370. if(SUCCEEDED(hr))
  371. {
  372. hr = pNetConfig->Initialize(NULL);
  373. if(SUCCEEDED(hr))
  374. {
  375. GUID NetDevClass = GUID_DEVCLASS_NET;
  376. IEnumNetCfgComponent* pNetConfigComponentEnum;
  377. hr = pNetConfig->EnumComponents(&NetDevClass, &pNetConfigComponentEnum);
  378. if (SUCCEEDED(hr))
  379. {
  380. INetCfgComponent* pNetConfigComponent;
  381. BOOL fFound = FALSE;
  382. ULONG ulFetched;
  383. while (FALSE == fFound && S_OK == pNetConfigComponentEnum->Next(1, &pNetConfigComponent, &ulFetched))
  384. {
  385. Assert(1 == ulFetched);
  386. GUID DeviceGuid;
  387. hr = pNetConfigComponent->GetInstanceGuid( &DeviceGuid );
  388. if (SUCCEEDED(hr) && (InlineIsEqualGUID(DeviceGuid,*pGuid)))
  389. {
  390. fFound = TRUE;
  391. DWORD dwCharacteristics;
  392. hr = pNetConfigComponent->GetCharacteristics(&dwCharacteristics);
  393. if(SUCCEEDED(hr))
  394. {
  395. if(NCF_PHYSICAL & dwCharacteristics)
  396. {
  397. *bPhysical = TRUE;
  398. }
  399. }
  400. }
  401. ReleaseObj(pNetConfigComponent);
  402. }
  403. ReleaseObj(pNetConfigComponentEnum);
  404. }
  405. pNetConfig->Uninitialize();
  406. }
  407. ReleaseObj(pNetConfigLock);
  408. }
  409. ReleaseObj(pNetConfig);
  410. }
  411. return hr;
  412. }