xref: /reactos/dll/win32/netcfgx/propertypage.c (revision 680f103f)
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
FreeParameterArray(_In_ PPARAMETER_ARRAY ParamArray)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
GetStringValue(_In_ HKEY hKey,_In_ PWSTR pValueName,_Out_ PWSTR * pString,_Out_opt_ PDWORD pdwStringLength)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
GetBooleanValue(_In_ HKEY hKey,_In_ PWSTR pValueName,_In_ BOOL bDefault,_Out_ PBOOL pValue)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
GetIntValue(_In_ HKEY hKey,_In_ PWSTR pValueName,_In_ INT iDefault,_Out_ PINT pValue)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
GetLongValue(_In_ HKEY hKey,_In_ PWSTR pValueName,_In_ LONG lDefault,_Out_ PLONG pValue)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
GetDWordValue(_In_ HKEY hKey,_In_ PWSTR pValueName,_In_ DWORD dwDefault,_Out_ PDWORD pValue)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
GetEnumOptions(_In_ HKEY hKey,_In_ PPARAMETER pParameter)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
FindEnumOption(_In_ PPARAMETER pParameter,_In_ PWSTR pszValue)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
BuildParameterArray(_In_ HDEVINFO DeviceInfoSet,_In_ PSP_DEVINFO_DATA DeviceInfoData,_Out_ PPARAMETER_ARRAY * ParameterArray)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                 else if (ParamArray->Array[dwIndex].Type == DWORD_TYPE)
598                 {
599                     dwDefaultMin = 0UL;
600                     dwDefaultMax = 4294967295UL; //MAX_DWORD;
601                 }
602 
603                 if (ParamArray->Array[dwIndex].Type == INT_TYPE ||
604                     ParamArray->Array[dwIndex].Type == LONG_TYPE)
605                 {
606                     GetLongValue(hParamKey,
607                                  L"Min",
608                                  lDefaultMin,
609                                  &ParamArray->Array[dwIndex].u.l.lMin);
610 
611                     GetLongValue(hParamKey,
612                                  L"Max",
613                                  lDefaultMax,
614                                  &ParamArray->Array[dwIndex].u.l.lMax);
615                 }
616                 else if (ParamArray->Array[dwIndex].Type == WORD_TYPE ||
617                          ParamArray->Array[dwIndex].Type == DWORD_TYPE)
618                 {
619                     GetDWordValue(hParamKey,
620                                   L"Min",
621                                   dwDefaultMin,
622                                   &ParamArray->Array[dwIndex].u.dw.dwMin);
623 
624                     GetDWordValue(hParamKey,
625                                   L"Max",
626                                   dwDefaultMax,
627                                   &ParamArray->Array[dwIndex].u.dw.dwMax);
628                 }
629 
630                 GetIntValue(hParamKey,
631                             L"Base",
632                             10,
633                             &ParamArray->Array[dwIndex].iBase);
634 
635                 GetIntValue(hParamKey,
636                             L"Step",
637                             1,
638                             &ParamArray->Array[dwIndex].iStep);
639             }
640             else if (ParamArray->Array[dwIndex].Type == EDIT_TYPE)
641             {
642                 GetBooleanValue(hParamKey,
643                                 L"UpperCase",
644                                 FALSE,
645                                 &ParamArray->Array[dwIndex].bUpperCase);
646 
647                 GetIntValue(hParamKey,
648                             L"TextLimit",
649                             0,
650                             &ParamArray->Array[dwIndex].iTextLimit);
651             }
652             else if (ParamArray->Array[dwIndex].Type == ENUM_TYPE)
653             {
654                 GetEnumOptions(hParamKey,
655                                &ParamArray->Array[dwIndex]);
656             }
657 
658             RegCloseKey(hParamKey);
659         }
660 
661         lError = GetStringValue(hDriverKey,
662                                 ParamArray->Array[dwIndex].pszName,
663                                 &ParamArray->Array[dwIndex].pszValue,
664                                 &ParamArray->Array[dwIndex].cchValueLength);
665         if ((lError == ERROR_SUCCESS) ||
666             (ParamArray->Array[dwIndex].pszDefault != NULL))
667         {
668             ParamArray->Array[dwIndex].bPresent = TRUE;
669         }
670     }
671 
672     *ParameterArray = ParamArray;
673     ret = TRUE;
674 
675 done:
676     if (ret == FALSE && ParamArray != NULL)
677         FreeParameterArray(ParamArray);
678 
679     if (hParamsKey != INVALID_HANDLE_VALUE)
680         RegCloseKey(hParamsKey);
681 
682     if (hDriverKey != INVALID_HANDLE_VALUE)
683         RegCloseKey(hDriverKey);
684 
685     return ret;
686 }
687 
688 
689 static
690 VOID
ReadParameterValue(HWND hwnd,PPARAMETER pParam)691 ReadParameterValue(
692      HWND hwnd,
693      PPARAMETER pParam)
694 {
695     INT iIndex, iLength;
696 
697     if (pParam->Type == ENUM_TYPE)
698     {
699         iIndex = ComboBox_GetCurSel(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST));
700         if (iIndex != CB_ERR && iIndex < pParam->dwEnumOptions)
701         {
702             iLength = wcslen(pParam->pEnumOptions[iIndex].pszValue);
703             if (iLength > pParam->cchValueLength)
704             {
705                 if (pParam->pszValue != NULL)
706                     HeapFree(GetProcessHeap(), 0, pParam->pszValue);
707 
708                 pParam->pszValue = HeapAlloc(GetProcessHeap(), 0, (iLength + 1) * sizeof(WCHAR));
709             }
710 
711             if (pParam->pszValue != NULL)
712             {
713                 wcscpy(pParam->pszValue,
714                        pParam->pEnumOptions[iIndex].pszValue);
715                 pParam->cchValueLength = iLength;
716             }
717         }
718     }
719     else
720     {
721         iLength = Edit_GetTextLength(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT));
722         if (iLength > pParam->cchValueLength)
723         {
724             if (pParam->pszValue != NULL)
725                 HeapFree(GetProcessHeap(), 0, pParam->pszValue);
726 
727             pParam->pszValue = HeapAlloc(GetProcessHeap(), 0, (iLength + 1) * sizeof(WCHAR));
728         }
729 
730         if (pParam->pszValue != NULL)
731         {
732             Edit_GetText(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT),
733                          pParam->pszValue,
734                          iLength + 1);
735             pParam->cchValueLength = iLength;
736         }
737     }
738 }
739 
740 
741 static
742 VOID
WriteParameterArray(_In_ HWND hwnd,_In_ PPARAMETER_ARRAY ParamArray)743 WriteParameterArray(
744     _In_ HWND hwnd,
745     _In_ PPARAMETER_ARRAY ParamArray)
746 {
747     SP_DEVINSTALL_PARAMS_W InstallParams;
748     PPARAMETER Param;
749     HKEY hDriverKey;
750     INT i;
751 
752     if (ParamArray == NULL)
753         return;
754 
755     hDriverKey = SetupDiOpenDevRegKey(ParamArray->DeviceInfoSet,
756                                       ParamArray->DeviceInfoData,
757                                       DICS_FLAG_GLOBAL,
758                                       0,
759                                       DIREG_DRV,
760                                       KEY_WRITE);
761     if (hDriverKey == INVALID_HANDLE_VALUE)
762     {
763         ERR("SetupDiOpenDevRegKey() failed\n");
764         return;
765     }
766 
767     for (i = 0; i < ParamArray->dwCount; i++)
768     {
769         Param = &ParamArray->Array[i];
770 
771         if (Param == ParamArray->pCurrentParam)
772         {
773             ReadParameterValue(hwnd, Param);
774         }
775 
776         if (Param->bPresent)
777         {
778             TRACE("Set '%S' --> '%S'\n", Param->pszName, Param->pszValue);
779             RegSetValueExW(hDriverKey,
780                            Param->pszName,
781                            0,
782                            REG_SZ,
783                            (LPBYTE)Param->pszValue,
784                            (wcslen(Param->pszValue) + 1) * sizeof(WCHAR));
785         }
786         else
787         {
788             TRACE("Delete '%S'\n", Param->pszName);
789             RegDeleteValueW(hDriverKey,
790                             Param->pszName);
791         }
792     }
793 
794     RegCloseKey(hDriverKey);
795 
796     /* Notify the installer of changes to the properties */
797     InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
798     if (SetupDiGetDeviceInstallParamsW(ParamArray->DeviceInfoSet,
799                                        ParamArray->DeviceInfoData,
800                                        &InstallParams))
801     {
802         InstallParams.FlagsEx |= DI_FLAGSEX_PROPCHANGE_PENDING;
803 
804         SetupDiSetDeviceInstallParamsW(ParamArray->DeviceInfoSet,
805                                        ParamArray->DeviceInfoData,
806                                        &InstallParams);
807     }
808 }
809 
810 
811 static
812 VOID
DisplayParameter(_In_ HWND hwnd,_In_ PPARAMETER Parameter)813 DisplayParameter(
814     _In_ HWND hwnd,
815     _In_ PPARAMETER Parameter)
816 {
817     HWND hwndControl;
818     LONG_PTR Style;
819     INT idx;
820     DWORD i;
821 
822     ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_PRESENT), (Parameter->bOptional) ? SW_SHOW : SW_HIDE);
823     ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_NOT_PRESENT), (Parameter->bOptional) ? SW_SHOW : SW_HIDE);
824     if (Parameter->bOptional)
825     {
826         if (Parameter->bPresent)
827             Button_SetCheck(GetDlgItem(hwnd, IDC_PROPERTY_PRESENT), BST_CHECKED);
828         else
829             Button_SetCheck(GetDlgItem(hwnd, IDC_PROPERTY_NOT_PRESENT), BST_CHECKED);
830     }
831 
832     switch (Parameter->Type)
833     {
834         case INT_TYPE:
835         case LONG_TYPE:
836         case WORD_TYPE:
837         case DWORD_TYPE:
838             ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST), SW_HIDE);
839 
840             hwndControl = GetDlgItem(hwnd, IDC_PROPERTY_VALUE_UPDN);
841 
842             if (Parameter->Type != DWORD_TYPE)
843             {
844                 EnableWindow(hwndControl, Parameter->bPresent);
845                 ShowWindow(hwndControl, SW_SHOW);
846             }
847 
848             if (Parameter->Type == WORD_TYPE || Parameter->Type == DWORD_TYPE)
849                 SendMessage(hwndControl, UDM_SETBASE, Parameter->iBase, 0);
850             else
851                 SendMessage(hwndControl, UDM_SETBASE, 10, 0);
852 
853             if (Parameter->Type == INT_TYPE || Parameter->Type == LONG_TYPE)
854             {
855                 TRACE("SetMin %ld  SetMax %ld\n", Parameter->u.l.lMin, Parameter->u.l.lMax);
856                 SendMessage(hwndControl, UDM_SETRANGE32, Parameter->u.l.lMin, Parameter->u.l.lMax);
857             }
858             else if (Parameter->Type == WORD_TYPE)
859             {
860                 TRACE("SetMin %lu  SetMax %lu\n", Parameter->u.dw.dwMin, Parameter->u.dw.dwMax);
861                 SendMessage(hwndControl, UDM_SETRANGE32, (INT)Parameter->u.dw.dwMin, (INT)Parameter->u.dw.dwMax);
862             }
863 
864             hwndControl = GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT);
865             EnableWindow(hwndControl, Parameter->bPresent);
866             ShowWindow(hwndControl, SW_SHOW);
867 
868             Style = GetWindowLongPtr(hwndControl, GWL_STYLE);
869             Style |= ES_NUMBER;
870             SetWindowLongPtr(hwndControl, GWL_STYLE, Style);
871 
872             Edit_LimitText(hwndControl, 0);
873 
874             if (Parameter->pszValue)
875                 Edit_SetText(hwndControl, Parameter->pszValue);
876             else if (Parameter->pszDefault)
877                 Edit_SetText(hwndControl, Parameter->pszDefault);
878             break;
879 
880         case EDIT_TYPE:
881             ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_UPDN), SW_HIDE);
882             ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST), SW_HIDE);
883 
884             hwndControl = GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT);
885             EnableWindow(hwndControl, Parameter->bPresent);
886             ShowWindow(hwndControl, SW_SHOW);
887 
888             Style = GetWindowLongPtr(hwndControl, GWL_STYLE);
889             Style &= ~ES_NUMBER;
890             if (Parameter->bUpperCase)
891                 Style |= ES_UPPERCASE;
892             else
893                 Style &= ~ES_UPPERCASE;
894             SetWindowLongPtr(hwndControl, GWL_STYLE, Style);
895 
896             Edit_LimitText(hwndControl, Parameter->iTextLimit);
897 
898             if (Parameter->pszValue)
899                 Edit_SetText(hwndControl, Parameter->pszValue);
900             else if (Parameter->pszDefault)
901                 Edit_SetText(hwndControl, Parameter->pszDefault);
902             break;
903 
904         case ENUM_TYPE:
905             ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT), SW_HIDE);
906             ShowWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_UPDN), SW_HIDE);
907 
908             hwndControl = GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST);
909             EnableWindow(hwndControl, Parameter->bPresent);
910             ShowWindow(hwndControl, SW_SHOW);
911 
912             ComboBox_ResetContent(hwndControl);
913 
914             if (Parameter->pEnumOptions != NULL && Parameter->dwEnumOptions != 0)
915             {
916                 for (i = 0; i < Parameter->dwEnumOptions; i++)
917                 {
918                     ComboBox_AddString(hwndControl, Parameter->pEnumOptions[i].pszName);
919                 }
920             }
921 
922             if (Parameter->pszValue)
923             {
924                 idx = FindEnumOption(Parameter, Parameter->pszValue);
925                 if (idx != CB_ERR)
926                     ComboBox_SetCurSel(hwndControl, idx);
927             }
928             else if (Parameter->pszDefault)
929             {
930                 idx = FindEnumOption(Parameter, Parameter->pszDefault);
931                 if (idx != CB_ERR)
932                     ComboBox_SetCurSel(hwndControl, idx);
933             }
934             break;
935 
936         default:
937             break;
938     }
939 }
940 
941 
942 static
943 BOOL
OnInitDialog(HWND hwnd,WPARAM wParam,LPARAM lParam)944 OnInitDialog(
945     HWND hwnd,
946     WPARAM wParam,
947     LPARAM lParam)
948 {
949     PPARAMETER_ARRAY pParamArray;
950     HWND hwndControl;
951     PWSTR pszText;
952     DWORD i;
953     INT idx;
954 
955     TRACE("OnInitDialog()\n");
956 
957     pParamArray = (PPARAMETER_ARRAY)((LPPROPSHEETPAGEW)lParam)->lParam;
958     if (pParamArray == NULL)
959     {
960         ERR("pParamArray is NULL\n");
961         return FALSE;
962     }
963 
964     SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)pParamArray);
965 
966     hwndControl = GetDlgItem(hwnd, IDC_PROPERTY_NAME);
967     if (hwndControl)
968     {
969         for (i = 0; i < pParamArray->dwCount; i++)
970         {
971             if (pParamArray->Array[i].pszDescription != NULL)
972                 pszText = pParamArray->Array[i].pszDescription;
973             else
974                 pszText = pParamArray->Array[i].pszName;
975 
976             idx = ListBox_AddString(hwndControl, pszText);
977             if (idx != LB_ERR)
978                 ListBox_SetItemData(hwndControl, idx, (LPARAM)&pParamArray->Array[i]);
979         }
980 
981         if (pParamArray->dwCount > 0)
982         {
983             ListBox_SetCurSel(hwndControl, 0);
984             pParamArray->pCurrentParam = (PPARAMETER)ListBox_GetItemData(hwndControl, 0);
985             DisplayParameter(hwnd, pParamArray->pCurrentParam);
986         }
987     }
988 
989     return TRUE;
990 }
991 
992 
993 static
994 VOID
OnCommand(HWND hwnd,WPARAM wParam,LPARAM lParam)995 OnCommand(
996     HWND hwnd,
997     WPARAM wParam,
998     LPARAM lParam)
999 {
1000     PPARAMETER_ARRAY pParamArray;
1001     INT iIndex;
1002 
1003     TRACE("OnCommand()\n");
1004 
1005     pParamArray = (PPARAMETER_ARRAY)GetWindowLongPtr(hwnd, DWLP_USER);
1006     if (pParamArray == NULL)
1007     {
1008         ERR("pParamArray is NULL\n");
1009         return;
1010     }
1011 
1012     if ((LOWORD(wParam) == IDC_PROPERTY_NAME) && (HIWORD(wParam) == LBN_SELCHANGE))
1013     {
1014         if (pParamArray->pCurrentParam != NULL)
1015         {
1016             ReadParameterValue(hwnd, pParamArray->pCurrentParam);
1017         }
1018 
1019         iIndex = ListBox_GetCurSel((HWND)lParam);
1020         if (iIndex != LB_ERR && iIndex < pParamArray->dwCount)
1021         {
1022             pParamArray->pCurrentParam = (PPARAMETER)ListBox_GetItemData((HWND)lParam, iIndex);
1023             DisplayParameter(hwnd, pParamArray->pCurrentParam);
1024         }
1025     }
1026     else if ((LOWORD(wParam) == IDC_PROPERTY_PRESENT) && (HIWORD(wParam) == BN_CLICKED))
1027     {
1028         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT), TRUE);
1029         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_UPDN), TRUE);
1030         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST), TRUE);
1031         pParamArray->pCurrentParam->bPresent = TRUE;
1032     }
1033     else if ((LOWORD(wParam) == IDC_PROPERTY_NOT_PRESENT) && (HIWORD(wParam) == BN_CLICKED))
1034     {
1035         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_EDIT), FALSE);
1036         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_UPDN), FALSE);
1037         EnableWindow(GetDlgItem(hwnd, IDC_PROPERTY_VALUE_LIST), FALSE);
1038         pParamArray->pCurrentParam->bPresent = FALSE;
1039     }
1040 }
1041 
1042 
1043 static
1044 VOID
OnNotify(HWND hwnd,WPARAM wParam,LPARAM lParam)1045 OnNotify(
1046     HWND hwnd,
1047     WPARAM wParam,
1048     LPARAM lParam)
1049 {
1050     PPARAMETER_ARRAY pParamArray;
1051 
1052     TRACE("OnNotify()\n");
1053 
1054     pParamArray = (PPARAMETER_ARRAY)GetWindowLongPtr(hwnd, DWLP_USER);
1055     if (pParamArray == NULL)
1056     {
1057         ERR("pParamArray is NULL\n");
1058         return;
1059     }
1060 
1061     if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
1062     {
1063         TRACE("PSN_APPLY!\n");
1064         WriteParameterArray(hwnd, pParamArray);
1065     }
1066     else if (((LPNMHDR)lParam)->code == (UINT)UDN_DELTAPOS)
1067     {
1068         LPNMUPDOWN pUpDown = (LPNMUPDOWN)lParam;
1069         pUpDown->iDelta *= pParamArray->pCurrentParam->iStep;
1070     }
1071 }
1072 
1073 
1074 static
1075 VOID
OnDestroy(HWND hwnd)1076 OnDestroy(
1077     HWND hwnd)
1078 {
1079     PPARAMETER_ARRAY pParamArray;
1080 
1081     TRACE("OnDestroy()\n");
1082 
1083     pParamArray = (PPARAMETER_ARRAY)GetWindowLongPtr(hwnd, DWLP_USER);
1084     if (pParamArray == NULL)
1085     {
1086         ERR("pParamArray is NULL\n");
1087         return;
1088     }
1089 
1090     FreeParameterArray(pParamArray);
1091     SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)NULL);
1092 }
1093 
1094 
1095 static
1096 INT_PTR
1097 CALLBACK
NetPropertyPageDlgProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)1098 NetPropertyPageDlgProc(
1099     HWND hwnd,
1100     UINT uMsg,
1101     WPARAM wParam,
1102     LPARAM lParam)
1103 {
1104     switch (uMsg)
1105     {
1106         case WM_INITDIALOG:
1107             return OnInitDialog(hwnd, wParam, lParam);
1108 
1109         case WM_COMMAND:
1110             OnCommand(hwnd, wParam, lParam);
1111             break;
1112 
1113         case WM_NOTIFY:
1114             OnNotify(hwnd, wParam, lParam);
1115             break;
1116 
1117         case WM_DESTROY:
1118             OnDestroy(hwnd);
1119             break;
1120 
1121         default:
1122             break;
1123     }
1124 
1125     return FALSE;
1126 }
1127 
1128 
1129 BOOL
1130 WINAPI
NetPropPageProvider(PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest,LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc,LPARAM lParam)1131 NetPropPageProvider(
1132     PSP_PROPSHEETPAGE_REQUEST lpPropSheetPageRequest,
1133     LPFNADDPROPSHEETPAGE lpfnAddPropSheetPageProc,
1134     LPARAM lParam)
1135 {
1136     PROPSHEETPAGEW PropSheetPage;
1137     HPROPSHEETPAGE hPropSheetPage;
1138     PPARAMETER_ARRAY ParameterArray = NULL;
1139 
1140     TRACE("NetPropPageProvider(%p %p %lx)\n",
1141           lpPropSheetPageRequest, lpfnAddPropSheetPageProc, lParam);
1142 
1143     if (!BuildParameterArray(lpPropSheetPageRequest->DeviceInfoSet,
1144                              lpPropSheetPageRequest->DeviceInfoData,
1145                              &ParameterArray))
1146         return FALSE;
1147 
1148     if (lpPropSheetPageRequest->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES)
1149     {
1150         TRACE("SPPSR_ENUM_ADV_DEVICE_PROPERTIES\n");
1151 
1152         PropSheetPage.dwSize = sizeof(PROPSHEETPAGEW);
1153         PropSheetPage.dwFlags = 0;
1154         PropSheetPage.hInstance = netcfgx_hInstance;
1155         PropSheetPage.u.pszTemplate = MAKEINTRESOURCE(IDD_NET_PROPERTY_DLG);
1156         PropSheetPage.pfnDlgProc = NetPropertyPageDlgProc;
1157         PropSheetPage.lParam = (LPARAM)ParameterArray;
1158         PropSheetPage.pfnCallback = NULL;
1159 
1160         hPropSheetPage = CreatePropertySheetPageW(&PropSheetPage);
1161         if (hPropSheetPage == NULL)
1162         {
1163             ERR("CreatePropertySheetPageW() failed!\n");
1164             return FALSE;
1165         }
1166 
1167         if (!(*lpfnAddPropSheetPageProc)(hPropSheetPage, lParam))
1168         {
1169             ERR("lpfnAddPropSheetPageProc() failed!\n");
1170             DestroyPropertySheetPage(hPropSheetPage);
1171             return FALSE;
1172         }
1173     }
1174 
1175     TRACE("Done!\n");
1176 
1177     return TRUE;
1178 }
1179 
1180 /* EOF */
1181