tcpip: make sure to clean up failed adapter bindings
[reactos.git] / reactos / dll / cpl / ncpa / ncpa.c
1 /*
2 * Copyright 2004 Gero Kuehn
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 /*
19 * PROJECT: ReactOS Network Control Panel
20 * FILE: lib/cpl/system/ncpa.c
21 * PURPOSE: ReactOS Network Control Panel
22 * PROGRAMMER: Gero Kuehn (reactos.filter@gkware.com)
23 * UPDATE HISTORY:
24 * 07-18-2004 Created
25 */
26
27 /*
28 * Read this first !
29 *
30 * This file contains a first attempt for reactos network configuration
31 *
32 * - It is not complete.
33 * - It does not work the way it works on Windows.
34 *
35 * A lot of code that can be found here now, will probably be relocated into the OS core or some
36 * protocol Co-Installers or Notify Objects later when all the required COM
37 * and "netcfgx.dll" infrastructure (esp. headers and Interfaces) get implemented step by step.
38 *
39 * This code is only a first approach to provide a usable network configuration dialogs for
40 * the new network support in Reactos.
41 *
42 * If you intend to extend this code by more, please contact me to avoid duplicate work.
43 * There are already resources and code for TCP/IP configuration that are not
44 * mature enough for committing them to CVS yet.
45 */
46
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <stdarg.h>
50 #include <tchar.h>
51 #include <windows.h>
52 #include <iphlpapi.h>
53 #include <commctrl.h>
54 #include <cpl.h>
55
56 #include <debug.h>
57
58 #include "resource.h"
59 #include "ncpa.h"
60
61
62 #define NCF_HIDDEN 0x08
63 #define NCF_HAS_UI 0x80
64
65 typedef void (ENUMREGKEYCALLBACK)(void *pCookie,HKEY hBaseKey,TCHAR *pszSubKey);
66
67 static LONG CALLBACK DisplayApplet(VOID);
68 static INT_PTR CALLBACK NetworkPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
69 void DisplayTCPIPProperties(HWND hParent,IP_ADAPTER_INFO *pInfo);
70
71 HINSTANCE hApplet = 0;
72
73 /* Applets */
74 static APPLET Applets[] =
75 {
76 {IDI_CPLSYSTEM, IDS_CPLSYSTEMNAME, IDS_CPLSYSTEMDESCRIPTION, DisplayApplet}
77 };
78
79
80
81 /* useful utilities */
82 static VOID
83 EnumRegKeys(ENUMREGKEYCALLBACK *pCallback,PVOID pCookie,HKEY hBaseKey,TCHAR *tpszRegPath)
84 {
85 HKEY hKey;
86 INT i;
87 LONG ret;
88 TCHAR tpszName[MAX_PATH];
89 DWORD dwNameLen = sizeof(tpszName);
90
91 if(RegOpenKeyEx(hBaseKey,tpszRegPath,0,KEY_ENUMERATE_SUB_KEYS,&hKey)!=ERROR_SUCCESS)
92 {
93 DPRINT("EnumRegKeys failed (key not found): %S\n", tpszRegPath);
94 return;
95 }
96
97 for(i=0;;i++)
98 {
99 TCHAR pszNewPath[MAX_PATH];
100 ret = RegEnumKeyEx(hKey,i,tpszName,&dwNameLen,NULL,NULL,NULL,NULL);
101 if(ret != ERROR_SUCCESS)
102 {
103 DPRINT("EnumRegKeys: RegEnumKeyEx failed for %S (rc 0x%lx)\n", tpszName, ret);
104 break;
105 }
106
107 _stprintf(pszNewPath,_T("%s\\%s"),tpszRegPath,tpszName);
108 DPRINT("EnumRegKeys: Calling user supplied enum function\n");
109 pCallback(pCookie,hBaseKey,pszNewPath);
110
111 dwNameLen = sizeof(tpszName);
112 }
113
114 RegCloseKey(hKey);
115 }
116
117 void
118 InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc,LPARAM lParam)
119 {
120 ZeroMemory(psp, sizeof(PROPSHEETPAGE));
121 psp->dwSize = sizeof(PROPSHEETPAGE);
122 psp->dwFlags = PSP_DEFAULT;
123 psp->hInstance = hApplet;
124 psp->pszTemplate = MAKEINTRESOURCE(idDlg);
125 psp->pfnDlgProc = DlgProc;
126 psp->lParam = lParam;
127 }
128
129
130
131 static BOOL
132 FindNICClassKeyForCfgInstance(TCHAR *tpszCfgInst,TCHAR *tpszSubKeyOut)
133 {
134 int i;
135 TCHAR tpszSubKey[MAX_PATH];
136 TCHAR tpszCfgInst2[MAX_PATH];
137 HKEY hKey;
138 DWORD dwType,dwSize;
139
140 for (i = 0; i < 100; i++)
141 {
142 _stprintf(tpszSubKey,_T("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%04d"),i);
143 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszSubKey,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS)
144 continue;
145 dwType = REG_SZ;
146 dwSize = sizeof(tpszCfgInst2);
147 if(RegQueryValueEx(hKey,_T("NetCfgInstanceId"),NULL,&dwType,(BYTE*)tpszCfgInst2,&dwSize)!=ERROR_SUCCESS) {
148 RegCloseKey(hKey);
149 continue;
150 }
151 RegCloseKey(hKey);
152 if(_tcscmp(tpszCfgInst,tpszCfgInst2)==0) {
153 _tcscpy(tpszSubKeyOut,tpszSubKey);
154 return TRUE;
155 }
156 }
157 return FALSE;
158 }
159
160
161 static void
162 NICPropertyProtocolCallback(void *pCookie,HKEY hBaseKey,TCHAR *tpszSubKey)
163 {
164 HWND hwndDlg;
165 DWORD dwCharacteristics;
166 HKEY hKey,hNDIKey;
167 DWORD dwType,dwSize;
168 TCHAR tpszDescription[MAX_PATH];
169 TCHAR tpszNotifyObjectCLSID[MAX_PATH];
170 TCHAR *tpszSubKeyCopy;
171 int nIndex;
172 // CLSID CLSID_NotifObj;
173 // IUnknown *pUnk = NULL;
174 // INetCfgComponentControl *pNetCfg;
175 // INetCfgComponentPropertyUi *pNetCfgPropUI;
176 hwndDlg = (HWND)pCookie;
177
178 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszSubKey,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS)
179 return;
180
181 dwType = REG_DWORD;
182 dwSize = sizeof(dwCharacteristics);
183 if(RegQueryValueEx(hKey,_T("Characteristics"),NULL,&dwType,(BYTE*)&dwCharacteristics,&dwSize)!= ERROR_SUCCESS)
184 return;
185
186 if(dwCharacteristics & NCF_HIDDEN)
187 {
188 RegCloseKey(hKey);
189 return;
190 }
191
192 dwType = REG_SZ;
193 dwSize = sizeof(tpszDescription);
194 if(RegQueryValueEx(hKey,_T("Description"),NULL,&dwType,(BYTE*)tpszDescription,&dwSize)!= ERROR_SUCCESS)
195 return;
196
197 RegOpenKeyEx(hKey,_T("Ndi"),0,KEY_QUERY_VALUE,&hNDIKey);
198 dwType = REG_SZ;
199 dwSize = sizeof(tpszNotifyObjectCLSID);
200 if(RegQueryValueEx(hNDIKey,_T("ClsId"),NULL,&dwType,(BYTE*)tpszNotifyObjectCLSID,&dwSize)!= ERROR_SUCCESS)
201 ;//return;
202
203 RegCloseKey(hNDIKey);
204
205 //
206 // This code works on Windows... but not on Reactos
207 //
208
209 // CLSIDFromString(tpszNotifyObjectCLSID,&CLSID_NotifObj);
210 // CoCreateInstance(&CLSID_NotifObj,NULL,CLSCTX_INPROC_SERVER,&IID_IUnknown,(void**)&pUnk);
211 // pUnk->lpVtbl->QueryInterface(pUnk,&IID_INetCfgComponentControl,(void**)&pNetCfg);
212 // pUnk->lpVtbl->QueryInterface(pUnk,&IID_INetCfgComponentPropertyUi,(void**)&pNetCfgPropUI);
213 {
214 /*
215 HRESULT hr;
216 hr = pNetCfg->lpVtbl->Initialize(pNetCfg,&NetCfgComponent,&NetCfg,FALSE);
217 hr = pNetCfgPropUI->lpVtbl->QueryPropertyUi(pNetCfgPropUI,(INetCfg*)&NetCfg);
218 hr = pNetCfgPropUI->lpVtbl->SetContext(pNetCfgPropUI,(INetCfg*)&NetCfgComponent);
219 DWORD dwNumPages = 10;
220 HPROPSHEETPAGE *bOut = NULL;
221 UINT nPages;
222 hr = pNetCfgPropUI->MergePropPages(&dwNumPages,(BYTE**)&bOut,&nPages,GetDesktopWindow(),NULL);
223 */
224 }
225
226 RegCloseKey(hKey);
227 nIndex = SendDlgItemMessage(hwndDlg,IDC_COMPONENTSLIST,LB_ADDSTRING,0,(LPARAM)tpszDescription);
228 tpszSubKeyCopy = _tcsdup(tpszSubKey);
229 SendDlgItemMessage(hwndDlg,IDC_COMPONENTSLIST,LB_SETITEMDATA,nIndex,(LPARAM)tpszSubKeyCopy);
230 }
231
232
233
234 static INT_PTR CALLBACK
235 NICPropertyPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
236 {
237 PROPSHEETPAGE *pPage = (PROPSHEETPAGE *)GetWindowLongPtr(hwndDlg,GWL_USERDATA);
238 switch(uMsg)
239 {
240 case WM_INITDIALOG:
241 {
242 TCHAR *tpszCfgInstanceID;
243 DWORD dwType,dwSize;
244 TCHAR tpszSubKey[MAX_PATH];
245 TCHAR tpszDisplayName[MAX_PATH];
246 HKEY hKey;
247 pPage = (PROPSHEETPAGE *)lParam;
248 tpszCfgInstanceID = (TCHAR*)pPage->lParam;
249 if(!FindNICClassKeyForCfgInstance(tpszCfgInstanceID,tpszSubKey))
250 {
251 MessageBox(hwndDlg,_T("NIC Entry not found"),_T("Registry error"),MB_ICONSTOP);
252 MessageBox(hwndDlg,tpszCfgInstanceID,tpszSubKey,MB_ICONSTOP);
253 }
254
255 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszSubKey,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS)
256 return 0;
257 dwType = REG_SZ;
258 dwSize = sizeof(tpszDisplayName);
259 if(RegQueryValueEx(hKey,_T("DriverDesc"),NULL,&dwType,(BYTE*)tpszDisplayName,&dwSize)!= ERROR_SUCCESS)
260 return 0;
261 RegCloseKey(hKey);
262
263 SetDlgItemText(hwndDlg,IDC_NETCARDNAME,tpszDisplayName);
264 EnableWindow(GetDlgItem(hwndDlg,IDC_CONFIGURE),FALSE);
265
266
267 SetWindowLongPtr(hwndDlg,GWL_USERDATA,(DWORD_PTR)lParam);
268 //SetDlgItemTextA(hwndDlg,IDC_NETCARDNAME,Info[pPage->lParam].Description);
269 EnumRegKeys(NICPropertyProtocolCallback,hwndDlg,HKEY_LOCAL_MACHINE,_T("System\\CurrentControlSet\\Control\\Network\\{4D36E975-E325-11CE-BFC1-08002BE10318}"));
270
271 }
272 break;
273 case WM_COMMAND:
274 switch(LOWORD(wParam))
275 {
276 case IDC_COMPONENTSLIST:
277 if(HIWORD(wParam)==LBN_SELCHANGE)
278 {
279 TCHAR *tpszSubKey;
280 TCHAR tpszHelpKey[MAX_PATH];
281 TCHAR tpszHelpText[MAX_PATH];
282 HKEY hNDIKey;
283 DWORD dwType,dwSize;
284 HWND hListBox = GetDlgItem(hwndDlg,IDC_COMPONENTSLIST);
285 tpszSubKey = (TCHAR*)SendMessage(hListBox,LB_GETITEMDATA,SendMessage(hListBox,LB_GETCURSEL,0,0),0);
286 if(!tpszSubKey)
287 break;
288 _stprintf(tpszHelpKey,_T("%s\\Ndi"),tpszSubKey);
289
290 RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszHelpKey,0,KEY_QUERY_VALUE,&hNDIKey);
291 dwType = REG_SZ;
292 dwSize = sizeof(tpszHelpText);
293 if(RegQueryValueEx(hNDIKey,_T("HelpText"),NULL,&dwType,(BYTE*)tpszHelpText,&dwSize)!= ERROR_SUCCESS)
294 ;//return;
295 RegCloseKey(hNDIKey);
296
297 SetDlgItemText(hwndDlg,IDC_DESCRIPTION,tpszHelpText);
298
299 }
300 if(HIWORD(wParam)!=LBN_DBLCLK)
301 break;
302 // drop though
303 case IDC_PROPERTIES:
304 {
305 TCHAR *tpszSubKey;
306 TCHAR tpszNDIKey[MAX_PATH];
307 TCHAR tpszClsIDText[MAX_PATH];
308 TCHAR *tpszTCPIPClsID = _T("{A907657F-6FDF-11D0-8EFB-00C04FD912B2}");
309 HKEY hNDIKey;
310 DWORD dwType,dwSize;
311 HWND hListBox = GetDlgItem(hwndDlg,IDC_COMPONENTSLIST);
312 tpszSubKey = (TCHAR*)SendMessage(hListBox,LB_GETITEMDATA,SendMessage(hListBox,LB_GETCURSEL,0,0),0);
313 if(!tpszSubKey)
314 break;
315 _stprintf(tpszNDIKey,_T("%s\\Ndi"),tpszSubKey);
316
317 RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszNDIKey,0,KEY_QUERY_VALUE,&hNDIKey);
318 dwSize = sizeof(tpszClsIDText);
319 if(RegQueryValueEx(hNDIKey,_T("ClsId"),NULL,&dwType,(BYTE*)tpszClsIDText,&dwSize)!= ERROR_SUCCESS || dwType != REG_SZ)
320 ;//return;
321 RegCloseKey(hNDIKey);
322
323 if(_tcscmp(tpszTCPIPClsID,tpszClsIDText)==0)
324 {
325 IP_ADAPTER_INFO *Adapters = LocalAlloc( LMEM_FIXED, sizeof(IP_ADAPTER_INFO) * 64 );
326 IP_ADAPTER_INFO *pAdapter;
327 TCHAR *tpszCfgInstanceID;
328 DWORD dwSize = sizeof(*Adapters) * 64;
329 memset(Adapters,0x00,dwSize);
330 if(GetAdaptersInfo(Adapters,&dwSize)!=ERROR_SUCCESS)
331 break;
332 pAdapter = Adapters;
333 tpszCfgInstanceID = (TCHAR*)pPage->lParam;
334 while(pAdapter)
335 {
336 TCHAR tpszAdatperName[MAX_PATH];
337 swprintf(tpszAdatperName,L"%S",pAdapter->AdapterName);
338 DPRINT("IPHLPAPI returned: %S\n", tpszAdatperName);
339 if(_tcscmp(tpszAdatperName,tpszCfgInstanceID)==0)
340 {
341 memcpy(Adapters,pAdapter,sizeof(*pAdapter));
342 pAdapter = Adapters;
343 DisplayTCPIPProperties(hwndDlg,pAdapter);
344 break;
345 } else
346 {
347 DPRINT("... which is not the TCPIP property sheet\n");
348 }
349 pAdapter = pAdapter->Next;
350 if(!pAdapter)
351 {
352 MessageBox(NULL,_T("If you see this, then the IPHLPAPI.DLL probably needs more work because GetAdaptersInfo did not return the expected data."),_T("Error"),MB_ICONSTOP);
353 }
354 }
355
356 } else
357 {
358 MessageBox(NULL,_T("This control panel is incomplete.\r\nUsually, the \"Notify Object\" for this Network component should be invoked here. Reactos lacks the infrastructure to do this right now.\r\n- C++\r\n- DDK Headers for notify objects\r\n- clean header structure, that allow Windows-Compatible COM C++ Code"),_T("Error"),MB_ICONSTOP);
359 }
360
361 }
362 break;
363 }
364 break;
365 }
366 return FALSE;
367 }
368
369
370 static void
371 DisplayNICProperties(HWND hParent,TCHAR *tpszCfgInstanceID)
372 {
373 PROPSHEETPAGE psp[1];
374 PROPSHEETHEADER psh;
375 TCHAR tpszSubKey[MAX_PATH];
376 HKEY hKey;
377 DWORD dwType = REG_SZ;
378 TCHAR tpszName[MAX_PATH];
379 DWORD dwSize = sizeof(tpszName);
380
381 // Get the "Name" for this Connection
382 _stprintf(tpszSubKey,_T("System\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection"),tpszCfgInstanceID);
383 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszSubKey,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS)
384 return;
385 if(RegQueryValueEx(hKey,_T("Name"),NULL,&dwType,(BYTE*)tpszName,&dwSize)!=ERROR_SUCCESS)
386 _stprintf(tpszName,_T("[ERROR]"));
387 else
388 _tcscat(tpszName,_T(" Properties"));
389 RegCloseKey(hKey);
390
391
392 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
393 psh.dwSize = sizeof(PROPSHEETHEADER);
394 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW;
395 psh.hwndParent = hParent;
396 psh.hInstance = hApplet;
397 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDI_CPLSYSTEM));
398 psh.pszCaption = tpszName;
399 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
400 psh.nStartPage = 0;
401 psh.ppsp = psp;
402 psh.pfnCallback = NULL;
403
404
405 InitPropSheetPage(&psp[0], IDD_NETPROPERTIES, NICPropertyPageProc,(LPARAM)tpszCfgInstanceID);
406 PropertySheet(&psh);
407 return;
408 }
409
410
411
412 static INT_PTR CALLBACK
413 NICStatusPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
414 {
415 switch(uMsg)
416 {
417 case WM_INITDIALOG:
418 {
419 PROPSHEETPAGE *psp= (PROPSHEETPAGE *)lParam;
420 EnableWindow(GetDlgItem(hwndDlg,IDC_ENDISABLE),FALSE);
421 SetWindowLongPtr(hwndDlg,DWL_USER,(DWORD_PTR)psp->lParam);
422 }
423 break;
424 case WM_COMMAND:
425 switch(LOWORD(wParam))
426 {
427 case IDC_PROPERTIES:
428 {
429 TCHAR *tpszCfgInstance;
430 tpszCfgInstance = (TCHAR*)GetWindowLong(hwndDlg,DWL_USER);
431 DisplayNICProperties(hwndDlg,tpszCfgInstance);
432 }
433 break;
434 }
435 break;
436 }
437 return FALSE;
438 }
439
440 static VOID
441 DisplayNICStatus(HWND hParent,TCHAR *tpszCfgInstanceID)
442 {
443 PROPSHEETPAGE psp[1];
444 PROPSHEETHEADER psh;
445 TCHAR tpszSubKey[MAX_PATH];
446 HKEY hKey;
447 DWORD dwType = REG_SZ;
448 TCHAR tpszName[MAX_PATH];
449 DWORD dwSize = sizeof(tpszName);
450
451 // Get the "Name" for this Connection
452 _stprintf(tpszSubKey,_T("System\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection"),tpszCfgInstanceID);
453 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,tpszSubKey,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS)
454 return;
455
456 if (RegQueryValueEx(hKey,_T("Name"),NULL,&dwType,(BYTE*)tpszName,&dwSize)!=ERROR_SUCCESS)
457 _stprintf(tpszName,_T("[ERROR]"));
458 //_stprintf(tpszName,_T("[ERROR]") _T(__FILE__) _T(" %d"),__LINE__ );
459 else
460 _tcscat(tpszName,_T(" Status"));
461 RegCloseKey(hKey);
462
463 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
464 psh.dwSize = sizeof(PROPSHEETHEADER);
465 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW;
466 psh.hwndParent = hParent;
467 psh.hInstance = hApplet;
468 // FIX THESE REACTOS HEADERS !!!!!!!!!
469 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDI_CPLSYSTEM));
470 psh.pszCaption = tpszName;//Caption;
471 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
472 psh.nStartPage = 0;
473 psh.ppsp = psp;
474 psh.pfnCallback = NULL;
475
476
477 InitPropSheetPage(&psp[0], IDD_CARDPROPERTIES, NICStatusPageProc,(LPARAM)tpszCfgInstanceID);
478 PropertySheet(&psh);
479 return;
480 }
481
482 //
483 // IPHLPAPI does not provide a list of all adapters
484 //
485 #if 0
486 static VOID
487 EnumAdapters(HWND hwndDlg)
488 {
489 TCHAR pszText[MAX_ADAPTER_NAME_LENGTH + 4];
490 IP_ADAPTER_INFO *pInfo;
491 ULONG size;
492 INT nIndex;
493
494 size=sizeof(Info);
495 if(GetAdaptersInfo(Info,&size)!=ERROR_SUCCESS)
496 {
497 MessageBox(hwndDlg,L"IPHLPAPI.DLL failed to provide Adapter information",L"Error",MB_ICONSTOP);
498 return;
499 }
500
501 pInfo = &Info[0];
502 while(pInfo)
503 {
504 swprintf(pszText,L"%S",Info[0].Description);
505 nIndex = SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_ADDSTRING,0,(LPARAM)pszText);
506 SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_SETITEMDATA,nIndex,(LPARAM)pInfo);
507 pInfo = pInfo->Next;
508 }
509 }
510 #endif
511
512
513
514 static void
515 NetAdapterCallback(void *pCookie,HKEY hBaseKey,TCHAR *tpszSubKey)
516 {
517 TCHAR tpszDisplayName[MAX_PATH];
518 //TCHAR tpszDeviceID[MAX_PATH];
519 TCHAR tpszCfgInstanceID[MAX_PATH];
520 TCHAR *ptpszCfgInstanceID;
521 HKEY hKey;
522 DWORD dwType = REG_SZ;
523 DWORD dwSize = sizeof(tpszDisplayName);
524 int nIndex;
525 HWND hwndDlg = (HWND)pCookie;
526 DWORD dwCharacteristics;
527
528 DPRINT("NetAdapterCallback: %S\n", tpszSubKey);
529 if(RegOpenKeyEx(hBaseKey,tpszSubKey,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS)
530 return;
531
532 DPRINT("NetAdapterCallback: Reading Characteristics\n");
533 dwType = REG_DWORD;
534 dwSize = sizeof(dwCharacteristics);
535 if(RegQueryValueEx(hKey,_T("Characteristics"),NULL,&dwType,(BYTE*)&dwCharacteristics,&dwSize)!=ERROR_SUCCESS)
536 dwCharacteristics = 0;
537
538
539 if (dwCharacteristics & NCF_HIDDEN)
540 return;
541 // if (!(dwCharacteristics & NCF_HAS_UI))
542 // return;
543
544 DPRINT("NetAdapterCallback: Reading DriverDesc\n");
545 dwType = REG_SZ;
546 dwSize = sizeof(tpszDisplayName);
547 if (RegQueryValueEx(hKey,_T("DriverDesc"),NULL,&dwType,(BYTE*)tpszDisplayName,&dwSize)!= ERROR_SUCCESS)
548 _tcscpy(tpszDisplayName,_T("Unnamed Adapter"));
549
550 // get the link to the Enum Subkey (currently unused)
551 //dwType = REG_SZ;
552 //dwSize = sizeof(tpszDeviceID);
553 //if(RegQueryValueEx(hKey,_T("MatchingDeviceId"),NULL,&dwType,(BYTE*)tpszDeviceID,&dwSize) != ERROR_SUCCESS) {
554 // MessageBox(hwndDlg,_T("Missing MatchingDeviceId Entry"),_T("Registry Problem"),MB_ICONSTOP);
555 // return;
556 //}
557
558 // get the card configuration GUID
559 dwType = REG_SZ;
560 dwSize = sizeof(tpszCfgInstanceID);
561 if(RegQueryValueEx(hKey,_T("NetCfgInstanceId"),NULL,&dwType,(BYTE*)tpszCfgInstanceID,&dwSize) != ERROR_SUCCESS) {
562 MessageBox(hwndDlg,_T("Missing NetCfgInstanceId Entry"),_T("Registry Problem"),MB_ICONSTOP);
563 return;
564 }
565
566 ptpszCfgInstanceID = _tcsdup(tpszCfgInstanceID);
567 //
568 // **TODO** **FIXME** TBD
569 // At this point, we should verify, if the device listed here
570 // really represents a device that is currently connected to the system
571 //
572 // How is this done properly ?
573
574
575 nIndex = SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_ADDSTRING,0,(LPARAM)tpszDisplayName);
576 SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_SETITEMDATA,nIndex,(LPARAM)ptpszCfgInstanceID);
577 RegCloseKey(hKey);
578 }
579
580
581 static void
582 EnumAdapters(HWND hwndDlg)
583 {
584 LPTSTR lpRegPath = _T("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
585
586 EnumRegKeys(NetAdapterCallback,hwndDlg,HKEY_LOCAL_MACHINE,lpRegPath);
587 return;
588 }
589
590
591 static INT_PTR CALLBACK
592 NetworkPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
593 {
594 NMHDR* pnmh;
595 int nIndex;
596 switch(uMsg)
597 {
598 case WM_INITDIALOG:
599 {
600 EnableWindow(GetDlgItem(hwndDlg,IDC_ADD),FALSE);
601 EnableWindow(GetDlgItem(hwndDlg,IDC_REMOVE),FALSE);
602
603 SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_SETCURSEL,0,0);
604
605 EnumAdapters(hwndDlg);
606 }
607 break;
608
609 case WM_NOTIFY:
610 pnmh=(NMHDR*)lParam;
611 switch(pnmh->code)
612 {
613 case PSN_APPLY:
614 case PSN_RESET:
615 while(SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_GETCOUNT,0,0)>0)
616 {
617 TCHAR *tpszString;
618
619 tpszString = (TCHAR*)SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_GETITEMDATA,0,0);
620 if(tpszString)
621 free(tpszString);
622 SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_DELETESTRING,0,0);
623 }
624 break;
625 }
626 break;
627
628 case WM_COMMAND:
629 switch(LOWORD(wParam))
630 {
631 case IDC_NETCARDLIST:
632 if(HIWORD(wParam)==LBN_DBLCLK) {
633 nIndex = SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_GETCURSEL,0,0);
634 if(nIndex!=-1)
635 DisplayNICStatus(hwndDlg,(TCHAR*)SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_GETITEMDATA,nIndex,0));
636 }
637 break;
638
639 case IDC_PROPERTIES:
640 nIndex = SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_GETCURSEL,0,0);
641 if(nIndex!=-1)
642 DisplayNICStatus(hwndDlg,(TCHAR*)SendDlgItemMessage(hwndDlg,IDC_NETCARDLIST,LB_GETITEMDATA,nIndex,0));
643 break;
644 }
645 break;
646 }
647
648 return FALSE;
649 }
650
651
652
653 /* First Applet */
654 static LONG CALLBACK
655 DisplayApplet(VOID)
656 {
657 PROPSHEETPAGE psp[1];
658 PROPSHEETHEADER psh = {0};
659 TCHAR Caption[1024];
660
661 LoadString(hApplet, IDS_CPLSYSTEMNAME, Caption, sizeof(Caption) / sizeof(TCHAR));
662
663 psh.dwSize = sizeof(PROPSHEETHEADER);
664 psh.dwFlags = PSH_PROPSHEETPAGE;
665 psh.hwndParent = NULL;
666 psh.hInstance = hApplet;
667 psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDI_CPLSYSTEM));
668 psh.pszCaption = Caption;
669 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
670 psh.nStartPage = 0;
671 psh.ppsp = psp;
672 psh.pfnCallback = NULL;
673
674 InitPropSheetPage(&psp[0], IDD_PROPPAGENETWORK, NetworkPageProc,0);
675
676 return (LONG)(PropertySheet(&psh) != -1);
677 }
678
679 /* Control Panel Callback */
680 LONG CALLBACK
681 CPlApplet(HWND hwndCPl, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
682 {
683 switch (uMsg)
684 {
685 case CPL_INIT:
686 {
687 return TRUE;
688 }
689
690 case CPL_GETCOUNT:
691 {
692 return sizeof(Applets)/sizeof(APPLET);
693 }
694
695 case CPL_INQUIRE:
696 {
697 CPLINFO *CPlInfo = (CPLINFO*)lParam2;
698 CPlInfo->lData = 0;
699 CPlInfo->idIcon = Applets[(int)lParam1].idIcon;
700 CPlInfo->idName = Applets[(int)lParam1].idName;
701 CPlInfo->idInfo = Applets[(int)lParam1].idDescription;
702 break;
703 }
704
705 case CPL_DBLCLK:
706 {
707 Applets[(int)lParam1].AppletProc();
708 break;
709 }
710 }
711
712 return FALSE;
713 }
714
715
716 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
717 {
718 switch(dwReason)
719 {
720 case DLL_PROCESS_ATTACH:
721 case DLL_THREAD_ATTACH:
722 hApplet = hinstDLL;
723 break;
724 }
725
726 return TRUE;
727 }
728