Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / dll / win32 / netshell / lanconnectui.cpp
1 #include "precomp.h"
2
3 WINE_DEFAULT_DEBUG_CHANNEL (shell);
4
5 /// CLASSID
6 /// {7007ACC5-3202-11D1-AAD2-00805FC1270E}
7 /// open network properties and wlan properties
8
9 typedef enum
10 {
11 NET_TYPE_CLIENT = 1,
12 NET_TYPE_SERVICE = 2,
13 NET_TYPE_PROTOCOL = 3
14 } NET_TYPE;
15
16 typedef struct
17 {
18 NET_TYPE Type;
19 DWORD dwCharacteristics;
20 LPWSTR szHelp;
21 INetCfgComponent *pNCfgComp;
22 UINT NumPropDialogOpen;
23 } NET_ITEM, *PNET_ITEM;
24
25 class CNetConnectionPropertyUi final :
26 public INetConnectionPropertyUi2,
27 public INetLanConnectionUiInfo,
28 public INetConnectionConnectUi
29 {
30 public:
31 CNetConnectionPropertyUi();
32
33 // IUnknown
34 virtual HRESULT WINAPI QueryInterface(REFIID riid, LPVOID *ppvOut);
35 virtual ULONG WINAPI AddRef();
36 virtual ULONG WINAPI Release();
37
38 // INetConnectionPropertyUi2
39 virtual HRESULT WINAPI AddPages(HWND hwndParent, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
40 virtual HRESULT WINAPI GetIcon(DWORD dwSize, HICON *phIcon);
41
42 // INetLanConnectionUiInfo
43 virtual HRESULT WINAPI GetDeviceGuid(GUID *pGuid);
44
45 // INetConnectionConnectUi
46 virtual HRESULT WINAPI SetConnection(INetConnection* pCon);
47 virtual HRESULT WINAPI Connect(HWND hwndParent, DWORD dwFlags);
48 virtual HRESULT WINAPI Disconnect(HWND hwndParent, DWORD dwFlags);
49
50 private:
51 BOOL GetINetCfgComponent(INetCfg *pNCfg, INetCfgComponent ** pOut);
52 VOID EnumComponents(HWND hDlgCtrl, INetCfg *pNCfg, const GUID *CompGuid, UINT Type);
53 VOID InitializeLANPropertiesUIDlg(HWND hwndDlg);
54 VOID ShowNetworkComponentProperties(HWND hwndDlg);
55 static INT_PTR CALLBACK LANPropertiesUIDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
56
57 INetConnection * pCon;
58 INetCfgLock *NCfgLock;
59 INetCfg * pNCfg;
60 NETCON_PROPERTIES * pProperties;
61 LONG ref;
62 };
63
64 CNetConnectionPropertyUi::CNetConnectionPropertyUi()
65 {
66 ref = 0;
67 pCon = NULL;
68 pNCfg = NULL;
69 NCfgLock = NULL;
70 pProperties = NULL;
71 }
72
73 HPROPSHEETPAGE
74 InitializePropertySheetPage(LPWSTR resname, DLGPROC dlgproc, LPARAM lParam, LPWSTR szTitle)
75 {
76 PROPSHEETPAGEW ppage;
77
78 memset(&ppage, 0x0, sizeof(PROPSHEETPAGEW));
79 ppage.dwSize = sizeof(PROPSHEETPAGEW);
80 ppage.dwFlags = PSP_DEFAULT;
81 ppage.pszTemplate = resname;
82 ppage.pfnDlgProc = dlgproc;
83 ppage.lParam = lParam;
84 ppage.hInstance = netshell_hInstance;
85 if (szTitle)
86 {
87 ppage.dwFlags |= PSP_USETITLE;
88 ppage.pszTitle = szTitle;
89 }
90 return CreatePropertySheetPageW(&ppage);
91 }
92
93 VOID
94 AddItemToListView(HWND hDlgCtrl, PNET_ITEM pItem, LPWSTR szName, BOOL bChecked)
95 {
96 LVITEMW lvItem;
97
98 ZeroMemory(&lvItem, sizeof(lvItem));
99 lvItem.mask = LVIF_TEXT | LVIF_PARAM;
100 lvItem.pszText = szName;
101 lvItem.lParam = (LPARAM)pItem;
102 lvItem.iItem = ListView_GetItemCount(hDlgCtrl);
103 lvItem.iItem = SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&lvItem);
104 ListView_SetCheckState(hDlgCtrl, lvItem.iItem, bChecked);
105 }
106
107 BOOL
108 CNetConnectionPropertyUi::GetINetCfgComponent(INetCfg *pNCfg, INetCfgComponent ** pOut)
109 {
110 LPWSTR pName;
111 HRESULT hr;
112 INetCfgComponent * pNCg;
113 ULONG Fetched;
114 IEnumNetCfgComponent * pEnumCfg;
115
116 hr = pNCfg->EnumComponents(&GUID_DEVCLASS_NET, &pEnumCfg);
117 if (FAILED(hr))
118 {
119 return FALSE;
120 }
121
122 while (pEnumCfg->Next(1, &pNCg, &Fetched) == S_OK)
123 {
124 hr = pNCg->GetDisplayName(&pName);
125 if (SUCCEEDED(hr))
126 {
127 if (!_wcsicmp(pName, pProperties->pszwDeviceName))
128 {
129 *pOut = pNCg;
130 pEnumCfg->Release();
131 return TRUE;
132 }
133 CoTaskMemFree(pName);
134 }
135 pNCg->Release();
136 }
137 pEnumCfg->Release();
138 return FALSE;
139 }
140
141 VOID
142 CNetConnectionPropertyUi::EnumComponents(HWND hDlgCtrl, INetCfg *pNCfg, const GUID *CompGuid, UINT Type)
143 {
144 HRESULT hr;
145 IEnumNetCfgComponent * pENetCfg;
146 INetCfgComponent *pNCfgComp, *pAdapterCfgComp;
147 INetCfgComponentBindings * pCompBind;
148 ULONG Num;
149 DWORD dwCharacteristics;
150 LPOLESTR pDisplayName, pHelpText;
151 PNET_ITEM pItem;
152 BOOL bChecked;
153
154 hr = pNCfg->EnumComponents(CompGuid, &pENetCfg);
155 if (FAILED(hr))
156 {
157 pNCfg->Release();
158 return;
159 }
160 while(pENetCfg->Next(1, &pNCfgComp, &Num) == S_OK)
161 {
162 hr = pNCfgComp->GetCharacteristics(&dwCharacteristics);
163 if (SUCCEEDED(hr) && (dwCharacteristics & NCF_HIDDEN))
164 {
165 pNCfgComp->Release();
166 continue;
167 }
168 pDisplayName = NULL;
169 pHelpText = NULL;
170 hr = pNCfgComp->GetDisplayName(&pDisplayName);
171 hr = pNCfgComp->GetHelpText(&pHelpText);
172 bChecked = TRUE; //ReactOS hack
173 hr = pNCfgComp->QueryInterface(IID_INetCfgComponentBindings, (LPVOID*)&pCompBind);
174 if (SUCCEEDED(hr))
175 {
176 if (GetINetCfgComponent(pNCfg, &pAdapterCfgComp))
177 {
178 hr = pCompBind->IsBoundTo(pAdapterCfgComp);
179 if (hr == S_OK)
180 bChecked = TRUE;
181 else
182 bChecked = FALSE;
183 pAdapterCfgComp->Release();
184 pCompBind->Release();
185 }
186 }
187
188 pItem = (NET_ITEM*)CoTaskMemAlloc(sizeof(NET_ITEM));
189 if (!pItem)
190 continue;
191
192 pItem->dwCharacteristics = dwCharacteristics;
193 pItem->szHelp = pHelpText;
194 pItem->Type = (NET_TYPE)Type;
195 pItem->pNCfgComp = pNCfgComp;
196 pItem->NumPropDialogOpen = 0;
197
198 AddItemToListView(hDlgCtrl, pItem, pDisplayName, bChecked);
199 CoTaskMemFree(pDisplayName);
200 }
201 pENetCfg->Release();
202 }
203
204 VOID
205 CNetConnectionPropertyUi::InitializeLANPropertiesUIDlg(HWND hwndDlg)
206 {
207 HRESULT hr;
208 INetCfg *pNCfg;
209 INetCfgLock *pNCfgLock;
210 HWND hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMPONENTSLIST);
211 LVCOLUMNW lc;
212 RECT rc;
213 DWORD dwStyle;
214 LPWSTR pDisplayName;
215 LVITEMW li;
216
217 SendDlgItemMessageW(hwndDlg, IDC_NETCARDNAME, WM_SETTEXT, 0, (LPARAM)pProperties->pszwDeviceName);
218 if (pProperties->dwCharacter & NCCF_SHOW_ICON)
219 {
220 /* check show item on taskbar*/
221 SendDlgItemMessageW(hwndDlg, IDC_SHOWTASKBAR, BM_SETCHECK, BST_CHECKED, 0);
222 }
223 if (pProperties->dwCharacter & NCCF_NOTIFY_DISCONNECTED)
224 {
225 /* check notify item */
226 SendDlgItemMessageW(hwndDlg, IDC_NOTIFYNOCONNECTION, BM_SETCHECK, BST_CHECKED, 0);
227 }
228
229 memset(&lc, 0, sizeof(LV_COLUMN));
230 lc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
231 lc.fmt = LVCFMT_FIXED_WIDTH;
232 if (GetClientRect(hDlgCtrl, &rc))
233 {
234 lc.mask |= LVCF_WIDTH;
235 lc.cx = rc.right - rc.left;
236 }
237 lc.pszText = (LPWSTR)L"";
238 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&lc);
239 dwStyle = (DWORD) SendMessage(hDlgCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
240 dwStyle = dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES;
241 SendMessage(hDlgCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
242
243 hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (LPVOID*)&pNCfg);
244 if (FAILED(hr))
245 return;
246
247 hr = pNCfg->QueryInterface(IID_INetCfgLock, (LPVOID*)&pNCfgLock);
248 hr = pNCfgLock->AcquireWriteLock(100, L"", &pDisplayName);
249 if (hr == S_FALSE)
250 {
251 CoTaskMemFree(pDisplayName);
252 return;
253 }
254
255 NCfgLock = pNCfgLock;
256 hr = pNCfg->Initialize(NULL);
257 if (FAILED(hr))
258 {
259 pNCfg->Release();
260 return;
261 }
262
263 EnumComponents(hDlgCtrl, pNCfg, &GUID_DEVCLASS_NETCLIENT, NET_TYPE_CLIENT);
264 EnumComponents(hDlgCtrl, pNCfg, &GUID_DEVCLASS_NETSERVICE, NET_TYPE_SERVICE);
265 EnumComponents(hDlgCtrl, pNCfg, &GUID_DEVCLASS_NETTRANS, NET_TYPE_PROTOCOL);
266 this->pNCfg = pNCfg;
267
268 ZeroMemory(&li, sizeof(li));
269 li.mask = LVIF_STATE;
270 li.stateMask = (UINT)-1;
271 li.state = LVIS_FOCUSED|LVIS_SELECTED;
272 (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&li);
273 }
274
275 VOID
276 CNetConnectionPropertyUi::ShowNetworkComponentProperties(HWND hwndDlg)
277 {
278 LVITEMW lvItem;
279 HWND hDlgCtrl;
280 UINT Index, Count;
281 HRESULT hr;
282 INetCfgComponent *pNCfgComp;
283 PNET_ITEM pItem;
284
285 hDlgCtrl = GetDlgItem(hwndDlg, IDC_COMPONENTSLIST);
286 Count = ListView_GetItemCount(hDlgCtrl);
287 if (!Count)
288 return;
289
290 ZeroMemory(&lvItem, sizeof(LVITEMW));
291 lvItem.mask = LVIF_PARAM | LVIF_STATE;
292 lvItem.stateMask = (UINT)-1;
293 for (Index = 0; Index < Count; Index++)
294 {
295 lvItem.iItem = Index;
296 if (SendMessageW(hDlgCtrl, LVM_GETITEMW, 0, (LPARAM)&lvItem))
297 {
298 if (lvItem.state & LVIS_SELECTED)
299 break;
300 }
301 }
302
303 if (!(lvItem.state & LVIS_SELECTED))
304 {
305 return;
306 }
307
308 pItem = (PNET_ITEM)lvItem.lParam;
309 pNCfgComp = (INetCfgComponent*)pItem->pNCfgComp;
310 hr = pNCfgComp->RaisePropertyUi(GetParent(hwndDlg), NCRP_QUERY_PROPERTY_UI, (INetConnectionConnectUi*)this);
311 if (SUCCEEDED(hr))
312 {
313 hr = pNCfgComp->RaisePropertyUi(GetParent(hwndDlg), NCRP_SHOW_PROPERTY_UI, (INetConnectionConnectUi*)this);
314 }
315 }
316
317 INT_PTR
318 CALLBACK
319 CNetConnectionPropertyUi::LANPropertiesUIDlg(
320 HWND hwndDlg,
321 UINT uMsg,
322 WPARAM wParam,
323 LPARAM lParam)
324 {
325 PROPSHEETPAGE *page;
326 LPNMLISTVIEW lppl;
327 LVITEMW li;
328 PNET_ITEM pItem;
329 CNetConnectionPropertyUi * This;
330 LPPSHNOTIFY lppsn;
331 DWORD dwShowIcon;
332 HRESULT hr;
333 WCHAR szKey[200];
334 LPOLESTR pStr;
335 HKEY hKey;
336
337 switch(uMsg)
338 {
339 case WM_INITDIALOG:
340 page = (PROPSHEETPAGE*)lParam;
341 This = (CNetConnectionPropertyUi*)page->lParam;
342 This->InitializeLANPropertiesUIDlg(hwndDlg);
343 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)This);
344 return TRUE;
345 case WM_NOTIFY:
346 lppl = (LPNMLISTVIEW) lParam;
347 lppsn = (LPPSHNOTIFY) lParam;
348 if (lppsn->hdr.code == PSN_APPLY)
349 {
350 This = (CNetConnectionPropertyUi*)GetWindowLongPtr(hwndDlg, DWLP_USER);
351 if (This->pNCfg)
352 {
353 hr = This->pNCfg->Apply();
354 if (FAILED(hr))
355 return PSNRET_INVALID;
356 }
357
358 if (SendDlgItemMessageW(hwndDlg, IDC_SHOWTASKBAR, BM_GETCHECK, 0, 0) == BST_CHECKED)
359 dwShowIcon = 1;
360 else
361 dwShowIcon = 0;
362
363
364 if (StringFromCLSID((CLSID)This->pProperties->guidId, &pStr) == ERROR_SUCCESS)
365 {
366 swprintf(szKey, L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", pStr);
367 CoTaskMemFree(pStr);
368 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szKey, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
369 {
370 RegSetValueExW(hKey, L"ShowIcon", 0, REG_DWORD, (LPBYTE)&dwShowIcon, sizeof(DWORD));
371 RegCloseKey(hKey);
372 }
373 }
374
375 return PSNRET_NOERROR;
376 }
377 #if 0
378 else if (lppsn->hdr.code == PSN_CANCEL)
379 {
380 This = (CNetConnectionPropertyUi*)GetWindowLongPtr(hwndDlg, DWLP_USER);
381 if (This->pNCfg)
382 {
383 hr = This->pNCfg->Cancel();
384 if (SUCCEEDED(hr))
385 return PSNRET_NOERROR;
386 else
387 return PSNRET_INVALID;
388 }
389 return PSNRET_NOERROR;
390 }
391 #endif
392 if (lppl->hdr.code == LVN_ITEMCHANGING)
393 {
394 ZeroMemory(&li, sizeof(li));
395 li.mask = LVIF_PARAM;
396 li.iItem = lppl->iItem;
397 if (!SendMessageW(lppl->hdr.hwndFrom, LVM_GETITEMW, 0, (LPARAM)&li))
398 return TRUE;
399
400 pItem = (PNET_ITEM)li.lParam;
401 if (!pItem)
402 return TRUE;
403
404 if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED))
405 {
406 /* new focused item */
407 if (pItem->dwCharacteristics & NCF_NOT_USER_REMOVABLE)
408 EnableWindow(GetDlgItem(hwndDlg, IDC_UNINSTALL), FALSE);
409 else
410 EnableWindow(GetDlgItem(hwndDlg, IDC_UNINSTALL), TRUE);
411
412 if (pItem->dwCharacteristics & NCF_HAS_UI)
413 EnableWindow(GetDlgItem(hwndDlg, IDC_PROPERTIES), TRUE);
414 else
415 EnableWindow(GetDlgItem(hwndDlg, IDC_PROPERTIES), FALSE);
416
417 SendDlgItemMessageW(hwndDlg, IDC_DESCRIPTION, WM_SETTEXT, 0, (LPARAM)pItem->szHelp);
418 }
419 }
420 break;
421 case WM_COMMAND:
422 if (LOWORD(wParam) == IDC_PROPERTIES)
423 {
424 This = (CNetConnectionPropertyUi*) GetWindowLongPtr(hwndDlg, DWLP_USER);
425 This->ShowNetworkComponentProperties(hwndDlg);
426 return FALSE;
427 }
428 break;
429 }
430 return FALSE;
431 }
432
433 HRESULT
434 WINAPI
435 CNetConnectionPropertyUi::QueryInterface(
436 REFIID iid,
437 LPVOID *ppvObj)
438 {
439 LPOLESTR pStr;
440 *ppvObj = NULL;
441
442 if (IsEqualIID (iid, IID_IUnknown) ||
443 IsEqualIID (iid, IID_INetConnectionPropertyUi) ||
444 IsEqualIID (iid, IID_INetConnectionPropertyUi2))
445 {
446 *ppvObj = (INetConnectionPropertyUi2*)this;
447 AddRef();
448 return S_OK;
449 }
450 else if (IsEqualIID(iid, IID_INetLanConnectionUiInfo))
451 {
452 *ppvObj = (INetLanConnectionUiInfo*)this;
453 AddRef();
454 return S_OK;
455 }
456 else if (IsEqualIID(iid, IID_INetConnectionConnectUi))
457 {
458 *ppvObj = (INetConnectionConnectUi*)this;
459 AddRef();
460 return S_OK;
461 }
462
463 StringFromCLSID((CLSID)iid, &pStr);
464 MessageBoxW(NULL, pStr, L"INetConnectionPropertyUi_fnQueryInterface", MB_OK);
465 CoTaskMemFree(pStr);
466 return E_NOINTERFACE;
467 }
468
469 ULONG
470 WINAPI
471 CNetConnectionPropertyUi::AddRef()
472 {
473 ULONG refCount = InterlockedIncrement(&ref);
474
475 return refCount;
476 }
477
478 ULONG
479 WINAPI
480 CNetConnectionPropertyUi::Release()
481 {
482 ULONG refCount = InterlockedDecrement(&ref);
483
484 if (!refCount)
485 {
486 if (pNCfg)
487 {
488 pNCfg->Uninitialize();
489 pNCfg->Release();
490 }
491 if (NCfgLock)
492 {
493 NCfgLock->Release();
494 }
495 if (pProperties)
496 {
497 NcFreeNetconProperties(pProperties);
498 }
499 delete this;
500 }
501
502 return refCount;
503 }
504
505 HRESULT
506 WINAPI
507 CNetConnectionPropertyUi::AddPages(
508 HWND hwndParent,
509 LPFNADDPROPSHEETPAGE pfnAddPage,
510 LPARAM lParam)
511 {
512 HPROPSHEETPAGE hProp;
513 BOOL ret;
514 HRESULT hr = E_FAIL;
515 INITCOMMONCONTROLSEX initEx;
516
517 initEx.dwSize = sizeof(initEx);
518 initEx.dwICC = ICC_LISTVIEW_CLASSES;
519 if(!InitCommonControlsEx(&initEx))
520 return E_FAIL;
521
522 hr = pCon->GetProperties(&pProperties);
523 if (FAILED(hr))
524 return hr;
525
526 hProp = InitializePropertySheetPage(MAKEINTRESOURCEW(IDD_NETPROPERTIES), LANPropertiesUIDlg, (LPARAM)this, pProperties->pszwName);
527 if (hProp)
528 {
529 ret = (*pfnAddPage)(hProp, lParam);
530 if (ret)
531 {
532 hr = NOERROR;
533 }
534 else
535 {
536 DestroyPropertySheetPage(hProp);
537 }
538 }
539 return hr;
540 }
541
542 HRESULT
543 WINAPI
544 CNetConnectionPropertyUi::GetIcon(
545 DWORD dwSize,
546 HICON *phIcon)
547 {
548 return E_NOTIMPL;
549 }
550
551 HRESULT
552 WINAPI
553 CNetConnectionPropertyUi::GetDeviceGuid(GUID *pGuid)
554 {
555 CopyMemory(pGuid, &pProperties->guidId, sizeof(GUID));
556 return S_OK;
557 }
558
559 HRESULT
560 WINAPI
561 CNetConnectionPropertyUi::SetConnection(INetConnection* pCon)
562 {
563 if (this->pCon)
564 this->pCon->Release();
565
566 if (!pCon)
567 return E_POINTER;
568
569 this->pCon = pCon;
570 pCon->AddRef();
571 return S_OK;
572 }
573
574 HRESULT
575 WINAPI
576 CNetConnectionPropertyUi::Connect(
577 HWND hwndParent,
578 DWORD dwFlags)
579 {
580 if (!pCon)
581 return E_POINTER; //FIXME
582
583
584 if (dwFlags & NCUC_NO_UI)
585 return pCon->Connect();
586
587 return E_FAIL;
588 }
589
590 HRESULT
591 WINAPI
592 CNetConnectionPropertyUi::Disconnect(
593 HWND hwndParent,
594 DWORD dwFlags)
595 {
596 WCHAR szBuffer[100];
597 swprintf(szBuffer, L"INetConnectionConnectUi_fnDisconnect flags %x\n", dwFlags);
598 MessageBoxW(NULL, szBuffer, NULL, MB_OK);
599
600 return S_OK;
601 }
602
603 HRESULT WINAPI LanConnectUI_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
604 {
605 TRACE("LanConnectUI_Constructor\n");
606
607 if (!ppv)
608 return E_POINTER;
609
610 if (pUnkOuter)
611 return CLASS_E_NOAGGREGATION;
612
613 CNetConnectionPropertyUi *pConPropUi = new CNetConnectionPropertyUi;
614 if (!pConPropUi)
615 return E_OUTOFMEMORY;
616
617 pConPropUi->AddRef();
618 HRESULT hr = pConPropUi->QueryInterface(riid, ppv);
619 pConPropUi->Release();
620
621 return hr;
622 }