1 /*
2 * PROJECT: ReactOS Shell
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: CNetConnectionPropertyUi: Network connection configuration dialog
5 * COPYRIGHT: Copyright 2008 Johannes Anderwald (johannes.anderwald@reactos.org)
6 */
7
8 #include "precomp.h"
9
CNetConnectionPropertyUi()10 CNetConnectionPropertyUi::CNetConnectionPropertyUi() :
11 m_pProperties(NULL)
12 {
13 }
14
~CNetConnectionPropertyUi()15 CNetConnectionPropertyUi::~CNetConnectionPropertyUi()
16 {
17 if (m_pNCfg)
18 m_pNCfg->Uninitialize();
19
20 // Note: MSDN says we can only unlock after INetCfg::Uninitialize
21 if (m_NCfgLock)
22 m_NCfgLock->ReleaseWriteLock();
23
24 if (m_pProperties)
25 NcFreeNetconProperties(m_pProperties);
26 }
27
28 VOID
AddItemToListView(HWND hDlgCtrl,PNET_ITEM pItem,LPWSTR szName,BOOL bChecked,UINT Image)29 AddItemToListView(HWND hDlgCtrl, PNET_ITEM pItem, LPWSTR szName, BOOL bChecked, UINT Image)
30 {
31 LVITEMW lvItem;
32
33 lvItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
34 lvItem.pszText = szName;
35 lvItem.lParam = (LPARAM)pItem;
36 lvItem.iImage = Image;
37 lvItem.iItem = 0x7fffffff; // Append at the end of the list.
38 lvItem.iSubItem = 0;
39 lvItem.iItem = SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&lvItem);
40 ListView_SetCheckState(hDlgCtrl, lvItem.iItem, bChecked);
41 }
42
43 BOOL
GetINetCfgComponent(INetCfg * pNCfg,INetCfgComponent ** pOut)44 CNetConnectionPropertyUi::GetINetCfgComponent(INetCfg *pNCfg, INetCfgComponent ** pOut)
45 {
46 LPWSTR pName;
47 HRESULT hr;
48 ULONG Fetched;
49 CComPtr<IEnumNetCfgComponent> pEnumCfg;
50
51 hr = pNCfg->EnumComponents(&GUID_DEVCLASS_NET, &pEnumCfg);
52 if (FAILED_UNEXPECTEDLY(hr))
53 return FALSE;
54
55 while (TRUE)
56 {
57 CComPtr<INetCfgComponent> pNCg;
58 hr = pEnumCfg->Next(1, &pNCg, &Fetched);
59 if (hr != S_OK)
60 break;
61
62 hr = pNCg->GetDisplayName(&pName);
63 if (SUCCEEDED(hr))
64 {
65 if (!_wcsicmp(pName, m_pProperties->pszwDeviceName))
66 {
67 *pOut = pNCg.Detach();
68 return TRUE;
69 }
70 CoTaskMemFree(pName);
71 }
72 }
73 return FALSE;
74 }
75
76 VOID
EnumComponents(HWND hDlgCtrl,INetCfg * pNCfg,const GUID * CompGuid,UINT Type,PSP_CLASSIMAGELIST_DATA pCILD)77 CNetConnectionPropertyUi::EnumComponents(HWND hDlgCtrl, INetCfg *pNCfg, const GUID *CompGuid, UINT Type, PSP_CLASSIMAGELIST_DATA pCILD)
78 {
79 HRESULT hr;
80 CComPtr<IEnumNetCfgComponent> pENetCfg;
81 ULONG Num;
82 DWORD dwCharacteristics;
83 LPOLESTR pDisplayName, pHelpText;
84 PNET_ITEM pItem;
85 BOOL bChecked;
86
87 hr = pNCfg->EnumComponents(CompGuid, &pENetCfg);
88 if (FAILED_UNEXPECTEDLY(hr))
89 return;
90
91 while (TRUE)
92 {
93 CComPtr<INetCfgComponent> pNCfgComp;
94 CComPtr<INetCfgComponentBindings> pCompBind;
95 CComPtr<INetCfgComponent> pAdapterCfgComp;
96
97 hr = pENetCfg->Next(1, &pNCfgComp, &Num);
98 if (hr != S_OK)
99 break;
100
101 hr = pNCfgComp->GetCharacteristics(&dwCharacteristics);
102 if (SUCCEEDED(hr) && (dwCharacteristics & NCF_HIDDEN))
103 continue;
104
105 pDisplayName = NULL;
106 pHelpText = NULL;
107 hr = pNCfgComp->GetDisplayName(&pDisplayName);
108 hr = pNCfgComp->GetHelpText(&pHelpText);
109 bChecked = FALSE;
110 hr = pNCfgComp->QueryInterface(IID_PPV_ARG(INetCfgComponentBindings, &pCompBind));
111 if (SUCCEEDED(hr))
112 {
113 if (GetINetCfgComponent(pNCfg, &pAdapterCfgComp))
114 {
115 hr = pCompBind->IsBoundTo(pAdapterCfgComp);
116 if (hr == S_OK)
117 bChecked = TRUE;
118 }
119 }
120
121 pItem = static_cast<NET_ITEM*>(CoTaskMemAlloc(sizeof(NET_ITEM)));
122 if (!pItem)
123 continue;
124
125 pItem->dwCharacteristics = dwCharacteristics;
126 pItem->szHelp = pHelpText;
127 pItem->Type = (NET_TYPE)Type;
128 pItem->pNCfgComp = pNCfgComp.Detach();
129 pItem->NumPropDialogOpen = 0;
130
131 INT image;
132 if (!pCILD->ImageList || !SetupDiGetClassImageIndex(pCILD, CompGuid, &image))
133 image = I_IMAGENONE;
134 AddItemToListView(hDlgCtrl, pItem, pDisplayName, bChecked, image);
135 CoTaskMemFree(pDisplayName);
136 }
137 }
138
139 VOID
InitializeLANPropertiesUIDlg(HWND hwndDlg)140 CNetConnectionPropertyUi::InitializeLANPropertiesUIDlg(HWND hwndDlg)
141 {
142 HRESULT hr;
143 CComPtr<INetCfg> pNCfg;
144 CComPtr<INetCfgLock> pNCfgLock;
145 HWND hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMPONENTSLIST);
146 LVCOLUMNW lc;
147 RECT rc;
148 DWORD dwStyle;
149 LPWSTR pDisplayName;
150
151 SendDlgItemMessageW(hwndDlg, IDC_NETCARDNAME, WM_SETTEXT, 0, (LPARAM)m_pProperties->pszwDeviceName);
152 if (m_pProperties->dwCharacter & NCCF_SHOW_ICON)
153 {
154 /* check show item on taskbar*/
155 SendDlgItemMessageW(hwndDlg, IDC_SHOWTASKBAR, BM_SETCHECK, BST_CHECKED, 0);
156 }
157 if (m_pProperties->dwCharacter & NCCF_NOTIFY_DISCONNECTED)
158 {
159 /* check notify item */
160 SendDlgItemMessageW(hwndDlg, IDC_NOTIFYNOCONNECTION, BM_SETCHECK, BST_CHECKED, 0);
161 }
162
163 memset(&lc, 0, sizeof(LV_COLUMN));
164 lc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
165 lc.fmt = LVCFMT_FIXED_WIDTH;
166 if (GetClientRect(hDlgCtrl, &rc))
167 {
168 lc.mask |= LVCF_WIDTH;
169 lc.cx = rc.right - rc.left;
170 }
171 lc.pszText = (LPWSTR)L"";
172 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&lc);
173 dwStyle = (DWORD) SendMessage(hDlgCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
174 dwStyle = dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES;
175 SendMessage(hDlgCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
176
177 hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(INetCfg, &pNCfg));
178 if (FAILED(hr))
179 return;
180
181 hr = pNCfg->QueryInterface(IID_PPV_ARG(INetCfgLock, &pNCfgLock));
182 hr = pNCfgLock->AcquireWriteLock(100, L"", &pDisplayName);
183 if (hr == S_FALSE)
184 {
185 CoTaskMemFree(pDisplayName);
186 return;
187 }
188
189 hr = pNCfg->Initialize(NULL);
190 if (FAILED_UNEXPECTEDLY(hr))
191 {
192 pNCfgLock->ReleaseWriteLock();
193 return;
194 }
195
196 m_pNCfg = pNCfg;
197 m_NCfgLock = pNCfgLock;
198
199 SP_CLASSIMAGELIST_DATA spcid;
200 spcid.cbSize = sizeof(spcid);
201 if (SetupDiGetClassImageList(&spcid))
202 {
203 HIMAGELIST hIL = ImageList_Duplicate(spcid.ImageList);
204 ListView_SetImageList(hDlgCtrl, hIL, LVSIL_SMALL);
205 }
206 else
207 {
208 spcid.ImageList = NULL;
209 }
210
211 EnumComponents(hDlgCtrl, pNCfg, &GUID_DEVCLASS_NETCLIENT, NET_TYPE_CLIENT, &spcid);
212 EnumComponents(hDlgCtrl, pNCfg, &GUID_DEVCLASS_NETSERVICE, NET_TYPE_SERVICE, &spcid);
213 EnumComponents(hDlgCtrl, pNCfg, &GUID_DEVCLASS_NETTRANS, NET_TYPE_PROTOCOL, &spcid);
214
215 if (spcid.ImageList)
216 SetupDiDestroyClassImageList(&spcid);
217
218 ListView_SetItemState(hDlgCtrl, 0, -1, LVIS_FOCUSED | LVIS_SELECTED);
219 }
220
221 VOID
ShowNetworkComponentProperties(HWND hwndDlg)222 CNetConnectionPropertyUi::ShowNetworkComponentProperties(HWND hwndDlg)
223 {
224 LVITEMW lvItem;
225 HWND hDlgCtrl;
226 UINT Index, Count;
227 HRESULT hr;
228 INetCfgComponent *pNCfgComp;
229 PNET_ITEM pItem;
230
231 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMPONENTSLIST);
232 Count = ListView_GetItemCount(hDlgCtrl);
233 if (!Count)
234 return;
235
236 ZeroMemory(&lvItem, sizeof(LVITEMW));
237 lvItem.mask = LVIF_PARAM | LVIF_STATE;
238 lvItem.stateMask = (UINT)-1;
239 for (Index = 0; Index < Count; Index++)
240 {
241 lvItem.iItem = Index;
242 if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)&lvItem))
243 {
244 if (lvItem.state & LVIS_SELECTED)
245 break;
246 }
247 }
248
249 if (!(lvItem.state & LVIS_SELECTED))
250 {
251 return;
252 }
253
254 pItem = (PNET_ITEM)lvItem.lParam;
255 pNCfgComp = (INetCfgComponent*)pItem->pNCfgComp;
256 hr = pNCfgComp->RaisePropertyUi(GetParent(hwndDlg), NCRP_QUERY_PROPERTY_UI, (INetConnectionConnectUi*)this);
257 if (SUCCEEDED(hr))
258 {
259 hr = pNCfgComp->RaisePropertyUi(GetParent(hwndDlg), NCRP_SHOW_PROPERTY_UI, (INetConnectionConnectUi*)this);
260 }
261 }
262
263 INT_PTR
264 CALLBACK
LANPropertiesUIDlg(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)265 CNetConnectionPropertyUi::LANPropertiesUIDlg(
266 HWND hwndDlg,
267 UINT uMsg,
268 WPARAM wParam,
269 LPARAM lParam)
270 {
271 PROPSHEETPAGE *page;
272 LPNMLISTVIEW lppl;
273 LVITEMW li;
274 PNET_ITEM pItem;
275 CNetConnectionPropertyUi * This;
276 LPPSHNOTIFY lppsn;
277 DWORD dwShowIcon, dwNotifyDisconnect;
278 HRESULT hr;
279 WCHAR szKey[200];
280 LPOLESTR pStr;
281 HKEY hKey;
282
283 switch (uMsg)
284 {
285 case WM_INITDIALOG:
286 page = (PROPSHEETPAGE*)lParam;
287 This = (CNetConnectionPropertyUi*)page->lParam;
288 This->InitializeLANPropertiesUIDlg(hwndDlg);
289 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)This);
290 return TRUE;
291 case WM_NOTIFY:
292 lppl = (LPNMLISTVIEW) lParam;
293 lppsn = (LPPSHNOTIFY) lParam;
294 if (lppsn->hdr.code == PSN_APPLY)
295 {
296 This = (CNetConnectionPropertyUi*)GetWindowLongPtr(hwndDlg, DWLP_USER);
297 if (This->m_pNCfg)
298 {
299 hr = This->m_pNCfg->Apply();
300 if (FAILED(hr))
301 return PSNRET_INVALID;
302 }
303
304 if (SendDlgItemMessageW(hwndDlg, IDC_SHOWTASKBAR, BM_GETCHECK, 0, 0) == BST_CHECKED)
305 dwShowIcon = 1;
306 else
307 dwShowIcon = 0;
308
309 if (SendDlgItemMessageW(hwndDlg, IDC_NOTIFYNOCONNECTION, BM_GETCHECK, 0, 0) == BST_CHECKED)
310 dwNotifyDisconnect = 1;
311 else
312 dwNotifyDisconnect = 0;
313
314 //NOTE: Windows write these setting with the undocumented INetLanConnection::SetInfo
315 if (StringFromCLSID((CLSID)This->m_pProperties->guidId, &pStr) == ERROR_SUCCESS)
316 {
317 swprintf(szKey, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", pStr);
318 CoTaskMemFree(pStr);
319 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKey, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
320 {
321 RegSetValueExW(hKey, L"ShowIcon", 0, REG_DWORD, (LPBYTE)&dwShowIcon, sizeof(DWORD));
322 RegSetValueExW(hKey, L"IpCheckingEnabled", 0, REG_DWORD, (LPBYTE)&dwNotifyDisconnect, sizeof(DWORD));
323 RegCloseKey(hKey);
324 }
325 }
326
327 return PSNRET_NOERROR;
328 }
329 #if 0
330 else if (lppsn->hdr.code == PSN_CANCEL)
331 {
332 This = (CNetConnectionPropertyUi*)GetWindowLongPtr(hwndDlg, DWLP_USER);
333 if (This->m_pNCfg)
334 {
335 hr = This->m_pNCfg->Cancel();
336 if (SUCCEEDED(hr))
337 return PSNRET_NOERROR;
338 else
339 return PSNRET_INVALID;
340 }
341 return PSNRET_NOERROR;
342 }
343 #endif
344 if (lppl->hdr.code == NM_DBLCLK)
345 {
346 This = (CNetConnectionPropertyUi*)GetWindowLongPtr(hwndDlg, DWLP_USER);
347 This->ShowNetworkComponentProperties(hwndDlg);
348 return FALSE;
349 }
350
351 if (lppl->hdr.code == LVN_ITEMCHANGING)
352 {
353 ZeroMemory(&li, sizeof(li));
354 li.mask = LVIF_PARAM;
355 li.iItem = lppl->iItem;
356 if (!SendMessageW(lppl->hdr.hwndFrom, LVM_GETITEMW, 0, (LPARAM)&li))
357 return TRUE;
358
359 pItem = (PNET_ITEM)li.lParam;
360 if (!pItem)
361 return TRUE;
362
363 if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED))
364 {
365 /* new focused item */
366 if (pItem->dwCharacteristics & NCF_NOT_USER_REMOVABLE)
367 EnableWindow(GetDlgItem(hwndDlg, IDC_UNINSTALL), FALSE);
368 else
369 EnableWindow(GetDlgItem(hwndDlg, IDC_UNINSTALL), TRUE);
370
371 if (pItem->dwCharacteristics & NCF_HAS_UI)
372 EnableWindow(GetDlgItem(hwndDlg, IDC_PROPERTIES), TRUE);
373 else
374 EnableWindow(GetDlgItem(hwndDlg, IDC_PROPERTIES), FALSE);
375
376 SendDlgItemMessageW(hwndDlg, IDC_DESCRIPTION, WM_SETTEXT, 0, (LPARAM)pItem->szHelp);
377 }
378 }
379 break;
380 case WM_COMMAND:
381 if (LOWORD(wParam) == IDC_PROPERTIES)
382 {
383 This = (CNetConnectionPropertyUi*) GetWindowLongPtr(hwndDlg, DWLP_USER);
384 This->ShowNetworkComponentProperties(hwndDlg);
385 return FALSE;
386 }
387 else if (LOWORD(wParam) == IDC_CONFIGURE)
388 {
389 LPOLESTR DeviceInstanceID;
390 This = (CNetConnectionPropertyUi*)GetWindowLongPtr(hwndDlg, DWLP_USER);
391
392 if (This->GetDeviceInstanceID(&DeviceInstanceID))
393 {
394 WCHAR wszCmd[2*MAX_PATH];
395 StringCbPrintfW(wszCmd, sizeof(wszCmd), L"rundll32.exe devmgr.dll,DeviceProperties_RunDLL /DeviceID %s", DeviceInstanceID);
396 CoTaskMemFree(DeviceInstanceID);
397
398 STARTUPINFOW si;
399 PROCESS_INFORMATION pi;
400 ZeroMemory(&si, sizeof(si));
401 si.cb = sizeof(si);
402 if (!CreateProcessW(NULL, wszCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
403 break;
404
405 CloseHandle(pi.hProcess);
406 CloseHandle(pi.hThread);
407 }
408 }
409 break;
410 }
411 return FALSE;
412 }
413
414 BOOL
GetDeviceInstanceID(OUT LPOLESTR * DeviceInstanceID)415 CNetConnectionPropertyUi::GetDeviceInstanceID(
416 OUT LPOLESTR *DeviceInstanceID)
417 {
418 LPOLESTR pStr, pResult;
419 HKEY hKey;
420 DWORD dwInstanceID;
421 WCHAR szKeyName[2*MAX_PATH];
422 WCHAR szInstanceID[2*MAX_PATH];
423
424 if (StringFromCLSID(m_pProperties->guidId, &pStr) != ERROR_SUCCESS)
425 {
426 // failed to convert guid to string
427 return FALSE;
428 }
429
430 StringCbPrintfW(szKeyName, sizeof(szKeyName), L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", pStr);
431 CoTaskMemFree(pStr);
432
433 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
434 {
435 // failed to open key
436 return FALSE;
437 }
438
439 dwInstanceID = sizeof(szInstanceID);
440 if (RegGetValueW(hKey, NULL, L"PnpInstanceId", RRF_RT_REG_SZ, NULL, (PVOID)szInstanceID, &dwInstanceID) == ERROR_SUCCESS)
441 {
442 szInstanceID[MAX_PATH-1] = L'\0';
443 pResult = static_cast<LPOLESTR>(CoTaskMemAlloc((wcslen(szInstanceID) + 1) * sizeof(WCHAR)));
444 if (pResult != 0)
445 {
446 wcscpy(pResult, szInstanceID);
447 *DeviceInstanceID = pResult;
448 RegCloseKey(hKey);
449 return TRUE;
450 }
451 }
452 RegCloseKey(hKey);
453 return FALSE;
454 }
455
456 HRESULT
457 WINAPI
AddPages(HWND hwndParent,LPFNADDPROPSHEETPAGE pfnAddPage,LPARAM lParam)458 CNetConnectionPropertyUi::AddPages(
459 HWND hwndParent,
460 LPFNADDPROPSHEETPAGE pfnAddPage,
461 LPARAM lParam)
462 {
463 HPROPSHEETPAGE hProp;
464 BOOL ret;
465 HRESULT hr = E_FAIL;
466 INITCOMMONCONTROLSEX initEx;
467
468 initEx.dwSize = sizeof(initEx);
469 initEx.dwICC = ICC_LISTVIEW_CLASSES;
470 if (!InitCommonControlsEx(&initEx))
471 return E_FAIL;
472
473 hr = m_pCon->GetProperties(&m_pProperties);
474 if (FAILED_UNEXPECTEDLY(hr))
475 return hr;
476
477 hProp = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_NETPROPERTIES), LANPropertiesUIDlg, reinterpret_cast<LPARAM>(this), NULL);
478 if (hProp)
479 {
480 ret = (*pfnAddPage)(hProp, lParam);
481 if (ret)
482 {
483 hr = NOERROR;
484 }
485 else
486 {
487 DestroyPropertySheetPage(hProp);
488 }
489 }
490 return hr;
491 }
492
493 HRESULT
494 WINAPI
GetIcon(DWORD dwSize,HICON * phIcon)495 CNetConnectionPropertyUi::GetIcon(
496 DWORD dwSize,
497 HICON *phIcon)
498 {
499 return E_NOTIMPL;
500 }
501
502 HRESULT
503 WINAPI
GetDeviceGuid(GUID * pGuid)504 CNetConnectionPropertyUi::GetDeviceGuid(GUID *pGuid)
505 {
506 CopyMemory(pGuid, &m_pProperties->guidId, sizeof(GUID));
507 return S_OK;
508 }
509
510 HRESULT
511 WINAPI
SetConnection(INetConnection * pCon)512 CNetConnectionPropertyUi::SetConnection(INetConnection* pCon)
513 {
514 if (!pCon)
515 return E_POINTER;
516
517 m_pCon = pCon;
518 return S_OK;
519 }
520
521 HRESULT
522 WINAPI
Connect(HWND hwndParent,DWORD dwFlags)523 CNetConnectionPropertyUi::Connect(
524 HWND hwndParent,
525 DWORD dwFlags)
526 {
527 if (!m_pCon)
528 return E_POINTER; //FIXME
529
530 if (dwFlags & NCUC_NO_UI)
531 return m_pCon->Connect();
532
533 return E_FAIL;
534 }
535
536 HRESULT
537 WINAPI
Disconnect(HWND hwndParent,DWORD dwFlags)538 CNetConnectionPropertyUi::Disconnect(
539 HWND hwndParent,
540 DWORD dwFlags)
541 {
542 WCHAR szBuffer[100];
543 swprintf(szBuffer, L"INetConnectionConnectUi_fnDisconnect flags %x\n", dwFlags);
544 MessageBoxW(NULL, szBuffer, NULL, MB_OK);
545
546 return S_OK;
547 }
548