xref: /reactos/dll/win32/netcfgx/propertypage.c (revision e1338178)
1 /*
2  * PROJECT:     ReactOS system libraries
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Network property page provider
5  * COPYRIGHT:   Copyright 2018 Eric Kohl (eric.kohl@reactos.org)
6  */
7 
8 #include "precomp.h"
9 
10 typedef enum _PARAM_TYPE
11 {
12     NO_TYPE,
13     INT_TYPE,
14     LONG_TYPE,
15     WORD_TYPE,
16     DWORD_TYPE,
17     EDIT_TYPE,
18     ENUM_TYPE,
19 } PARAM_TYPE, *PPARAM_TYPE;
20 
21 typedef struct _ENUM_OPTION
22 {
23     PWSTR pszValue;
24     PWSTR pszName;
25 } ENUM_OPTION, *PENUM_OPTION;
26 
27 typedef struct _PARAMETER
28 {
29     PWSTR pszName;
30     PWSTR pszDescription;
31     PWSTR pszValue;
32     DWORD cchValueLength;
33     PWSTR pszDefault;
34     BOOL bOptional;
35     BOOL bPresent;
36     PARAM_TYPE Type;
37 
38     DWORD dwEnumOptions;
39     PENUM_OPTION pEnumOptions;
40 
41     BOOL bUpperCase;
42     INT iTextLimit;
43 
44     INT iBase;
45     INT iStep;
46 
47     union
48     {
49         struct
50         {
51             LONG lMin;
52             LONG lMax;
53         } l;
54         struct
55         {
56             DWORD dwMin;
57             DWORD dwMax;
58         } dw;
59     } u;
60 } PARAMETER, *PPARAMETER;
61 
62 typedef struct _PARAMETER_ARRAY
63 {
64     HDEVINFO DeviceInfoSet;
65     PSP_DEVINFO_DATA DeviceInfoData;
66     PPARAMETER pCurrentParam;
67     DWORD dwCount;
68     PARAMETER Array[0];
69 } PARAMETER_ARRAY, *PPARAMETER_ARRAY;
70 
71 
72 static
73 VOID
74 FreeParameterArray(
75     _In_ PPARAMETER_ARRAY ParamArray)
76 {
77     INT i, j;
78 
79     if (ParamArray == NULL)
80         return;
81 
82     for (i = 0; i < ParamArray->dwCount; i++)
83     {
84         if (ParamArray->Array[i].pszName != NULL)
85             HeapFree(GetProcessHeap(), 0, ParamArray->Array[i].pszName);
86 
87         if (ParamArray->Array[i].pszDescription != NULL)
88             HeapFree(GetProcessHeap(), 0, ParamArray->Array[i].pszDescription);
89 
90         if (ParamArray->Array[i].pszDefault != NULL)
91             HeapFree(GetProcessHeap(), 0, ParamArray->Array[i].pszDefault);
92 
93 
94         if (ParamArray->Array[i].pEnumOptions != NULL)
95         {
96             for (j = 0; j < ParamArray->Array[i].dwEnumOptions; j++)
97             {
98                 if (ParamArray->Array[i].pEnumOptions[j].pszValue != NULL)
99                     HeapFree(GetProcessHeap(), 0, ParamArray->Array[i].pEnumOptions[j].pszValue);
100 
101                 if (ParamArray->Array[i].pEnumOptions[j].pszName != NULL)
102                     HeapFree(GetProcessHeap(), 0, ParamArray->Array[i].pEnumOptions[j].pszName);
103             }
104 
105             HeapFree(GetProcessHeap(), 0, ParamArray->Array[i].pEnumOptions);
106         }
107     }
108 
109     HeapFree(GetProcessHeap(), 0, ParamArray);
110 }
111 
112 
113 static DWORD
114 GetStringValue(
115     _In_ HKEY hKey,
116     _In_ PWSTR pValueName,
117     _Out_ PWSTR *pString,
118     _Out_opt_ PDWORD pdwStringLength)
119 {
120     PWSTR pBuffer;
121     DWORD dwLength = 0;
122     DWORD dwRegType;
123     DWORD dwError;
124 
125     *pString = NULL;
126 
127     RegQueryValueExW(hKey, pValueName, NULL, &dwRegType, NULL, &dwLength);
128 
129     if (dwLength == 0 || dwRegType != REG_SZ)
130         return ERROR_FILE_NOT_FOUND;
131 
132     pBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
133     if (pBuffer == NULL)
134         return ERROR_NOT_ENOUGH_MEMORY;
135 
136     dwError = RegQueryValueExW(hKey, pValueName, NULL, NULL, (LPBYTE)pBuffer, &dwLength);
137     if (dwError != ERROR_SUCCESS)
138     {
139         HeapFree(GetProcessHeap(), 0, pBuffer);
140         return dwError;
141     }
142 
143     pBuffer[dwLength / sizeof(WCHAR)] = UNICODE_NULL;
144 
145     *pString = pBuffer;
146     if (pdwStringLength)
147         *pdwStringLength = dwLength;
148 
149     return ERROR_SUCCESS;
150 }
151 
152 
153 static DWORD
154 GetBooleanValue(
155     _In_ HKEY hKey,
156     _In_ PWSTR pValueName,
157     _In_ BOOL bDefault,
158     _Out_ PBOOL pValue)
159 {
160     WCHAR szBuffer[16];
161     DWORD dwLength = 0;
162     DWORD dwRegType;
163 
164     *pValue = bDefault;
165 
166     dwLength = sizeof(szBuffer);
167     RegQueryValueExW(hKey,
168                      pValueName,
169                      NULL,
170                      &dwRegType,
171                      (LPBYTE)szBuffer,
172                      &dwLength);
173 
174     if (dwRegType == REG_SZ && dwLength >= sizeof(WCHAR))
175     {
176         if (szBuffer[0] == L'0')
177             *pValue = FALSE;
178         else
179             *pValue = TRUE;
180     }
181 
182     return ERROR_SUCCESS;
183 }
184 
185 
186 static DWORD
187 GetIntValue(
188     _In_ HKEY hKey,
189     _In_ PWSTR pValueName,
190     _In_ INT iDefault,
191     _Out_ PINT pValue)
192 {
193     WCHAR szBuffer[24];
194     DWORD dwLength = 0;
195     DWORD dwRegType;
196 
197     *pValue = iDefault;
198 
199     dwLength = sizeof(szBuffer);
200     RegQueryValueExW(hKey,
201                      pValueName,
202                      NULL,
203                      &dwRegType,
204                      (LPBYTE)szBuffer,
205                      &dwLength);
206 
207     if (dwRegType == REG_SZ && dwLength >= sizeof(WCHAR))
208     {
209         *pValue = _wtoi(szBuffer);
210     }
211 
212     return ERROR_SUCCESS;
213 }
214 
215 
216 static DWORD
217 GetLongValue(
218     _In_ HKEY hKey,
219     _In_ PWSTR pValueName,
220     _In_ LONG lDefault,
221     _Out_ PLONG pValue)
222 {
223     WCHAR szBuffer[24];
224     DWORD dwLength = 0;
225     DWORD dwRegType;
226     PWSTR ptr = NULL;
227 
228     dwLength = sizeof(szBuffer);
229     RegQueryValueExW(hKey,
230                      pValueName,
231                      NULL,
232                      &dwRegType,
233                      (LPBYTE)szBuffer,
234                      &dwLength);
235 
236     if (dwRegType == REG_SZ && dwLength >= sizeof(WCHAR))
237     {
238         *pValue = wcstol(szBuffer, &ptr, 10);
239         if (*pValue == 0 && ptr != NULL)
240             *pValue = lDefault;
241     }
242     else
243     {
244         *pValue = lDefault;
245     }
246 
247     return ERROR_SUCCESS;
248 }
249 
250 
251 static DWORD
252 GetDWordValue(
253     _In_ HKEY hKey,
254     _In_ PWSTR pValueName,
255     _In_ DWORD dwDefault,
256     _Out_ PDWORD pValue)
257 {
258     WCHAR szBuffer[24];
259     DWORD dwLength = 0;
260     DWORD dwRegType;
261     PWSTR ptr = NULL;
262 
263     dwLength = sizeof(szBuffer);
264     RegQueryValueExW(hKey,
265                      pValueName,
266                      NULL,
267                      &dwRegType,
268                      (LPBYTE)szBuffer,
269                      &dwLength);
270 
271     if (dwRegType == REG_SZ && dwLength >= sizeof(WCHAR))
272     {
273         *pValue = wcstoul(szBuffer, &ptr, 10);
274         if (*pValue == 0 && ptr != NULL)
275             *pValue = dwDefault;
276     }
277     else
278     {
279         *pValue = dwDefault;
280     }
281 
282     return ERROR_SUCCESS;
283 }
284 
285 
286 static
287 DWORD
288 GetEnumOptions(
289     _In_ HKEY hKey,
290     _In_ PPARAMETER pParameter)
291 {
292     HKEY hEnumKey = NULL;
293     PENUM_OPTION pOptions = NULL;
294     DWORD dwValues, dwMaxValueNameLen, dwMaxValueLen;
295     DWORD dwValueNameLength, dwValueLength;
296     DWORD i;
297     DWORD dwError;
298 
299     dwError = RegOpenKeyExW(hKey,
300                             L"enum",
301                             0,
302                             KEY_READ,
303                             &hEnumKey);
304     if (dwError != ERROR_SUCCESS)
305         return dwError;
306 
307     dwError = RegQueryInfoKeyW(hEnumKey,
308                                NULL,
309                                NULL,
310                                NULL,
311                                NULL,
312                                NULL,
313                                NULL,
314                                &dwValues,
315                                &dwMaxValueNameLen,
316                                &dwMaxValueLen,
317                                NULL,
318                                NULL);
319     if (dwError != ERROR_SUCCESS)
320     {
321         ERR("RegQueryInfoKeyW failed (Error %lu)\n", dwError);
322         goto done;
323     }
324 
325     pOptions = HeapAlloc(GetProcessHeap(),
326                          HEAP_ZERO_MEMORY,
327                          dwValues * sizeof(ENUM_OPTION));
328     if (pOptions == NULL)
329     {
330         dwError = ERROR_OUTOFMEMORY;
331         goto done;
332     }
333 
334     for (i = 0; i < dwValues; i++)
335     {
336         dwValueNameLength = dwMaxValueNameLen + sizeof(WCHAR);
337         pOptions[i].pszValue = HeapAlloc(GetProcessHeap(),
338                                         0,
339                                         dwValueNameLength * sizeof(WCHAR));
340         if (pOptions[i].pszValue == NULL)
341         {
342             dwError = ERROR_OUTOFMEMORY;
343             goto done;
344         }
345 
346         dwValueLength = dwMaxValueLen;
347         pOptions[i].pszName = HeapAlloc(GetProcessHeap(),
348                                         0,
349                                         dwValueLength);
350         if (pOptions[i].pszName == NULL)
351         {
352             dwError = ERROR_OUTOFMEMORY;
353             goto done;
354         }
355 
356         dwError = RegEnumValueW(hEnumKey,
357                                 i,
358                                 pOptions[i].pszValue,
359                                 &dwValueNameLength,
360                                 NULL,
361                                 NULL,
362                                 (PBYTE)pOptions[i].pszName,
363                                 &dwValueLength);
364         if (dwError == ERROR_NO_MORE_ITEMS)
365         {
366             dwError = ERROR_SUCCESS;
367             goto done;
368         }
369         else if (dwError != ERROR_SUCCESS)
370         {
371             goto done;
372         }
373     }
374 
375     pParameter->pEnumOptions = pOptions;
376     pParameter->dwEnumOptions = dwValues;
377     pOptions = NULL;
378 
379 done:
380     if (pOptions != NULL)
381     {
382         for (i = 0; i < dwValues; i++)
383         {
384             if (pOptions[i].pszValue != NULL)
385                 HeapFree(GetProcessHeap(), 0, pOptions[i].pszValue);
386 
387             if (pOptions[i].pszName != NULL)
388                 HeapFree(GetProcessHeap(), 0, pOptions[i].pszName);
389         }
390 
391         HeapFree(GetProcessHeap(), 0, pOptions);
392     }
393 
394     if (hEnumKey != NULL)
395         RegCloseKey(hEnumKey);
396 
397     return dwError;
398 }
399 
400 
401 static
402 INT
403 FindEnumOption(
404     _In_ PPARAMETER pParameter,
405     _In_ PWSTR pszValue)
406 {
407     INT i;
408 
409     if ((pParameter->pEnumOptions == NULL) ||
410         (pParameter->dwEnumOptions == 0))
411         return -1;
412 
413     for (i = 0; i < pParameter->dwEnumOptions; i++)
414     {
415         if (_wcsicmp(pParameter->pEnumOptions[i].pszValue, pszValue) == 0)
416             return i;
417     }
418 
419     return -1;
420 }
421 
422 
423 static
424 BOOL
425 BuildParameterArray(
426     _In_ HDEVINFO DeviceInfoSet,
427     _In_ PSP_DEVINFO_DATA DeviceInfoData,
428     _Out_ PPARAMETER_ARRAY *ParameterArray)
429 {
430     HKEY hDriverKey = INVALID_HANDLE_VALUE;
431     HKEY hParamsKey = INVALID_HANDLE_VALUE;
432     HKEY hParamKey;
433     PPARAMETER_ARRAY ParamArray = NULL;
434     DWORD dwSubKeys, dwMaxSubKeyLen, dwKeyLen, dwIndex;
435     PWSTR pszType = NULL;
436     LONG lError;
437     LONG lDefaultMin, lDefaultMax;
438     DWORD dwDefaultMin, dwDefaultMax;
439     BOOL ret = FALSE;
440 
441     hDriverKey = SetupDiOpenDevRegKey(DeviceInfoSet,
442                                       DeviceInfoData,
443                                       DICS_FLAG_GLOBAL,
444                                       0,
445                                       DIREG_DRV,
446                                       KEY_READ);
447     if (hDriverKey == INVALID_HANDLE_VALUE)
448     {
449         ERR("SetupDiOpenDevRegKey() failed\n");
450         return FALSE;
451     }
452 
453     lError = RegOpenKeyExW(hDriverKey,
454                            L"Ndi\\Params",
455                            0,
456                            KEY_READ,
457                            &hParamsKey);
458     if (lError != ERROR_SUCCESS)
459     {
460         ERR("RegOpenKeyExW failed (Error %lu)\n", lError);
461         goto done;
462     }
463 
464     lError = RegQueryInfoKeyW(hParamsKey,
465                               NULL,
466                               NULL,
467                               NULL,
468                               &dwSubKeys,
469                               &dwMaxSubKeyLen,
470                               NULL,
471                               NULL,
472                               NULL,
473                               NULL,
474                               NULL,
475                               NULL);
476     if (lError != ERROR_SUCCESS)
477     {
478         ERR("RegOpenKeyExW failed (Error %lu)\n", lError);
479         goto done;
480     }
481 
482     TRACE("Sub keys: %lu\n", dwSubKeys);
483 
484     if (dwSubKeys == 0)
485     {
486         TRACE("No sub keys. Done!\n");
487         goto done;
488     }
489 
490     ParamArray = HeapAlloc(GetProcessHeap(),
491                            HEAP_ZERO_MEMORY,
492                            sizeof(PARAMETER_ARRAY) + (dwSubKeys * sizeof(PARAMETER)));
493     if (ParamArray == NULL)
494     {
495         ERR("Parameter array allocation failed!\n");
496         goto done;
497     }
498 
499     ParamArray->DeviceInfoSet = DeviceInfoSet;
500     ParamArray->DeviceInfoData = DeviceInfoData;
501     ParamArray->dwCount = dwSubKeys;
502 
503     dwMaxSubKeyLen++;
504 
505     for (dwIndex = 0; dwIndex < dwSubKeys; dwIndex++)
506     {
507         ParamArray->Array[dwIndex].pszName = HeapAlloc(GetProcessHeap(),
508                                                        0,
509                                                        dwMaxSubKeyLen * sizeof(WCHAR));
510         if (ParamArray->Array[dwIndex].pszName == NULL)
511         {
512             ERR("Parameter array allocation failed!\n");
513             goto done;
514         }
515 
516         dwKeyLen = dwMaxSubKeyLen;
517         lError = RegEnumKeyExW(hParamsKey,
518                                dwIndex,
519                                ParamArray->Array[dwIndex].pszName,
520                                &dwKeyLen,
521                                NULL,
522                                NULL,
523                                NULL,
524                                NULL);
525         if (lError != ERROR_SUCCESS)
526             break;
527 
528         TRACE("Sub key '%S'\n", ParamArray->Array[dwIndex].pszName);
529 
530         lError = RegOpenKeyExW(hParamsKey,
531                                ParamArray->Array[dwIndex].pszName,
532                                0,
533                                KEY_READ,
534                                &hParamKey);
535         if (lError == ERROR_SUCCESS)
536         {
537             GetStringValue(hParamKey,
538                            L"ParamDesc",
539                            &ParamArray->Array[dwIndex].pszDescription,
540                            NULL);
541 
542             GetStringValue(hParamKey,
543                            L"Type",
544                            &pszType,
545                            NULL);
546             if (pszType != NULL)
547             {
548                 if (_wcsicmp(pszType, L"int") == 0)
549                     ParamArray->Array[dwIndex].Type = INT_TYPE;
550                 else if (_wcsicmp(pszType, L"long") == 0)
551                     ParamArray->Array[dwIndex].Type = LONG_TYPE;
552                 else if (_wcsicmp(pszType, L"word") == 0)
553                     ParamArray->Array[dwIndex].Type = WORD_TYPE;
554                 else if (_wcsicmp(pszType, L"dword") == 0)
555                     ParamArray->Array[dwIndex].Type = DWORD_TYPE;
556                 else if (_wcsicmp(pszType, L"edit") == 0)
557                     ParamArray->Array[dwIndex].Type = EDIT_TYPE;
558                 else if (_wcsicmp(pszType, L"enum") == 0)
559                     ParamArray->Array[dwIndex].Type = ENUM_TYPE;
560                 else
561                     ParamArray->Array[dwIndex].Type = NO_TYPE;
562 
563                 HeapFree(GetProcessHeap(), 0, pszType);
564                 pszType = NULL;
565             }
566 
567             GetStringValue(hParamKey,
568                            L"Default",
569                            &ParamArray->Array[dwIndex].pszDefault,
570                            NULL);
571 
572             GetBooleanValue(hParamKey,
573                             L"Optional",
574                             FALSE,
575                             &ParamArray->Array[dwIndex].bOptional);
576 
577             if (ParamArray->Array[dwIndex].Type == INT_TYPE ||
578                 ParamArray->Array[dwIndex].Type == LONG_TYPE ||
579                 ParamArray->Array[dwIndex].Type == WORD_TYPE ||
580                 ParamArray->Array[dwIndex].Type == DWORD_TYPE)
581             {
582                 if (ParamArray->Array[dwIndex].Type == INT_TYPE)
583                 {
584                     lDefaultMin = -32768L; //MIN_SHORT;
585                     lDefaultMax = 32767L;  //MAX_SHORT;
586                 }
587                 else if (ParamArray->Array[dwIndex].Type == LONG_TYPE)
588                 {
589                     lDefaultMin = (-2147483647L - 1); // MIN_LONG;
590                     lDefaultMax = 2147483647L;        // MAX_LONG;
591                 }
592                 else if (ParamArray->Array[dwIndex].Type == WORD_TYPE)
593                 {
594                     dwDefaultMin = 0UL;
595                     dwDefaultMax = 65535UL; // MAX_WORD;
596                 }
597 #if 0
598                 else if (ParamArray->Array[dwIndex].Type == DWORD_TYPE)
599                 {
600                     dwDefaultMin = 0UL;
601                     dwDefaultMax = 4294967295UL; //MAX_DWORD;
602                 }
603 #endif
604 
605                 if (ParamArray->Array[dwIndex].Type == INT_TYPE ||
606                     ParamArray->Array[dwIndex].Type == LONG_TYPE)
607                 {
608                     GetLongValue(hParamKey,
609                                  L"Min",
610                                  lDefaultMin,
611                                  &ParamArray->Array[dwIndex].u.l.lMin);
612 
613                     GetLongValue(hParamKey,
614                                  L"Max",
615                                  lDefaultMax,
616                                  &ParamArray->Array[dwIndex].u.l.lMax);
617                 }
618                 else if (ParamArray->Array[dwIndex].Type == WORD_TYPE ||
619                          ParamArray->Array[dwIndex].Type == DWORD_TYPE)
620                 {
621                     GetDWordValue(hParamKey,
622                                   L"Min",
623                                   dwDefaultMin,
624                                   &ParamArray->Array[dwIndex].u.dw.dwMin);
625 
626                     GetDWordValue(hParamKey,
627                                   L"Max",
628                                   dwDefaultMax,
629                                   &ParamArray->Array[dwIndex].u.dw.dwMax);
630                 }
631 
632                 GetIntValue(hParamKey,
633                             L"Base",
634                             10,
635                             &ParamArray->Array[dwIndex].iBase);
636 
637                 GetIntValue(hParamKey,
638                             L"Step",
639                             1,
640                             &ParamArray->Array[dwIndex].iStep);
641             }
642             else if (ParamArray->Array[dwIndex].Type == EDIT_TYPE)
643             {
644                 GetBooleanValue(hParamKey,
645                                 L"UpperCase",
646                                 FALSE,
647                                 &ParamArray->Array[dwIndex].bUpperCase);
648 
649                 GetIntValue(hParamKey,
650                             L"TextLimit",
651                             0,
652                             &ParamArray->Array[dwIndex].iTextLimit);
653             }
654             else if (ParamArray->Array[dwIndex].Type == ENUM_TYPE)
655             {
656                 GetEnumOptions(hParamKey,
657                                &ParamArray->Array[dwIndex]);
658             }
659 
660             RegCloseKey(hParamKey);
661         }
662 
663         lError = GetStringValue(hDriverKey,
664                                 ParamArray->Array[dwIndex].pszName,
665                                 &ParamArray->Array[dwIndex].pszValue,
666                                 &ParamArray->Array[dwIndex].cchValueLength);
667         if ((lError == ERROR_SUCCESS) ||
668             (ParamArray->Array[dwIndex].pszDefault != NULL))
669         {
670             ParamArray->Array[dwIndex].bPresent = TRUE;
671         }
672     }
673 
674     *ParameterArray = ParamArray;
675     ret = TRUE;
676 
677 done:
678     if (ret == FALSE && ParamArray != NULL)
679         FreeParameterArray(ParamArray);
680 
681     if (hParamsKey != INVALID_HANDLE_VALUE)
682         RegCloseKey(hParamsKey);
683 
684     if (hDriverKey != INVALID_HANDLE_VALUE)
685         RegCloseKey(hDriverKey);
686 
687     return ret;
688 }
689 
690 
691 static
692 VOID
693 ReadParameterValue(
694      HWND hwnd,
695      PPARAMETER pParam)
696 {
697     INT iIndex, iLength;
698 
699     if (pParam->Type == ENUM_TYPE)
700     {
701         iIndex = ComboBox_GetCurSel(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST));
702         if (iIndex != CB_ERR && iIndex < pParam->dwEnumOptions)
703         {
704             iLength = wcslen(pParam->pEnumOptions[iIndex].pszValue);
705             if (iLength > pParam->cchValueLength)
706             {
707                 if (pParam->pszValue != NULL)
708                     HeapFree(GetProcessHeap(), 0, pParam->pszValue);
709 
710                 pParam->pszValue = HeapAlloc(GetProcessHeap(), 0, (iLength + 1) * sizeof(WCHAR));
711             }
712 
713             if (pParam->pszValue != NULL)
714             {
715                 wcscpy(pParam->pszValue,
716                        pParam->pEnumOptions[iIndex].pszValue);
717                 pParam->cchValueLength = iLength;
718             }
719         }
720     }
721     else
722     {
723         iLength = Edit_GetTextLength(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT));
724         if (iLength > pParam->cchValueLength)
725         {
726             if (pParam->pszValue != NULL)
727                 HeapFree(GetProcessHeap(), 0, pParam->pszValue);
728 
729             pParam->pszValue = HeapAlloc(GetProcessHeap(), 0, (iLength + 1) * sizeof(WCHAR));
730         }
731 
732         if (pParam->pszValue != NULL)
733         {
734             Edit_GetText(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT),
735                          pParam->pszValue,
736                          iLength + 1);
737             pParam->cchValueLength = iLength;
738         }
739     }
740 }
741 
742 
743 static
744 VOID
745 WriteParameterArray(
746     _In_ HWND hwnd,
747     _In_ PPARAMETER_ARRAY ParamArray)
748 {
749     PPARAMETER Param;
750     HKEY hDriverKey;
751     INT i;
752 
753     if (ParamArray == NULL)
754         return;
755 
756     hDriverKey = SetupDiOpenDevRegKey(ParamArray->DeviceInfoSet,
757                                       ParamArray->DeviceInfoData,
758                                       DICS_FLAG_GLOBAL,
759                                       0,
760                                       DIREG_DRV,
761                                       KEY_WRITE);
762     if (hDriverKey == INVALID_HANDLE_VALUE)
763     {
764         ERR("SetupDiOpenDevRegKey() failed\n");
765         return;
766     }
767 
768     for (i = 0; i < ParamArray->dwCount; i++)
769     {
770         Param = &ParamArray->Array[i];
771 
772         if (Param == ParamArray->pCurrentParam)
773         {
774             ReadParameterValue(hwnd, Param);
775         }
776 
777         if (Param->bPresent)
778         {
779             TRACE("Set '%S' --> '%S'\n", Param->pszName, Param->pszValue);
780             RegSetValueExW(hDriverKey,
781                            Param->pszName,
782                            0,
783                            REG_SZ,
784                            (LPBYTE)Param->pszValue,
785                            (wcslen(Param->pszValue) + 1) * sizeof(WCHAR));
786         }
787         else
788         {
789             TRACE("Delete '%S'\n", Param->pszName);
790             RegDeleteValueW(hDriverKey,
791                             Param->pszName);
792         }
793     }
794 
795     RegCloseKey(hDriverKey);
796 }
797 
798 
799 static
800 VOID
801 DisplayParameter(
802     _In_ HWND hwnd,
803     _In_ PPARAMETER Parameter)
804 {
805     HWND hwndControl;
806     LONG_PTR Style;
807     INT idx;
808     DWORD i;
809 
810     ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_PRESENT), (Parameter->bOptional) ? SW_SHOW : SW_HIDE);
811     ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_NOT_PRESENT), (Parameter->bOptional) ? SW_SHOW : SW_HIDE);
812     if (Parameter->bOptional)
813     {
814         if (Parameter->bPresent)
815             Button_SetCheck(GetDlgItem(hwnd, IDC_PROPERTY_PRESENT), BST_CHECKED);
816         else
817             Button_SetCheck(GetDlgItem(hwnd, IDC_PROPERTY_NOT_PRESENT), BST_CHECKED);
818     }
819 
820     switch (Parameter->Type)
821     {
822         case INT_TYPE:
823         case LONG_TYPE:
824         case WORD_TYPE:
825         case DWORD_TYPE:
826             ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST), SW_HIDE);
827 
828             hwndControl = GetDlgItem(hwnd, IDC_PROPERTY_VALUE_UPDN);
829 
830             if (Parameter->Type != DWORD_TYPE)
831             {
832                 EnableWindow(hwndControl, Parameter->bPresent);
833                 ShowWindow(hwndControl, SW_SHOW);
834             }
835 
836             if (Parameter->Type == WORD_TYPE || Parameter->Type == DWORD_TYPE)
837                 SendMessage(hwndControl, UDM_SETBASE, Parameter->iBase, 0);
838             else
839                 SendMessage(hwndControl, UDM_SETBASE, 10, 0);
840 
841             if (Parameter->Type == INT_TYPE || Parameter->Type == LONG_TYPE)
842             {
843                 TRACE("SetMin %ld  SetMax %ld\n", Parameter->u.l.lMin, Parameter->u.l.lMax);
844                 SendMessage(hwndControl, UDM_SETRANGE32, Parameter->u.l.lMin, Parameter->u.l.lMax);
845             }
846             else if (Parameter->Type == WORD_TYPE)
847             {
848                 TRACE("SetMin %lu  SetMax %lu\n", Parameter->u.dw.dwMin, Parameter->u.dw.dwMax);
849                 SendMessage(hwndControl, UDM_SETRANGE32, (INT)Parameter->u.dw.dwMin, (INT)Parameter->u.dw.dwMax);
850             }
851 
852             hwndControl = GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT);
853             EnableWindow(hwndControl, Parameter->bPresent);
854             ShowWindow(hwndControl, SW_SHOW);
855 
856             Style = GetWindowLongPtr(hwndControl, GWL_STYLE);
857             Style |= ES_NUMBER;
858             SetWindowLongPtr(hwndControl, GWL_STYLE, Style);
859 
860             Edit_LimitText(hwndControl, 0);
861 
862             if (Parameter->pszValue)
863                 Edit_SetText(hwndControl, Parameter->pszValue);
864             else if (Parameter->pszDefault)
865                 Edit_SetText(hwndControl, Parameter->pszDefault);
866             break;
867 
868         case EDIT_TYPE:
869             ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_UPDN), SW_HIDE);
870             ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST), SW_HIDE);
871 
872             hwndControl = GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT);
873             EnableWindow(hwndControl, Parameter->bPresent);
874             ShowWindow(hwndControl, SW_SHOW);
875 
876             Style = GetWindowLongPtr(hwndControl, GWL_STYLE);
877             Style &= ~ES_NUMBER;
878             if (Parameter->bUpperCase)
879                 Style |= ES_UPPERCASE;
880             else
881                 Style &= ~ES_UPPERCASE;
882             SetWindowLongPtr(hwndControl, GWL_STYLE, Style);
883 
884             Edit_LimitText(hwndControl, Parameter->iTextLimit);
885 
886             if (Parameter->pszValue)
887                 Edit_SetText(hwndControl, Parameter->pszValue);
888             else if (Parameter->pszDefault)
889                 Edit_SetText(hwndControl, Parameter->pszDefault);
890             break;
891 
892         case ENUM_TYPE:
893             ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT), SW_HIDE);
894             ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_UPDN), SW_HIDE);
895 
896             hwndControl = GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST);
897             EnableWindow(hwndControl, Parameter->bPresent);
898             ShowWindow(hwndControl, SW_SHOW);
899 
900             ComboBox_ResetContent(hwndControl);
901 
902             if (Parameter->pEnumOptions != NULL && Parameter->dwEnumOptions != 0)
903             {
904                 for (i = 0; i < Parameter->dwEnumOptions; i++)
905                 {
906                     ComboBox_AddString(hwndControl, Parameter->pEnumOptions[i].pszName);
907                 }
908             }
909 
910             if (Parameter->pszValue)
911             {
912                 idx = FindEnumOption(Parameter, Parameter->pszValue);
913                 if (idx != CB_ERR)
914                     ComboBox_SetCurSel(hwndControl, idx);
915             }
916             else if (Parameter->pszDefault)
917             {
918                 idx = FindEnumOption(Parameter, Parameter->pszDefault);
919                 if (idx != CB_ERR)
920                     ComboBox_SetCurSel(hwndControl, idx);
921             }
922             break;
923 
924         default:
925             break;
926     }
927 }
928 
929 
930 static
931 BOOL
932 OnInitDialog(
933     HWND hwnd,
934     WPARAM wParam,
935     LPARAM lParam)
936 {
937     PPARAMETER_ARRAY pParamArray;
938     HWND hwndControl;
939     PWSTR pszText;
940     DWORD i;
941     INT idx;
942 
943     TRACE("OnInitDialog()\n");
944 
945     pParamArray = (PPARAMETER_ARRAY)((LPPROPSHEETPAGEW)lParam)->lParam;
946     if (pParamArray == NULL)
947     {
948         ERR("pParamArray is NULL\n");
949         return FALSE;
950     }
951 
952     SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)pParamArray);
953 
954     hwndControl = GetDlgItem(hwnd, IDC_PROPERTY_NAME);
955     if (hwndControl)
956     {
957         for (i = 0; i < pParamArray->dwCount; i++)
958         {
959             if (pParamArray->Array[i].pszDescription != NULL)
960                 pszText = pParamArray->Array[i].pszDescription;
961             else
962                 pszText = pParamArray->Array[i].pszName;
963 
964             idx = ListBox_AddString(hwndControl, pszText);
965             if (idx != LB_ERR)
966                 ListBox_SetItemData(hwndControl, idx, (LPARAM)&pParamArray->Array[i]);
967         }
968 
969         if (pParamArray->dwCount > 0)
970         {
971             ListBox_SetCurSel(hwndControl, 0);
972             pParamArray->pCurrentParam = (PPARAMETER)ListBox_GetItemData(hwndControl, 0);
973             DisplayParameter(hwnd, pParamArray->pCurrentParam);
974         }
975     }
976 
977     return TRUE;
978 }
979 
980 
981 static
982 VOID
983 OnCommand(
984     HWND hwnd,
985     WPARAM wParam,
986     LPARAM lParam)
987 {
988     PPARAMETER_ARRAY pParamArray;
989     INT iIndex;
990 
991     TRACE("OnCommand()\n");
992 
993     pParamArray = (PPARAMETER_ARRAY)GetWindowLongPtr(hwnd, DWLP_USER);
994     if (pParamArray == NULL)
995     {
996         ERR("pParamArray is NULL\n");
997         return;
998     }
999 
1000     if ((LOWORD(wParam) == IDC_PROPERTY_NAME) && (HIWORD(wParam) == LBN_SELCHANGE))
1001     {
1002         if (pParamArray->pCurrentParam != NULL)
1003         {
1004             ReadParameterValue(hwnd, pParamArray->pCurrentParam);
1005         }
1006 
1007         iIndex = ListBox_GetCurSel((HWND)lParam);
1008         if (iIndex != LB_ERR && iIndex < pParamArray->dwCount)
1009         {
1010             pParamArray->pCurrentParam = (PPARAMETER)ListBox_GetItemData((HWND)lParam, iIndex);
1011             DisplayParameter(hwnd, pParamArray->pCurrentParam);
1012         }
1013     }
1014     else if ((LOWORD(wParam) == IDC_PROPERTY_PRESENT) && (HIWORD(wParam) == BN_CLICKED))
1015     {
1016         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT), TRUE);
1017         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_UPDN), TRUE);
1018         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST), TRUE);
1019         pParamArray->pCurrentParam->bPresent = TRUE;
1020     }
1021     else if ((LOWORD(wParam) == IDC_PROPERTY_NOT_PRESENT) && (HIWORD(wParam) == BN_CLICKED))
1022     {
1023         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT), FALSE);
1024         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_UPDN), FALSE);
1025         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST), FALSE);
1026         pParamArray->pCurrentParam->bPresent = FALSE;
1027     }
1028 }
1029 
1030 
1031 static
1032 VOID
1033 OnNotify(
1034     HWND hwnd,
1035     WPARAM wParam,
1036     LPARAM lParam)
1037 {
1038     PPARAMETER_ARRAY pParamArray;
1039 
1040     TRACE("OnNotify()\n");
1041 
1042     pParamArray = (PPARAMETER_ARRAY)GetWindowLongPtr(hwnd, DWLP_USER);
1043     if (pParamArray == NULL)
1044     {
1045         ERR("pParamArray is NULL\n");
1046         return;
1047     }
1048 
1049     if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
1050     {
1051         TRACE("PSN_APPLY!\n");
1052         WriteParameterArray(hwnd, pParamArray);
1053     }
1054     else if (((LPNMHDR)lParam)->code == (UINT)UDN_DELTAPOS)
1055     {
1056         LPNMUPDOWN pUpDown = (LPNMUPDOWN)lParam;
1057         pUpDown->iDelta *= pParamArray->pCurrentParam->iStep;
1058     }
1059 }
1060 
1061 
1062 static
1063 VOID
1064 OnDestroy(
1065     HWND hwnd)
1066 {
1067     PPARAMETER_ARRAY pParamArray;
1068 
1069     TRACE("OnDestroy()\n");
1070 
1071     pParamArray = (PPARAMETER_ARRAY)GetWindowLongPtr(hwnd, DWLP_USER);
1072     if (pParamArray == NULL)
1073     {
1074         ERR("pParamArray is NULL\n");
1075         return;
1076     }
1077 
1078     FreeParameterArray(pParamArray);
1079     SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)NULL);
1080 }
1081 
1082 
1083 static
1084 INT_PTR
1085 CALLBACK
1086 NetPropertyPageDlgProc(
1087     HWND hwnd,
1088     UINT uMsg,
1089     WPARAM wParam,
1090     LPARAM lParam)
1091 {
1092     switch (uMsg)
1093     {
1094         case WM_INITDIALOG:
1095             return OnInitDialog(hwnd, wParam, lParam);
1096 
1097         case WM_COMMAND:
1098             OnCommand(hwnd, wParam, lParam);
1099             break;
1100 
1101         case WM_NOTIFY:
1102             OnNotify(hwnd, wParam, lParam);
1103             break;
1104 
1105         case WM_DESTROY:
1106             OnDestroy(hwnd);
1107             break;
1108 
1109         default:
1110             break;
1111     }
1112 
1113     return FALSE;
1114 }
1115 
1116 
1117 BOOL
1118 WINAPI
1119 NetPropPageProvider(
1120     PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest,
1121     LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc,
1122     LPARAM lParam)
1123 {
1124     PROPSHEETPAGEW PropSheetPage;
1125     HPROPSHEETPAGE hPropSheetPage;
1126     PPARAMETER_ARRAY ParameterArray = NULL;
1127 
1128     TRACE("NetPropPageProvider(%p %p %lx)\n",
1129           lpPropSheetPageRequest, lpfnAddPropSheetPageProc, lParam);
1130 
1131     if (!BuildParameterArray(lpPropSheetPageRequest->DeviceInfoSet,
1132                              lpPropSheetPageRequest->DeviceInfoData,
1133                              &ParameterArray))
1134         return FALSE;
1135 
1136     if (lpPropSheetPageRequest->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES)
1137     {
1138         TRACE("SPPSR_ENUM_ADV_DEVICE_PROPERTIES\n");
1139 
1140         PropSheetPage.dwSize = sizeof(PROPSHEETPAGEW);
1141         PropSheetPage.dwFlags = 0;
1142         PropSheetPage.hInstance = netcfgx_hInstance;
1143         PropSheetPage.u.pszTemplate = MAKEINTRESOURCE(IDD_NET_PROPERTY_DLG);
1144         PropSheetPage.pfnDlgProc = NetPropertyPageDlgProc;
1145         PropSheetPage.lParam = (LPARAM)ParameterArray;
1146         PropSheetPage.pfnCallback = NULL;
1147 
1148         hPropSheetPage = CreatePropertySheetPageW(&PropSheetPage);
1149         if (hPropSheetPage == NULL)
1150         {
1151             ERR("CreatePropertySheetPageW() failed!\n");
1152             return FALSE;
1153         }
1154 
1155         if (!(*lpfnAddPropSheetPageProc)(hPropSheetPage, lParam))
1156         {
1157             ERR("lpfnAddPropSheetPageProc() failed!\n");
1158             DestroyPropertySheetPage(hPropSheetPage);
1159             return FALSE;
1160         }
1161     }
1162 
1163     TRACE("Done!\n");
1164 
1165     return TRUE;
1166 }
1167 
1168 /* EOF */
1169