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