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