xref: /reactos/dll/cpl/sysdm/hardprof.c (revision 4567e13e)
1 /*
2  * PROJECT:     ReactOS System Control Panel Applet
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        dll/cpl/sysdm/hardprof.c
5  * PURPOSE:     Modify hardware profiles
6  * COPYRIGHT:   Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
7  *
8  */
9 
10 #include "precomp.h"
11 
12 #include <debug.h>
13 
14 #define PROFILE_NAME_LENGTH 80
15 
16 typedef struct _PROFILE
17 {
18     WCHAR szFriendlyName[PROFILE_NAME_LENGTH];
19     WCHAR szName[5];
20     DWORD dwProfileNumber;
21     DWORD dwPreferenceOrder;
22 } PROFILE, *PPROFILE;
23 
24 typedef struct _PROFILEDATA
25 {
26     DWORD dwProfileCount;
27     DWORD dwLastProfile;
28     DWORD dwSelectedProfile;
29     DWORD dwSelectedProfileIndex;
30     PPROFILE pProfiles;
31 } PROFILEDATA, *PPROFILEDATA;
32 
33 typedef struct _PROFILENAMES
34 {
35     WCHAR szSourceName[PROFILE_NAME_LENGTH];
36     WCHAR szDestinationName[PROFILE_NAME_LENGTH];
37     PPROFILEDATA pProfileData;
38 } PROFILENAMES, *PPROFILENAMES;
39 
40 
41 static
42 VOID
43 UpdateButtons(
44     HWND hwndDlg,
45     PPROFILEDATA pProfileData)
46 {
47     EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFPROP), (pProfileData->dwSelectedProfileIndex != (DWORD)-1) ? TRUE : FALSE);
48     EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFCOPY), (pProfileData->dwSelectedProfileIndex != (DWORD)-1) ? TRUE : FALSE);
49     EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFRENAME), (pProfileData->dwSelectedProfileIndex != (DWORD)-1) ? TRUE : FALSE);
50     EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFDEL), (pProfileData->dwSelectedProfileIndex != (DWORD)-1) ? TRUE : FALSE);
51 
52     if (pProfileData->dwProfileCount < 2)
53     {
54         EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFUP), FALSE);
55         EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFDWN), FALSE);
56     }
57     else
58     {
59         EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFUP),
60                      (pProfileData->dwSelectedProfileIndex > 0) ? TRUE : FALSE);
61         EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFDWN),
62                      (pProfileData->dwSelectedProfileIndex < pProfileData->dwProfileCount - 1) ? TRUE : FALSE);
63     }
64 }
65 
66 
67 static
68 BOOL
69 IsProfileNameInUse(
70     PPROFILENAMES pProfileNames,
71     BOOL bIgnoreCurrent)
72 {
73     DWORD i;
74 
75     for (i = 0; i < pProfileNames->pProfileData->dwProfileCount; i++)
76     {
77         if (bIgnoreCurrent == TRUE && i == pProfileNames->pProfileData->dwSelectedProfileIndex)
78             continue;
79 
80         if (wcscmp(pProfileNames->pProfileData->pProfiles[i].szFriendlyName, pProfileNames->szDestinationName) == 0)
81             return TRUE;
82     }
83 
84     return FALSE;
85 }
86 
87 
88 static
89 INT_PTR
90 CALLBACK
91 CopyProfileDlgProc(
92     HWND hwndDlg,
93     UINT uMsg,
94     WPARAM wParam,
95     LPARAM lParam)
96 {
97     PPROFILENAMES pProfileNames;
98 
99     pProfileNames = (PPROFILENAMES)GetWindowLongPtr(hwndDlg, DWLP_USER);
100 
101     switch (uMsg)
102     {
103         case WM_INITDIALOG:
104             SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
105             pProfileNames = (PPROFILENAMES)lParam;
106 
107             /* Set the old name */
108             SetDlgItemText(hwndDlg, IDC_COPYPROFILEFROM, pProfileNames->szSourceName);
109 
110             /* Set the new name */
111             SendDlgItemMessageW(hwndDlg, IDC_COPYPROFILETO, EM_SETLIMITTEXT, PROFILE_NAME_LENGTH - 1, 0);
112             SetDlgItemText(hwndDlg, IDC_COPYPROFILETO, pProfileNames->szDestinationName);
113             break;
114 
115         case WM_COMMAND:
116             switch (LOWORD(wParam))
117             {
118                 case IDOK:
119                     GetDlgItemText(hwndDlg,
120                                    IDC_COPYPROFILETO,
121                                    pProfileNames->szDestinationName,
122                                    PROFILE_NAME_LENGTH);
123                     if (IsProfileNameInUse(pProfileNames, FALSE))
124                         ResourceMessageBox(hApplet,
125                                            NULL,
126                                            MB_OK | MB_ICONERROR,
127                                            IDS_HWPROFILE_WARNING,
128                                            IDS_HWPROFILE_ALREADY_IN_USE);
129                     else
130                         EndDialog(hwndDlg, IDOK);
131                     return TRUE;
132 
133                 case IDCANCEL:
134                     EndDialog(hwndDlg, IDCANCEL);
135                     return TRUE;
136             }
137             break;
138     }
139 
140     return FALSE;
141 }
142 
143 
144 static
145 VOID
146 CopyHardwareProfile(
147     HWND hwndDlg,
148     PPROFILEDATA pProfileData)
149 {
150     PROFILENAMES ProfileNames;
151     PPROFILE pProfile, pNewProfiles, pNewProfile;
152     WCHAR szBuffer[80];
153 
154     pProfile = &pProfileData->pProfiles[pProfileData->dwSelectedProfileIndex];
155 
156     LoadStringW(hApplet, IDS_HWPROFILE_PROFILE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR));
157 
158     wcscpy(ProfileNames.szSourceName, pProfile->szFriendlyName);
159     swprintf(ProfileNames.szDestinationName, L"%s %lu", szBuffer, pProfileData->dwProfileCount);
160 
161     ProfileNames.pProfileData = pProfileData;
162 
163     if (DialogBoxParam(hApplet,
164                        MAKEINTRESOURCE(IDD_COPYPROFILE),
165                        hwndDlg,
166                        CopyProfileDlgProc,
167                        (LPARAM)&ProfileNames) != IDOK)
168         return;
169 
170     /* Apply new name only if it has been changed */
171     if (wcscmp(ProfileNames.szSourceName, ProfileNames.szDestinationName) == 0)
172         return;
173 
174     /* Allocate memory for the new profile */
175     pNewProfiles = HeapReAlloc(GetProcessHeap(),
176                                HEAP_ZERO_MEMORY,
177                                pProfileData->pProfiles,
178                                (pProfileData->dwProfileCount + 1) * sizeof(PROFILE));
179     if (pNewProfiles == NULL)
180     {
181         DPRINT1("HeapReAlloc() failed!\n");
182         return;
183     }
184 
185     pProfileData->dwProfileCount++;
186     pProfileData->pProfiles = pNewProfiles;
187 
188     pNewProfile = &pProfileData->pProfiles[pProfileData->dwProfileCount - 1];
189 
190     CopyMemory(pNewProfile, pProfile, sizeof(PROFILE));
191 
192     wcscpy(pNewProfile->szFriendlyName, ProfileNames.szDestinationName);
193 
194     pNewProfile->dwProfileNumber = ++pProfileData->dwLastProfile;
195     swprintf(pNewProfile->szName, L"%04lu", pNewProfile->dwProfileNumber);
196 
197     pNewProfile->dwPreferenceOrder = pNewProfile->dwProfileNumber;
198 
199     SendDlgItemMessageW(hwndDlg, IDC_HRDPROFLSTBOX, LB_ADDSTRING, 0, (LPARAM)pNewProfile->szFriendlyName);
200 
201     UpdateButtons(hwndDlg, pProfileData);
202 }
203 
204 
205 static
206 INT_PTR
207 CALLBACK
208 RenameProfileDlgProc(
209     HWND hwndDlg,
210     UINT uMsg,
211     WPARAM wParam,
212     LPARAM lParam)
213 {
214     PPROFILENAMES pProfileNames;
215 
216     pProfileNames = (PPROFILENAMES)GetWindowLongPtr(hwndDlg, DWLP_USER);
217 
218     switch (uMsg)
219     {
220         case WM_INITDIALOG:
221             SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
222             pProfileNames = (PPROFILENAMES)lParam;
223 
224             /* Set the old name */
225             SetDlgItemText(hwndDlg, IDC_RENPROFEDITFROM, pProfileNames->szSourceName);
226 
227             /* Set the new name */
228             SendDlgItemMessageW(hwndDlg, IDC_RENPROFEDITTO, EM_SETLIMITTEXT, PROFILE_NAME_LENGTH - 1, 0);
229             SetDlgItemText(hwndDlg, IDC_RENPROFEDITTO, pProfileNames->szDestinationName);
230             break;
231 
232         case WM_COMMAND:
233             switch (LOWORD(wParam))
234             {
235                 case IDOK:
236                     GetDlgItemText(hwndDlg,
237                                    IDC_RENPROFEDITTO,
238                                    pProfileNames->szDestinationName,
239                                    PROFILE_NAME_LENGTH);
240                     if (IsProfileNameInUse(pProfileNames, TRUE))
241                         ResourceMessageBox(hApplet,
242                                            NULL,
243                                            MB_OK | MB_ICONERROR,
244                                            IDS_HWPROFILE_WARNING,
245                                            IDS_HWPROFILE_ALREADY_IN_USE);
246                     else
247                         EndDialog(hwndDlg, IDOK);
248                     return TRUE;
249 
250                 case IDCANCEL:
251                     EndDialog(hwndDlg, IDCANCEL);
252                     return TRUE;
253             }
254             break;
255     }
256 
257     return FALSE;
258 }
259 
260 
261 static
262 VOID
263 RenameHardwareProfile(
264     HWND hwndDlg,
265     PPROFILEDATA pProfileData)
266 {
267     PROFILENAMES ProfileNames;
268     PPROFILE pProfile;
269     WCHAR szBuffer[80];
270 
271     pProfile = &pProfileData->pProfiles[pProfileData->dwSelectedProfileIndex];
272 
273     LoadStringW(hApplet, IDS_HWPROFILE_PROFILE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR));
274 
275     wcscpy(ProfileNames.szSourceName, pProfile->szFriendlyName);
276     swprintf(ProfileNames.szDestinationName, L"%s %lu", szBuffer, pProfileData->dwProfileCount);
277 
278     ProfileNames.pProfileData = pProfileData;
279 
280     if (DialogBoxParam(hApplet,
281                        MAKEINTRESOURCE(IDD_RENAMEPROFILE),
282                        hwndDlg,
283                        RenameProfileDlgProc,
284                        (LPARAM)&ProfileNames) != IDOK)
285         return;
286 
287     /* Apply new name only if it has been changed */
288     if (wcscmp(pProfile->szFriendlyName, ProfileNames.szDestinationName) == 0)
289         return;
290 
291     /* Replace the profile name in the profile list */
292     wcscpy(pProfile->szFriendlyName, ProfileNames.szDestinationName);
293 
294     /* Replace the profile name in the listbox */
295     SendDlgItemMessageW(hwndDlg, IDC_HRDPROFLSTBOX, LB_DELETESTRING, pProfileData->dwSelectedProfileIndex, 0);
296     SendDlgItemMessageW(hwndDlg, IDC_HRDPROFLSTBOX, LB_INSERTSTRING, pProfileData->dwSelectedProfileIndex, (LPARAM)pProfile->szFriendlyName);
297 }
298 
299 
300 static
301 VOID
302 DeleteHardwareProfile(
303     HWND hwndDlg,
304     PPROFILEDATA pProfileData)
305 {
306     WCHAR szMessage[256];
307     WCHAR szBuffer[128];
308     WCHAR szCaption[80];
309     PPROFILE pProfiles;
310     PPROFILE pProfile;
311 
312     pProfile = &pProfileData->pProfiles[pProfileData->dwSelectedProfileIndex];
313 
314     LoadStringW(hApplet, IDS_HWPROFILE_CONFIRM_DELETE_TITLE, szCaption, sizeof(szCaption) / sizeof(WCHAR));
315     LoadStringW(hApplet, IDS_HWPROFILE_CONFIRM_DELETE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR));
316     swprintf(szMessage, szBuffer, pProfile->szFriendlyName);
317 
318     if (MessageBox(NULL,
319                    szMessage,
320                    szCaption,
321                    MB_YESNO | MB_ICONQUESTION) != IDYES)
322         return;
323 
324     SendDlgItemMessageW(hwndDlg, IDC_HRDPROFLSTBOX, LB_DELETESTRING, pProfileData->dwSelectedProfileIndex, 0);
325 
326     if (pProfileData->dwSelectedProfileIndex != pProfileData->dwProfileCount - 1)
327     {
328         RtlMoveMemory(&pProfileData->pProfiles[pProfileData->dwSelectedProfileIndex],
329                       &pProfileData->pProfiles[pProfileData->dwSelectedProfileIndex + 1],
330                       (pProfileData->dwProfileCount - pProfileData->dwSelectedProfileIndex - 1) * sizeof(PROFILE));
331     }
332     else
333     {
334         pProfileData->dwSelectedProfileIndex--;
335     }
336 
337     pProfiles = HeapReAlloc(GetProcessHeap(),
338                             HEAP_ZERO_MEMORY,
339                             pProfileData->pProfiles,
340                             (pProfileData->dwProfileCount - 1) * sizeof(PROFILE));
341     if (pProfiles == NULL)
342     {
343         DPRINT1("HeapReAlloc() failed!\n");
344         return;
345     }
346 
347     pProfileData->dwProfileCount--;
348     pProfileData->pProfiles = pProfiles;
349 
350     SendDlgItemMessageW(hwndDlg, IDC_HRDPROFLSTBOX, LB_SETCURSEL, pProfileData->dwSelectedProfileIndex, 0);
351 
352     UpdateButtons(hwndDlg, pProfileData);
353 }
354 
355 
356 static
357 VOID
358 MoveHardwareProfile(
359     HWND hwndDlg,
360     PPROFILEDATA pProfileData,
361     BOOL bMoveUp)
362 {
363     PROFILE TempProfile;
364     PPROFILE pSrcProfile, pDstProfile;
365     DWORD dwSrcIndex, dwDstIndex;
366 
367     dwSrcIndex = pProfileData->dwSelectedProfileIndex;
368     dwDstIndex = bMoveUp ? (dwSrcIndex - 1) : (dwSrcIndex + 1);
369 
370     pSrcProfile = &pProfileData->pProfiles[dwSrcIndex];
371     pDstProfile = &pProfileData->pProfiles[dwDstIndex];
372 
373     CopyMemory(&TempProfile, pDstProfile, sizeof(PROFILE));
374     CopyMemory(pDstProfile, pSrcProfile, sizeof(PROFILE));
375     CopyMemory(pSrcProfile, &TempProfile, sizeof(PROFILE));
376 
377     SendDlgItemMessageW(hwndDlg, IDC_HRDPROFLSTBOX, LB_DELETESTRING, dwSrcIndex, 0);
378     SendDlgItemMessageW(hwndDlg, IDC_HRDPROFLSTBOX, LB_INSERTSTRING, dwDstIndex, (LPARAM)pDstProfile->szFriendlyName);
379 
380     pProfileData->dwSelectedProfileIndex = dwDstIndex;
381     SendDlgItemMessageW(hwndDlg, IDC_HRDPROFLSTBOX, LB_SETCURSEL, pProfileData->dwSelectedProfileIndex, 0);
382 
383     UpdateButtons(hwndDlg, pProfileData);
384 }
385 
386 
387 static
388 INT_PTR
389 CALLBACK
390 HardwareProfilePropertiesDlgProc(
391     HWND hwndDlg,
392     UINT uMsg,
393     WPARAM wParam,
394     LPARAM lParam)
395 {
396     UNREFERENCED_PARAMETER(hwndDlg);
397     UNREFERENCED_PARAMETER(lParam);
398     UNREFERENCED_PARAMETER(wParam);
399 
400     switch (uMsg)
401     {
402         case WM_INITDIALOG:
403             return TRUE;
404 
405     }
406 
407     return FALSE;
408 }
409 
410 static int CALLBACK
411 PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam)
412 {
413     // NOTE: This callback is needed to set large icon correctly.
414     HICON hIcon;
415     switch (uMsg)
416     {
417         case PSCB_INITIALIZED:
418         {
419             hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDI_HARDPROF));
420             SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
421             break;
422         }
423     }
424     return 0;
425 }
426 
427 static
428 VOID
429 HardwareProfileProperties(
430     HWND hwndDlg,
431     PPROFILEDATA pProfileData)
432 {
433     HPROPSHEETPAGE hpsp;
434     PROPSHEETHEADER psh;
435     PROPSHEETPAGE psp;
436 
437     ZeroMemory(&psp, sizeof(psp));
438     psp.dwSize = sizeof(psp);
439     psp.dwFlags = PSP_DEFAULT;
440     psp.hInstance = hApplet;
441     psp.pszTemplate = MAKEINTRESOURCE(IDD_HARDWAREPROFILE);
442     psp.pfnDlgProc = HardwareProfilePropertiesDlgProc;
443 
444     hpsp = CreatePropertySheetPage(&psp);
445     if (hpsp == NULL)
446     {
447         return;
448     }
449 
450     ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
451     psh.dwSize = sizeof(PROPSHEETHEADER);
452     psh.dwFlags = PSH_PROPTITLE | PSH_USEICONID | PSH_USECALLBACK;
453     psh.hwndParent = hwndDlg;
454     psh.hInstance = hApplet;
455     psh.pszIcon = MAKEINTRESOURCEW(IDI_HARDPROF);
456     psh.pszCaption = pProfileData->pProfiles[pProfileData->dwSelectedProfileIndex].szFriendlyName;
457     psh.nPages = 1;
458     psh.nStartPage = 0;
459     psh.phpage = &hpsp;
460     psh.pfnCallback = PropSheetProc;
461 
462     PropertySheet(&psh);
463 }
464 
465 
466 static
467 DWORD
468 GetUserWaitInterval(VOID)
469 {
470     DWORD dwWaitInterval = 30;
471     DWORD dwSize;
472     HKEY hKey;
473 
474     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
475                       L"System\\CurrentControlSet\\Control\\IDConfigDB",
476                       0,
477                       KEY_QUERY_VALUE,
478                       &hKey))
479         return dwWaitInterval;
480 
481     dwSize = sizeof(DWORD);
482     RegQueryValueExW(hKey,
483                      L"UserWaitInterval",
484                      NULL,
485                      NULL,
486                      (LPBYTE)&dwWaitInterval,
487                      &dwSize);
488 
489     RegCloseKey(hKey);
490 
491     return dwWaitInterval;
492 }
493 
494 
495 static
496 VOID
497 SetUserWaitInterval(DWORD dwWaitInterval)
498 {
499     HKEY hKey;
500 
501     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
502                       L"System\\CurrentControlSet\\Control\\IDConfigDB",
503                       0,
504                       KEY_SET_VALUE,
505                       &hKey))
506         return;
507 
508     RegSetValueExW(hKey,
509                    L"UserWaitInterval",
510                    0,
511                    REG_DWORD,
512                    (LPBYTE)&dwWaitInterval,
513                    sizeof(DWORD));
514 
515     RegCloseKey(hKey);
516 }
517 
518 
519 static
520 BOOL
521 GetProfileCount(LPDWORD lpProfileCount)
522 {
523     HKEY hKey;
524     LONG lError;
525 
526     *lpProfileCount = 0;
527 
528     lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
529                            L"System\\CurrentControlSet\\Control\\IDConfigDB\\Hardware Profiles",
530                            0,
531                            KEY_READ,
532                            &hKey);
533     if (lError != ERROR_SUCCESS)
534         return FALSE;
535 
536     lError = RegQueryInfoKeyW(hKey, NULL, NULL, NULL, lpProfileCount,
537                               NULL, NULL, NULL, NULL, NULL, NULL, NULL);
538 
539     RegCloseKey(hKey);
540 
541     if (lError != ERROR_SUCCESS)
542         return FALSE;
543 
544     return TRUE;
545 }
546 
547 
548 static
549 VOID
550 GetProfile(
551     HWND hwndDlg,
552     HKEY hKey,
553     LPWSTR lpName,
554     DWORD dwProfileNumber,
555     PPROFILE pProfile)
556 {
557     HKEY hProfileKey;
558     DWORD dwSize;
559     LONG lError;
560 
561     lError = RegOpenKeyExW(hKey,
562                            lpName,
563                            0,
564                            KEY_READ,
565                            &hProfileKey);
566     if (lError != ERROR_SUCCESS)
567         return;
568 
569     dwSize = PROFILE_NAME_LENGTH * sizeof(WCHAR);
570     lError = RegQueryValueExW(hProfileKey,
571                               L"FriendlyName",
572                               NULL,
573                               NULL,
574                               (LPBYTE)pProfile->szFriendlyName,
575                               &dwSize);
576     if (lError == ERROR_SUCCESS)
577     {
578         DPRINT1("Profile: %S\n", pProfile->szFriendlyName);
579     }
580 
581     dwSize = sizeof(DWORD);
582     lError = RegQueryValueExW(hProfileKey,
583                               L"PreferenceOrder",
584                               NULL,
585                               NULL,
586                               (LPBYTE)&pProfile->dwPreferenceOrder,
587                               &dwSize);
588     if (lError == ERROR_SUCCESS)
589     {
590         DPRINT1("PreferenceOrder: %lu\n", pProfile->dwPreferenceOrder);
591     }
592 
593     pProfile->dwProfileNumber = dwProfileNumber;
594 
595     SendDlgItemMessageW(hwndDlg, IDC_HRDPROFLSTBOX, LB_ADDSTRING, 0, (LPARAM)pProfile->szFriendlyName);
596 
597     RegCloseKey(hProfileKey);
598 }
599 
600 
601 static
602 BOOL
603 GetProfiles(HWND hwndDlg)
604 {
605     PPROFILEDATA pProfileData;
606     WCHAR szName[8];
607     DWORD dwNameLength;
608     DWORD dwProfileNumber;
609     DWORD dwIndex = 0;
610     HKEY hKey;
611     LONG lError;
612 
613     pProfileData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PROFILEDATA));
614     if (pProfileData == NULL)
615         return FALSE;
616 
617     pProfileData->dwLastProfile = (DWORD)-1;
618     pProfileData->dwSelectedProfileIndex = (DWORD)-1;
619 
620     if (!GetProfileCount(&pProfileData->dwProfileCount))
621     {
622         HeapFree(GetProcessHeap(), 0, pProfileData);
623         return FALSE;
624     }
625 
626     pProfileData->pProfiles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
627                                         pProfileData->dwProfileCount * sizeof(PROFILE));
628     if (pProfileData->pProfiles == NULL)
629     {
630         HeapFree(GetProcessHeap(), 0, pProfileData);
631         return FALSE;
632     }
633 
634     SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pProfileData);
635 
636     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
637                       L"System\\CurrentControlSet\\Control\\IDConfigDB\\Hardware Profiles",
638                       0,
639                       KEY_READ,
640                       &hKey) != ERROR_SUCCESS)
641         return FALSE;
642 
643     for (dwIndex = 0; dwIndex < pProfileData->dwProfileCount; dwIndex++)
644     {
645         dwNameLength = 8;
646         lError = RegEnumKeyExW(hKey,
647                                dwIndex,
648                                szName,
649                                &dwNameLength,
650                                NULL,
651                                NULL,
652                                NULL,
653                                NULL);
654         if (lError != ERROR_SUCCESS)
655             break;
656 
657         dwProfileNumber = wcstoul(szName, NULL, 10);
658         DPRINT("Profile name: %S\n", szName);
659         DPRINT("Profile number: %lu\n", dwProfileNumber);
660 
661         if ((pProfileData->dwLastProfile == (DWORD)-1) ||
662             (pProfileData->dwLastProfile < dwProfileNumber))
663             pProfileData->dwLastProfile = dwProfileNumber;
664 
665         DPRINT("Last Profile number: %lu\n", pProfileData->dwLastProfile);
666 
667         GetProfile(hwndDlg, hKey, szName, dwProfileNumber, &pProfileData->pProfiles[dwIndex]);
668     }
669 
670     RegCloseKey(hKey);
671 
672     return TRUE;
673 }
674 
675 
676 static
677 BOOL
678 OnInitHardProfDialog(HWND hwndDlg)
679 {
680     DWORD dwWaitInterval;
681 
682     DPRINT("OnInitHardProfDialog()\n");
683 
684     SendMessage(GetDlgItem(hwndDlg, IDC_HRDPROFUP),
685                 BM_SETIMAGE,(WPARAM)IMAGE_ICON,
686                 (LPARAM)(HANDLE)LoadIcon(hApplet, MAKEINTRESOURCE(IDI_UP)));
687     SendMessage(GetDlgItem(hwndDlg, IDC_HRDPROFDWN),
688                 BM_SETIMAGE,(WPARAM)IMAGE_ICON,
689                 (LPARAM)(HANDLE)LoadIcon(hApplet, MAKEINTRESOURCE(IDI_DOWN)));
690 
691     if (!GetProfiles(hwndDlg))
692         return FALSE;
693 
694     SendDlgItemMessageW(hwndDlg, IDC_HRDPROFUPDWN, UDM_SETRANGE, (WPARAM)0, (LPARAM)MAKELONG((SHORT)500, 0));
695 
696     dwWaitInterval = GetUserWaitInterval();
697     if (dwWaitInterval == (DWORD)-1)
698     {
699         CheckDlgButton(hwndDlg, IDC_HRDPROFWAIT, BST_CHECKED);
700         SendDlgItemMessageW(hwndDlg, IDC_HRDPROFUPDWN, UDM_SETPOS, 0, 30);
701         EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFEDIT), FALSE);
702     }
703     else
704     {
705         CheckDlgButton(hwndDlg, IDC_HRDPROFSELECT, BST_CHECKED);
706         SendDlgItemMessageW(hwndDlg, IDC_HRDPROFUPDWN, UDM_SETPOS, 0, dwWaitInterval);
707     }
708 
709     return TRUE;
710 }
711 
712 
713 static
714 VOID
715 OnOk(HWND hwndDlg)
716 {
717     DWORD dwWaitInterval;
718 
719     if (IsDlgButtonChecked(hwndDlg, IDC_HRDPROFWAIT) == BST_CHECKED)
720     {
721         dwWaitInterval = (DWORD)-1;
722     }
723     else
724     {
725         dwWaitInterval = LOWORD(SendDlgItemMessageW(hwndDlg, IDC_HRDPROFUPDWN, UDM_GETPOS, 0, 0));
726     }
727 
728     SetUserWaitInterval(dwWaitInterval);
729 }
730 
731 
732 /* Property page dialog callback */
733 INT_PTR
734 CALLBACK
735 HardProfDlgProc(HWND hwndDlg,
736                 UINT uMsg,
737                 WPARAM wParam,
738                 LPARAM lParam)
739 {
740     PPROFILEDATA pProfileData;
741 
742     UNREFERENCED_PARAMETER(lParam);
743     UNREFERENCED_PARAMETER(wParam);
744     UNREFERENCED_PARAMETER(hwndDlg);
745 
746     pProfileData = (PPROFILEDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
747 
748     switch (uMsg)
749     {
750         case WM_INITDIALOG:
751             return OnInitHardProfDialog(hwndDlg);
752 
753         case WM_DESTROY:
754             if (pProfileData != NULL)
755             {
756                 if (pProfileData->pProfiles != NULL)
757                     HeapFree(GetProcessHeap(), 0, pProfileData->pProfiles);
758                 HeapFree(GetProcessHeap(), 0, pProfileData);
759             }
760             break;
761 
762         case WM_COMMAND:
763             switch (LOWORD(wParam))
764             {
765                 case IDC_HRDPROFPROP:
766                     HardwareProfileProperties(hwndDlg, pProfileData);
767                     break;
768 
769                 case IDC_HRDPROFCOPY:
770                     CopyHardwareProfile(hwndDlg, pProfileData);
771                     break;
772 
773                 case IDC_HRDPROFRENAME:
774                     RenameHardwareProfile(hwndDlg, pProfileData);
775                     break;
776 
777                 case IDC_HRDPROFDEL:
778                     DeleteHardwareProfile(hwndDlg, pProfileData);
779                     break;
780 
781                 case IDC_HRDPROFUP:
782                     MoveHardwareProfile(hwndDlg, pProfileData, TRUE);
783                     break;
784 
785                 case IDC_HRDPROFDWN:
786                     MoveHardwareProfile(hwndDlg, pProfileData, FALSE);
787                     break;
788 
789                 case IDC_HRDPROFWAIT:
790                     EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFEDIT), FALSE);
791                     return TRUE;
792 
793                 case IDC_HRDPROFSELECT:
794                     EnableWindow(GetDlgItem(hwndDlg, IDC_HRDPROFEDIT), TRUE);
795                     return TRUE;
796 
797                 case IDC_HRDPROFLSTBOX:
798                     if (HIWORD(wParam) == LBN_SELCHANGE)
799                     {
800                         pProfileData->dwSelectedProfileIndex = (DWORD)SendDlgItemMessage(hwndDlg, IDC_HRDPROFLSTBOX, LB_GETCURSEL, 0, 0);
801                         UpdateButtons(hwndDlg, pProfileData);
802                     }
803                     return TRUE;
804 
805                 case IDOK:
806                     OnOk(hwndDlg);
807 
808                 case IDCANCEL:
809                     EndDialog(hwndDlg, LOWORD(wParam));
810                     return TRUE;
811             }
812             break;
813     }
814 
815     return FALSE;
816 }
817