xref: /reactos/dll/shellext/netshell/setup.cpp (revision 8a978a17)
1 /*
2  * PROJECT:     ReactOS Shell
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     ReactOS Networking Configuration
5  * COPYRIGHT:   Copyright 2016 Eric Kohl
6  */
7 
8 #include "precomp.h"
9 
10 #include <syssetup/syssetup.h>
11 
12 
13 #define NETWORK_SETUP_MAGIC 0x50515253
14 
15 typedef struct _NETWORKSETUPDATA
16 {
17     DWORD dwMagic;
18     BOOL bTypicalNetworkSetup;
19 
20 
21     PSETUPDATA pSetupData;
22 } NETWORKSETUPDATA, *PNETWORKSETUPDATA;
23 
24 
25 extern "C"
26 {
27 
28 static
29 VOID
30 SetBoldText(
31     HWND hwndDlg,
32     INT control,
33     PSETUPDATA pSetupData)
34 {
35     SendDlgItemMessageW(hwndDlg, control, WM_SETFONT, (WPARAM)pSetupData->hBoldFont, MAKELPARAM(TRUE, 0));
36 }
37 
38 
39 static
40 HRESULT
41 InstallTypicalNetworkSettings(VOID)
42 {
43     INetCfg *pNetCfg = NULL;
44     INetCfgLock *pNetCfgLock = NULL;
45     INetCfgComponent *pTcpipComponent = NULL;
46     INetCfgComponent *pNicComponent = NULL;
47     IEnumNetCfgComponent *pEnumNicComponents = NULL;
48     WCHAR *pszNicName;
49     BOOL fWriteLocked = FALSE, fInitialized = FALSE;
50     HRESULT hr;
51 
52     TRACE("InstallTypicalNetworkSettings()\n");
53 
54     hr = CoInitialize(NULL);
55     if (hr != S_OK)
56     {
57         ERR("CoInitialize failed\n");
58         goto exit;
59     }
60 
61     hr = CoCreateInstance(CLSID_CNetCfg,
62                           NULL,
63                           CLSCTX_INPROC_SERVER,
64                           IID_INetCfg,
65                           (PVOID*)&pNetCfg);
66     if (hr != S_OK)
67     {
68         ERR("CoCreateInstance failed\n");
69         goto exit;
70     }
71 
72     /* Acquire the write-lock */
73     hr = pNetCfg->QueryInterface(IID_INetCfgLock,
74                                  (PVOID*)&pNetCfgLock);
75     if (hr != S_OK)
76     {
77         ERR("QueryInterface failed\n");
78         goto exit;
79     }
80 
81     hr = pNetCfgLock->AcquireWriteLock(5000,
82                                        L"SysSetup",
83                                        NULL);
84     if (hr != S_OK)
85     {
86         ERR("AcquireWriteLock failed\n");
87         goto exit;
88     }
89 
90     fWriteLocked = TRUE;
91 
92     /* Initialize the network configuration */
93     hr = pNetCfg->Initialize(NULL);
94     if (hr != S_OK)
95     {
96         ERR("Initialize failed\n");
97         goto exit;
98     }
99 
100     fInitialized = TRUE;
101 
102     /* Find the TCP/IP driver */
103     hr = pNetCfg->FindComponent(L"ms_tcpip",
104                                 &pTcpipComponent);
105     if (hr == S_OK)
106     {
107         FIXME("Found the TCP/IP driver!\n");
108     }
109     else
110     {
111         ERR("Initialize failed\n");
112         goto exit;
113     }
114 
115     hr = pNetCfg->EnumComponents(&GUID_DEVCLASS_NET,
116                                  &pEnumNicComponents);
117     if (hr != S_OK)
118     {
119         ERR("EnumComponents failed\n");
120         goto exit;
121     }
122 
123     for (;;)
124     {
125         hr = pEnumNicComponents->Next(1,
126                                       &pNicComponent,
127                                       NULL);
128         if (hr != S_OK)
129         {
130             TRACE("EnumNicComponents done!\n");
131             break;
132         }
133 
134         hr = pNicComponent->GetDisplayName(&pszNicName);
135         if (hr == S_OK)
136         {
137             FIXME("NIC name: %S\n", pszNicName);
138             CoTaskMemFree(pszNicName);
139         }
140 
141         // FIXME Bind Tcpip to the NIC
142 
143         pNicComponent->Release();
144         pNicComponent = NULL;
145     }
146 
147     TRACE("Done!\n");
148 exit:
149     if (pNicComponent != NULL)
150         pNicComponent->Release();
151 
152     if (pEnumNicComponents != NULL)
153         pEnumNicComponents->Release();
154 
155     if (pTcpipComponent != NULL)
156         pTcpipComponent->Release();
157 
158     if (fInitialized)
159         pNetCfg->Uninitialize();
160 
161     if (fWriteLocked)
162         pNetCfgLock->ReleaseWriteLock();
163 
164     if (pNetCfgLock != NULL)
165         pNetCfgLock->Release();
166 
167     if (pNetCfg != NULL)
168         pNetCfg->Release();
169 
170     CoUninitialize();
171 
172     TRACE("InstallTypicalNetworkSettings() done!\n");
173 
174     return hr;
175 }
176 
177 
178 static
179 INT_PTR
180 CALLBACK
181 NetworkSettingsPageDlgProc(
182     HWND hwndDlg,
183     UINT uMsg,
184     WPARAM wParam,
185     LPARAM lParam)
186 {
187     PNETWORKSETUPDATA pNetworkSetupData;
188     PSETUPDATA pSetupData;
189     LPNMHDR lpnm;
190 
191     /* Retrieve pointer to the global setup data */
192     pNetworkSetupData = (PNETWORKSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
193     if ((pNetworkSetupData != NULL) &&
194         (pNetworkSetupData->dwMagic == NETWORK_SETUP_MAGIC))
195         pSetupData = pNetworkSetupData->pSetupData;
196 
197     switch (uMsg)
198     {
199         case WM_INITDIALOG:
200             /* Save pointer to the global setup data */
201             pNetworkSetupData = (PNETWORKSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
202             SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pNetworkSetupData);
203             pSetupData = pNetworkSetupData->pSetupData;
204 
205             /* Set the fonts of both the options to bold */
206             SetBoldText(hwndDlg, IDC_NETWORK_TYPICAL, pSetupData);
207             SetBoldText(hwndDlg, IDC_NETWORK_CUSTOM, pSetupData);
208 
209             /* Set the typical settings option as the default */
210             SendDlgItemMessage(hwndDlg, IDC_NETWORK_TYPICAL, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
211 
212             if (pSetupData->UnattendSetup)
213             {
214                 //...
215             }
216             break;
217 
218         case WM_DESTROY:
219             /* ATTENTION: Free pNetworkSetupData only in one of the page functions!!! */
220             //...
221             break;
222 
223         case WM_NOTIFY:
224             lpnm = (LPNMHDR)lParam;
225 
226             switch (lpnm->code)
227             {
228                 case PSN_SETACTIVE:
229                     /* Enable the Back and Next buttons */
230                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
231                     if (pSetupData->UnattendSetup)
232                     {
233                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_NETWORKCOMPONENTPAGE);
234                         return TRUE;
235                     }
236                     break;
237 
238                 case PSN_WIZNEXT:
239                     pNetworkSetupData->bTypicalNetworkSetup = FALSE;
240 
241                     /* If the Typical Settings button is chosen, then skip to the Domain Page */
242                     if (IsDlgButtonChecked(hwndDlg, IDC_NETWORK_TYPICAL) == BST_CHECKED)
243                     {
244                         pNetworkSetupData->bTypicalNetworkSetup = TRUE;
245 
246                         InstallTypicalNetworkSettings();
247 
248                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_NETWORKDOMAINPAGE);
249                         return TRUE;
250                     }
251                     break;
252 
253                 case PSN_WIZBACK:
254                     pSetupData->UnattendSetup = FALSE;
255                     break;
256             }
257             break;
258 
259         default:
260             break;
261     }
262 
263     return FALSE;
264 }
265 
266 static
267 INT_PTR
268 CALLBACK
269 NetworkComponentPageDlgProc(
270     HWND hwndDlg,
271     UINT uMsg,
272     WPARAM wParam,
273     LPARAM lParam)
274 {
275     PNETWORKSETUPDATA pNetworkSetupData;
276     PSETUPDATA pSetupData;
277     LPNMHDR lpnm;
278 
279     /* Retrieve pointer to the global setup data */
280     pNetworkSetupData = (PNETWORKSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
281     if ((pNetworkSetupData != NULL) &&
282         (pNetworkSetupData->dwMagic == NETWORK_SETUP_MAGIC))
283         pSetupData = pNetworkSetupData->pSetupData;
284 
285     switch (uMsg)
286     {
287         case WM_INITDIALOG:
288             /* Save pointer to the global setup data */
289             pNetworkSetupData = (PNETWORKSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
290             SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pNetworkSetupData);
291             pSetupData = pNetworkSetupData->pSetupData;
292 
293             SetBoldText(hwndDlg, IDC_NETWORK_DEVICE, pSetupData);
294 
295             if (pSetupData->UnattendSetup)
296             {
297                 //...
298             }
299             break;
300 
301         case WM_DESTROY:
302             /* ATTENTION: Free pNetworkSetupData only in one of the page functions!!! */
303             //...
304             break;
305 
306         case WM_NOTIFY:
307             lpnm = (LPNMHDR)lParam;
308 
309             switch (lpnm->code)
310             {
311                 case PSN_SETACTIVE:
312                     /* Enable the Back and Next buttons */
313                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
314                     if (pSetupData->UnattendSetup)
315                     {
316                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_NETWORKDOMAINPAGE);
317                         return TRUE;
318                     }
319                     break;
320 
321                 case PSN_WIZBACK:
322                     pSetupData->UnattendSetup = FALSE;
323                     break;
324             }
325             break;
326 
327         default:
328             break;
329     }
330 
331     return FALSE;
332 }
333 
334 static
335 INT_PTR
336 CALLBACK
337 NetworkDomainPageDlgProc(
338     HWND hwndDlg,
339     UINT uMsg,
340     WPARAM wParam,
341     LPARAM lParam)
342 {
343     PNETWORKSETUPDATA pNetworkSetupData;
344     PSETUPDATA pSetupData;
345     WCHAR DomainName[51];
346     WCHAR Title[64];
347     WCHAR ErrorName[256];
348     LPNMHDR lpnm;
349 
350     /* Retrieve pointer to the global setup data */
351     pNetworkSetupData = (PNETWORKSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
352     if ((pNetworkSetupData != NULL) &&
353         (pNetworkSetupData->dwMagic == NETWORK_SETUP_MAGIC))
354         pSetupData = pNetworkSetupData->pSetupData;
355 
356     switch (uMsg)
357     {
358         case WM_INITDIALOG:
359             /* Save pointer to the global setup data */
360             pNetworkSetupData = (PNETWORKSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
361             SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pNetworkSetupData);
362             pSetupData = pNetworkSetupData->pSetupData;
363 
364             /* Set the workgroup option as the default */
365             SendDlgItemMessage(hwndDlg, IDC_SELECT_WORKGROUP, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
366 
367             wcscpy(DomainName, L"WORKGROUP");
368 
369             /* Display current computer name */
370             SetDlgItemTextW(hwndDlg, IDC_DOMAIN_NAME, DomainName);
371 
372             /* Set focus to owner name */
373             SetFocus(GetDlgItem(hwndDlg, IDC_DOMAIN_NAME));
374 
375             if (pSetupData->UnattendSetup)
376             {
377                 //...
378             }
379             break;
380 
381         case WM_DESTROY:
382             //...
383             /* ATTENTION: Free pNetworkSetupData only in one of the page functions!!! */
384             if (pNetworkSetupData != NULL)
385             {
386                 if ((!IsBadReadPtr(pNetworkSetupData, sizeof(NETWORKSETUPDATA))) &&
387                     (pNetworkSetupData->dwMagic == NETWORK_SETUP_MAGIC))
388                     HeapFree(GetProcessHeap(), 0, pNetworkSetupData);
389 
390                 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)NULL);
391             }
392             break;
393 
394         case WM_NOTIFY:
395             lpnm = (LPNMHDR)lParam;
396 
397             switch (lpnm->code)
398             {
399                 case PSN_SETACTIVE:
400                     /* Enable the Back and Next buttons */
401                     PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
402                     if (pSetupData->UnattendSetup)
403                     {
404                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, pSetupData->uPostNetworkWizardPage);
405                         return TRUE;
406                     }
407                     break;
408 
409                 case PSN_WIZNEXT:
410                     DomainName[0] = 0;
411                     if (GetDlgItemTextW(hwndDlg, IDC_DOMAIN_NAME, DomainName, 50) == 0)
412                     {
413                         if (0 == LoadStringW(netshell_hInstance, IDS_REACTOS_SETUP, Title, sizeof(Title) / sizeof(Title[0])))
414                         {
415                             wcscpy(Title, L"ReactOS Setup");
416                         }
417                         if (0 == LoadStringW(netshell_hInstance, IDS_WZD_DOMAIN_NAME, ErrorName, sizeof(ErrorName) / sizeof(ErrorName[0])))
418                         {
419                             wcscpy(ErrorName, L"Setup cannot continue until you\nenter the name of your domain/workgroup.");
420                         }
421                         MessageBoxW(hwndDlg, ErrorName, Title, MB_ICONERROR | MB_OK);
422 
423                         SetFocus(GetDlgItem(hwndDlg, IDC_DOMAIN_NAME));
424                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
425 
426                         //TODO: Implement setting the Domain/Workgroup
427 
428                         return TRUE;
429                     }
430                     break;
431 
432                 case PSN_WIZBACK:
433                     pSetupData->UnattendSetup = FALSE;
434 
435                     /* If the Typical setup chosen, then skip back to the Settings Page */
436                     if (pNetworkSetupData->bTypicalNetworkSetup == TRUE)
437                     {
438                         SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_NETWORKSETTINGSPAGE);
439                         return TRUE;
440                     }
441                     break;
442             }
443             break;
444 
445         default:
446             break;
447     }
448 
449     return FALSE;
450 }
451 
452 
453 DWORD
454 WINAPI
455 NetSetupRequestWizardPages(
456     PDWORD pPageCount,
457     HPROPSHEETPAGE *pPages,
458     PSETUPDATA pSetupData)
459 {
460     PNETWORKSETUPDATA pNetworkSetupData;
461     PROPSHEETPAGE psp = {0};
462     DWORD dwPageCount = 3;
463     INT nPage = 0;
464 
465     if (pPageCount == NULL)
466         return ERROR_INVALID_PARAMETER;
467 
468     if (pPages == NULL)
469     {
470         *pPageCount = dwPageCount;
471         return ERROR_SUCCESS;
472     }
473 
474     if (*pPageCount < dwPageCount)
475         return ERROR_BUFFER_OVERFLOW;
476 
477     pSetupData->uFirstNetworkWizardPage = IDD_NETWORKSETTINGSPAGE;
478 
479     pNetworkSetupData = (PNETWORKSETUPDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NETWORKSETUPDATA));
480     if (pNetworkSetupData == NULL)
481         return ERROR_OUTOFMEMORY;
482 
483     pNetworkSetupData->dwMagic = NETWORK_SETUP_MAGIC;
484     pNetworkSetupData->pSetupData = pSetupData;
485 
486 
487     /* Create the Network Settings page */
488     psp.dwSize = sizeof(PROPSHEETPAGE);
489     psp.hInstance = netshell_hInstance;
490     psp.lParam = (LPARAM)pNetworkSetupData;
491 
492     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
493     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NETWORKSETTINGSTITLE);
494     psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_NETWORKSETTINGSSUBTITLE);
495     psp.pfnDlgProc = NetworkSettingsPageDlgProc;
496     psp.pszTemplate = MAKEINTRESOURCE(IDD_NETWORKSETTINGSPAGE);
497     pPages[nPage++] = CreatePropertySheetPage(&psp);
498 
499     /* Create the Network Components page */
500     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
501     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NETWORKCOMPONENTTITLE);
502     psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_NETWORKCOMPONENTSUBTITLE);
503     psp.pfnDlgProc = NetworkComponentPageDlgProc;
504     psp.pszTemplate = MAKEINTRESOURCE(IDD_NETWORKCOMPONENTPAGE);
505     pPages[nPage++] = CreatePropertySheetPage(&psp);
506 
507     /* Create the Domain/Workgroup page */
508     psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
509     psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_NETWORKDOMAINTITLE);
510     psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_NETWORKDOMAINSUBTITLE);
511     psp.pfnDlgProc = NetworkDomainPageDlgProc;
512     psp.pszTemplate = MAKEINTRESOURCE(IDD_NETWORKDOMAINPAGE);
513     pPages[nPage++] = CreatePropertySheetPage(&psp);
514 
515     *pPageCount = dwPageCount;
516 
517     return ERROR_SUCCESS;
518 }
519 
520 } // extern "C"
521