xref: /reactos/dll/cpl/mmsys/sounds.c (revision 426598c6)
1 /*
2  * PROJECT:         ReactOS Multimedia Control Panel
3  * FILE:            dll/cpl/mmsys/sounds.c
4  * PURPOSE:         ReactOS Multimedia Control Panel
5  * PROGRAMMER:      Thomas Weidenmueller <w3seek@reactos.com>
6  *                  Johannes Anderwald <janderwald@reactos.com>
7  *                  Dmitry Chapyshev <dmitry@reactos.org>
8  *                  Victor Martinez Calvo <victor.martinez@reactos.org>
9  *                  Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
10  */
11 
12 #include "mmsys.h"
13 
14 #include <commdlg.h>
15 #include <windowsx.h>
16 
17 #include <debug.h>
18 
19 typedef struct _LABEL_MAP
20 {
21     PWCHAR szName;
22     PWCHAR szDesc;
23     PWCHAR szIcon;
24     struct _APP_MAP *AppMap;
25     struct _LABEL_MAP *Next;
26 } LABEL_MAP, *PLABEL_MAP;
27 
28 typedef struct _APP_MAP
29 {
30     WCHAR szName[MAX_PATH];
31     WCHAR szDesc[MAX_PATH];
32     WCHAR szIcon[MAX_PATH];
33 
34     struct _APP_MAP *Next;
35     PLABEL_MAP LabelMap;
36 } APP_MAP, *PAPP_MAP;
37 
38 typedef struct _LABEL_CONTEXT
39 {
40     PLABEL_MAP LabelMap;
41     PAPP_MAP AppMap;
42     WCHAR szValue[MAX_PATH];
43     struct _LABEL_CONTEXT *Next;
44 } LABEL_CONTEXT, *PLABEL_CONTEXT;
45 
46 typedef struct _SOUND_SCHEME_CONTEXT
47 {
48     WCHAR szName[MAX_PATH];
49     WCHAR szDesc[MAX_PATH];
50     PLABEL_CONTEXT LabelContext;
51 } SOUND_SCHEME_CONTEXT, *PSOUND_SCHEME_CONTEXT;
52 
53 typedef struct _GLOBAL_DATA
54 {
55     WCHAR szDefault[MAX_PATH];
56     HIMAGELIST hSoundsImageList;
57     PLABEL_MAP pLabelMap;
58     PAPP_MAP pAppMap;
59     UINT NumWavOut;
60 } GLOBAL_DATA, *PGLOBAL_DATA;
61 
62 
63 /* A filter string is a list separated by NULL and ends with double NULLs. */
64 LPWSTR MakeFilter(LPWSTR psz)
65 {
66     PWCHAR pch;
67 
68     ASSERT(psz[0] != UNICODE_NULL &&
69            psz[wcslen(psz) - 1] == L'|');
70     for (pch = psz; *pch != UNICODE_NULL; pch++)
71     {
72         /* replace vertical bar with NULL */
73         if (*pch == L'|')
74         {
75             *pch = UNICODE_NULL;
76         }
77     }
78     return psz;
79 }
80 
81 PLABEL_MAP FindLabel(PGLOBAL_DATA pGlobalData, PAPP_MAP pAppMap, PWCHAR szName)
82 {
83     PLABEL_MAP pMap = pGlobalData->pLabelMap;
84 
85     while (pMap)
86     {
87         ASSERT(pMap);
88         ASSERT(pMap->szName);
89         if (!wcscmp(pMap->szName, szName))
90             return pMap;
91 
92         pMap = pMap->Next;
93     }
94 
95     pMap = pAppMap->LabelMap;
96 
97     while (pMap)
98     {
99         ASSERT(pMap);
100         ASSERT(pMap->szName);
101         if (!wcscmp(pMap->szName, szName))
102             return pMap;
103 
104         pMap = pMap->Next;
105     }
106 
107     pMap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LABEL_MAP));
108     if (!pMap)
109         return NULL;
110 
111     pMap->szName = pMap->szDesc = _wcsdup(szName);
112     if (!pMap->szName)
113     {
114         HeapFree(GetProcessHeap(), 0, pMap);
115         return NULL;
116     }
117 
118     pMap->AppMap = pAppMap;
119     pMap->Next = pGlobalData->pLabelMap;
120     pGlobalData->pLabelMap = pMap;
121 
122     return pMap;
123 }
124 
125 
126 VOID RemoveLabel(PGLOBAL_DATA pGlobalData, PLABEL_MAP pMap)
127 {
128     PLABEL_MAP pCurMap = pGlobalData->pLabelMap;
129 
130     if (pCurMap == pMap)
131     {
132         pGlobalData->pLabelMap = pGlobalData->pLabelMap->Next;
133         return;
134     }
135 
136     while (pCurMap)
137     {
138         if (pCurMap->Next == pMap)
139         {
140             pCurMap->Next = pCurMap->Next->Next;
141             return;
142         }
143         pCurMap = pCurMap->Next;
144     }
145 }
146 
147 static
148 VOID
149 FreeLabelMap(PGLOBAL_DATA pGlobalData)
150 {
151     PLABEL_MAP pCurMap;
152 
153     while (pGlobalData->pLabelMap)
154     {
155         pCurMap = pGlobalData->pLabelMap->Next;
156 
157         /* Prevent double freeing (for "FindLabel") */
158         if (pGlobalData->pLabelMap->szName != pGlobalData->pLabelMap->szDesc)
159         {
160             free(pGlobalData->pLabelMap->szName);
161         }
162 
163         free(pGlobalData->pLabelMap->szDesc);
164         free(pGlobalData->pLabelMap->szIcon);
165 
166         HeapFree(GetProcessHeap(), 0, pGlobalData->pLabelMap);
167         pGlobalData->pLabelMap = pCurMap;
168     }
169 }
170 
171 PAPP_MAP FindApp(PGLOBAL_DATA pGlobalData, PWCHAR szName)
172 {
173     PAPP_MAP pMap = pGlobalData->pAppMap;
174 
175     while (pMap)
176     {
177         if (!wcscmp(pMap->szName, szName))
178             return pMap;
179 
180         pMap = pMap->Next;
181 
182     }
183     return NULL;
184 }
185 
186 static
187 VOID
188 FreeAppMap(PGLOBAL_DATA pGlobalData)
189 {
190     PAPP_MAP pCurMap;
191 
192     while (pGlobalData->pAppMap)
193     {
194         pCurMap = pGlobalData->pAppMap->Next;
195         HeapFree(GetProcessHeap(), 0, pGlobalData->pAppMap);
196         pGlobalData->pAppMap = pCurMap;
197     }
198 }
199 
200 PLABEL_CONTEXT FindLabelContext(PGLOBAL_DATA pGlobalData, PSOUND_SCHEME_CONTEXT pSoundScheme, PWCHAR AppName, PWCHAR LabelName)
201 {
202     PLABEL_CONTEXT pLabelContext;
203 
204     pLabelContext = pSoundScheme->LabelContext;
205 
206     while (pLabelContext)
207     {
208         ASSERT(pLabelContext->AppMap);
209         ASSERT(pLabelContext->LabelMap);
210 
211         if (!_wcsicmp(pLabelContext->AppMap->szName, AppName) && !_wcsicmp(pLabelContext->LabelMap->szName, LabelName))
212         {
213             return pLabelContext;
214         }
215         pLabelContext = pLabelContext->Next;
216     }
217 
218     pLabelContext = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LABEL_CONTEXT));
219     if (!pLabelContext)
220         return NULL;
221 
222     pLabelContext->AppMap = FindApp(pGlobalData, AppName);
223     pLabelContext->LabelMap = FindLabel(pGlobalData, pLabelContext->AppMap, LabelName);
224     ASSERT(pLabelContext->AppMap);
225     ASSERT(pLabelContext->LabelMap);
226     pLabelContext->szValue[0] = UNICODE_NULL;
227     pLabelContext->Next = pSoundScheme->LabelContext;
228     pSoundScheme->LabelContext = pLabelContext;
229 
230     return pLabelContext;
231 }
232 
233 
234 BOOL
235 LoadEventLabel(PGLOBAL_DATA pGlobalData, HKEY hKey, PWCHAR szSubKey)
236 {
237     HKEY hSubKey;
238     DWORD cbValue;
239     WCHAR szDesc[MAX_PATH];
240     WCHAR szData[MAX_PATH];
241     PLABEL_MAP pMap;
242 
243     if (RegOpenKeyExW(hKey,
244                       szSubKey,
245                       0,
246                       KEY_READ,
247                       &hSubKey) != ERROR_SUCCESS)
248     {
249         return FALSE;
250     }
251 
252     cbValue = sizeof(szDesc);
253     if (RegQueryValueExW(hSubKey,
254                          NULL,
255                          NULL,
256                          NULL,
257                          (LPBYTE)szDesc,
258                          &cbValue) != ERROR_SUCCESS)
259     {
260         RegCloseKey(hSubKey);
261         return FALSE;
262     }
263 
264     cbValue = sizeof(szData);
265     if (RegQueryValueExW(hSubKey,
266                          L"DispFileName",
267                          NULL,
268                          NULL,
269                          (LPBYTE)szData,
270                          &cbValue) != ERROR_SUCCESS)
271     {
272         RegCloseKey(hSubKey);
273         return FALSE;
274     }
275 
276     pMap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LABEL_MAP));
277     if (!pMap)
278     {
279         return FALSE;
280     }
281 
282     pMap->szName = _wcsdup(szSubKey);
283     pMap->szDesc = _wcsdup(szDesc);
284     pMap->szIcon = _wcsdup(szData);
285 
286     if (pGlobalData->pLabelMap)
287     {
288         pMap->Next = pGlobalData->pLabelMap;
289         pGlobalData->pLabelMap = pMap;
290     }
291     else
292     {
293         pGlobalData->pLabelMap = pMap;
294         pGlobalData->pLabelMap->Next = NULL;
295     }
296     return TRUE;
297 }
298 
299 
300 BOOL
301 LoadEventLabels(PGLOBAL_DATA pGlobalData)
302 {
303     HKEY hSubKey;
304     DWORD dwCurKey;
305     WCHAR szName[MAX_PATH];
306     DWORD dwName;
307     DWORD dwResult;
308     DWORD dwCount;
309     if (RegOpenKeyExW(HKEY_CURRENT_USER,
310                       L"AppEvents\\EventLabels",
311                       0,
312                       KEY_READ,
313                       &hSubKey) != ERROR_SUCCESS)
314     {
315         return FALSE;
316     }
317 
318     dwCurKey = 0;
319     dwCount = 0;
320     do
321     {
322         dwName = _countof(szName);
323         dwResult = RegEnumKeyExW(hSubKey,
324                                  dwCurKey,
325                                  szName,
326                                  &dwName,
327                                  NULL,
328                                  NULL,
329                                  NULL,
330                                  NULL);
331 
332         if (dwResult == ERROR_SUCCESS)
333         {
334             if (LoadEventLabel(pGlobalData, hSubKey, szName))
335             {
336                 dwCount++;
337             }
338         }
339         dwCurKey++;
340 
341     } while (dwResult == ERROR_SUCCESS);
342 
343     RegCloseKey(hSubKey);
344     return (dwCount != 0);
345 }
346 
347 
348 BOOL
349 AddSoundProfile(HWND hwndDlg, HKEY hKey, PWCHAR szSubKey, BOOL SetDefault)
350 {
351     HKEY hSubKey;
352     WCHAR szValue[MAX_PATH];
353     DWORD cbValue, dwResult;
354     LRESULT lResult;
355     PSOUND_SCHEME_CONTEXT pScheme;
356 
357     if (RegOpenKeyExW(hKey,
358                       szSubKey,
359                       0,
360                       KEY_READ,
361                       &hSubKey) != ERROR_SUCCESS)
362     {
363         return FALSE;
364     }
365 
366     cbValue = sizeof(szValue);
367     dwResult = RegQueryValueExW(hSubKey,
368                                 NULL,
369                                 NULL,
370                                 NULL,
371                                 (LPBYTE)szValue,
372                                 &cbValue);
373     RegCloseKey(hSubKey);
374 
375     if (dwResult != ERROR_SUCCESS)
376         return FALSE;
377 
378     /* Try to add the new profile */
379     lResult = ComboBox_AddString(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), szValue);
380     if (lResult == CB_ERR)
381         return FALSE;
382 
383     /* Allocate the profile scheme buffer */
384     pScheme = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOUND_SCHEME_CONTEXT));
385     if (pScheme == NULL)
386     {
387         /* We failed to allocate the buffer, no need to keep a dangling string in the combobox */
388         ComboBox_DeleteString(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lResult);
389         return FALSE;
390     }
391 
392     StringCchCopyW(pScheme->szDesc, _countof(pScheme->szDesc), szValue);
393     StringCchCopyW(pScheme->szName, _countof(pScheme->szName), szSubKey);
394 
395     /* Associate the value with the item in the combobox */
396     ComboBox_SetItemData(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lResult, pScheme);
397 
398     /* Optionally, select the profile */
399     if (SetDefault)
400     {
401         ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lResult);
402     }
403 
404     return TRUE;
405 }
406 
407 
408 DWORD
409 EnumerateSoundProfiles(PGLOBAL_DATA pGlobalData, HWND hwndDlg, HKEY hKey)
410 {
411     HKEY hSubKey;
412     DWORD dwName, dwCurKey, dwResult, dwNumSchemes;
413     DWORD cbDefault;
414     WCHAR szName[MAX_PATH];
415 
416     cbDefault = sizeof(pGlobalData->szDefault);
417     if (RegQueryValueExW(hKey,
418                          NULL,
419                          NULL,
420                          NULL,
421                          (LPBYTE)pGlobalData->szDefault,
422                          &cbDefault) != ERROR_SUCCESS)
423     {
424         return FALSE;
425     }
426 
427     if (RegOpenKeyExW(hKey,
428                       L"Names",
429                       0,
430                       KEY_READ,
431                       &hSubKey) != ERROR_SUCCESS)
432     {
433         return FALSE;
434     }
435 
436     dwNumSchemes = 0;
437     dwCurKey = 0;
438     do
439     {
440         dwName = _countof(szName);
441         dwResult = RegEnumKeyExW(hSubKey,
442                                  dwCurKey,
443                                  szName,
444                                  &dwName,
445                                  NULL,
446                                  NULL,
447                                  NULL,
448                                  NULL);
449 
450         if (dwResult == ERROR_SUCCESS)
451         {
452             if (AddSoundProfile(hwndDlg, hSubKey, szName, (!_wcsicmp(szName, pGlobalData->szDefault))))
453             {
454                 dwNumSchemes++;
455             }
456         }
457 
458         dwCurKey++;
459     } while (dwResult == ERROR_SUCCESS);
460 
461     RegCloseKey(hSubKey);
462     return dwNumSchemes;
463 }
464 
465 
466 PSOUND_SCHEME_CONTEXT FindSoundProfile(HWND hwndDlg, PWCHAR szName)
467 {
468     LRESULT lCount, lIndex, lResult;
469     PSOUND_SCHEME_CONTEXT pScheme;
470     HWND hwndComboBox;
471 
472     hwndComboBox = GetDlgItem(hwndDlg, IDC_SOUND_SCHEME);
473     lCount = ComboBox_GetCount(hwndComboBox);
474     if (lCount == CB_ERR)
475     {
476         return NULL;
477     }
478 
479     for (lIndex = 0; lIndex < lCount; lIndex++)
480     {
481         lResult = ComboBox_GetItemData(hwndComboBox, lIndex);
482         if (lResult == CB_ERR)
483         {
484             continue;
485         }
486 
487         pScheme = (PSOUND_SCHEME_CONTEXT)lResult;
488         if (!_wcsicmp(pScheme->szName, szName))
489         {
490             return pScheme;
491         }
492     }
493     return NULL;
494 }
495 
496 static
497 VOID
498 FreeSoundProfiles(HWND hwndDlg)
499 {
500     LRESULT lCount, lIndex, lResult;
501     PSOUND_SCHEME_CONTEXT pScheme;
502     PLABEL_CONTEXT pLabelContext;
503     HWND hwndComboBox;
504 
505     hwndComboBox = GetDlgItem(hwndDlg, IDC_SOUND_SCHEME);
506     lCount = ComboBox_GetCount(hwndComboBox);
507     if (lCount == CB_ERR)
508         return;
509 
510     for (lIndex = 0; lIndex < lCount; lIndex++)
511     {
512         lResult = ComboBox_GetItemData(hwndComboBox, lIndex);
513         if (lResult == CB_ERR)
514         {
515             continue;
516         }
517 
518         pScheme = (PSOUND_SCHEME_CONTEXT)lResult;
519 
520         while (pScheme->LabelContext)
521         {
522             pLabelContext = pScheme->LabelContext->Next;
523             HeapFree(GetProcessHeap(), 0, pScheme->LabelContext);
524             pScheme->LabelContext = pLabelContext;
525         }
526 
527         HeapFree(GetProcessHeap(), 0, pScheme);
528     }
529 }
530 
531 BOOL
532 ImportSoundLabel(PGLOBAL_DATA pGlobalData, HWND hwndDlg, HKEY hKey, PWCHAR szProfile, PWCHAR szLabelName, PWCHAR szAppName, PAPP_MAP AppMap, PLABEL_MAP LabelMap)
533 {
534     HKEY hSubKey;
535     WCHAR szValue[MAX_PATH];
536     WCHAR szBuffer[MAX_PATH];
537     DWORD cbValue, cchLength;
538     PSOUND_SCHEME_CONTEXT pScheme;
539     PLABEL_CONTEXT pLabelContext;
540     BOOL bCurrentProfile, bActiveProfile;
541 
542     bCurrentProfile = !_wcsicmp(szProfile, L".Current");
543     bActiveProfile = !_wcsicmp(szProfile, pGlobalData->szDefault);
544 
545     if (RegOpenKeyExW(hKey,
546                       szProfile,
547                       0,
548                       KEY_READ,
549                       &hSubKey) != ERROR_SUCCESS)
550     {
551         return FALSE;
552     }
553 
554     cbValue = sizeof(szValue);
555     if (RegQueryValueExW(hSubKey,
556                          NULL,
557                          NULL,
558                          NULL,
559                          (LPBYTE)szValue,
560                          &cbValue) != ERROR_SUCCESS)
561     {
562         return FALSE;
563     }
564 
565     if (bCurrentProfile)
566         pScheme = FindSoundProfile(hwndDlg, pGlobalData->szDefault);
567     else
568         pScheme = FindSoundProfile(hwndDlg, szProfile);
569 
570     if (!pScheme)
571     {
572         return FALSE;
573     }
574     pLabelContext = FindLabelContext(pGlobalData, pScheme, AppMap->szName, LabelMap->szName);
575 
576     cchLength = ExpandEnvironmentStringsW(szValue, szBuffer, _countof(szBuffer));
577     if (cchLength == 0 || cchLength > _countof(szBuffer))
578     {
579         /* fixme */
580         return FALSE;
581     }
582 
583     if (bCurrentProfile)
584         StringCchCopyW(pLabelContext->szValue, _countof(pLabelContext->szValue), szBuffer);
585     else if (!bActiveProfile)
586         StringCchCopyW(pLabelContext->szValue, _countof(pLabelContext->szValue), szBuffer);
587 
588     return TRUE;
589 }
590 
591 
592 DWORD
593 ImportSoundEntry(PGLOBAL_DATA pGlobalData, HWND hwndDlg, HKEY hKey, PWCHAR szLabelName, PWCHAR szAppName, PAPP_MAP pAppMap)
594 {
595     HKEY hSubKey;
596     DWORD dwNumProfiles;
597     DWORD dwCurKey;
598     DWORD dwResult;
599     DWORD dwProfile;
600     WCHAR szProfile[MAX_PATH];
601     PLABEL_MAP pLabel;
602 
603     if (RegOpenKeyExW(hKey,
604                       szLabelName,
605                       0,
606                       KEY_READ,
607                       &hSubKey) != ERROR_SUCCESS)
608     {
609         return FALSE;
610     }
611     pLabel = FindLabel(pGlobalData, pAppMap, szLabelName);
612 
613     ASSERT(pLabel);
614     RemoveLabel(pGlobalData, pLabel);
615 
616     pLabel->AppMap = pAppMap;
617     pLabel->Next = pAppMap->LabelMap;
618     pAppMap->LabelMap = pLabel;
619 
620     dwNumProfiles = 0;
621     dwCurKey = 0;
622     do
623     {
624         dwProfile = _countof(szProfile);
625         dwResult = RegEnumKeyExW(hSubKey,
626                                  dwCurKey,
627                                  szProfile,
628                                  &dwProfile,
629                                  NULL,
630                                  NULL,
631                                  NULL,
632                                  NULL);
633 
634         if (dwResult == ERROR_SUCCESS)
635         {
636             if (ImportSoundLabel(pGlobalData, hwndDlg, hSubKey, szProfile, szLabelName, szAppName, pAppMap, pLabel))
637             {
638                 dwNumProfiles++;
639             }
640         }
641 
642         dwCurKey++;
643     } while (dwResult == ERROR_SUCCESS);
644 
645     RegCloseKey(hSubKey);
646 
647     return dwNumProfiles;
648 }
649 
650 
651 DWORD
652 ImportAppProfile(PGLOBAL_DATA pGlobalData, HWND hwndDlg, HKEY hKey, PWCHAR szAppName)
653 {
654     HKEY hSubKey;
655     WCHAR szDefault[MAX_PATH];
656     DWORD cbValue;
657     DWORD dwCurKey;
658     DWORD dwResult;
659     DWORD dwNumEntry;
660     DWORD dwName;
661     WCHAR szName[MAX_PATH];
662     WCHAR szIcon[MAX_PATH];
663     PAPP_MAP AppMap;
664 
665     AppMap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APP_MAP));
666     if (!AppMap)
667         return 0;
668 
669     if (RegOpenKeyExW(hKey,
670                       szAppName,
671                       0,
672                       KEY_READ,
673                       &hSubKey) != ERROR_SUCCESS)
674     {
675         HeapFree(GetProcessHeap(), 0, AppMap);
676         return 0;
677     }
678 
679     cbValue = sizeof(szDefault);
680     if (RegQueryValueExW(hSubKey,
681                          NULL,
682                          NULL,
683                          NULL,
684                          (LPBYTE)szDefault,
685                          &cbValue) != ERROR_SUCCESS)
686     {
687         RegCloseKey(hSubKey);
688         HeapFree(GetProcessHeap(), 0, AppMap);
689         return 0;
690     }
691 
692     cbValue = sizeof(szIcon);
693     if (RegQueryValueExW(hSubKey,
694                          L"DispFileName",
695                          NULL,
696                          NULL,
697                          (LPBYTE)szIcon,
698                          &cbValue) != ERROR_SUCCESS)
699     {
700         szIcon[0] = UNICODE_NULL;
701     }
702 
703     /* initialize app map */
704     StringCchCopyW(AppMap->szName, _countof(AppMap->szName), szAppName);
705     StringCchCopyW(AppMap->szDesc, _countof(AppMap->szDesc), szDefault);
706     StringCchCopyW(AppMap->szIcon, _countof(AppMap->szIcon), szIcon);
707 
708     AppMap->Next = pGlobalData->pAppMap;
709     pGlobalData->pAppMap = AppMap;
710 
711 
712     dwCurKey = 0;
713     dwNumEntry = 0;
714     do
715     {
716         dwName = _countof(szName);
717         dwResult = RegEnumKeyExW(hSubKey,
718                                  dwCurKey,
719                                  szName,
720                                  &dwName,
721                                  NULL,
722                                  NULL,
723                                  NULL,
724                                  NULL);
725         if (dwResult == ERROR_SUCCESS)
726         {
727             if (ImportSoundEntry(pGlobalData, hwndDlg, hSubKey, szName, szAppName, AppMap))
728             {
729                 dwNumEntry++;
730             }
731         }
732         dwCurKey++;
733     } while (dwResult == ERROR_SUCCESS);
734 
735     RegCloseKey(hSubKey);
736     return dwNumEntry;
737 }
738 
739 
740 BOOL
741 ImportSoundProfiles(PGLOBAL_DATA pGlobalData, HWND hwndDlg, HKEY hKey)
742 {
743     DWORD dwCurKey;
744     DWORD dwResult;
745     DWORD dwNumApps;
746     WCHAR szName[MAX_PATH];
747     HKEY hSubKey;
748 
749     if (RegOpenKeyExW(hKey,
750                       L"Apps",
751                       0,
752                       KEY_READ,
753                       &hSubKey) != ERROR_SUCCESS)
754     {
755         return FALSE;
756     }
757 
758     dwNumApps = 0;
759     dwCurKey = 0;
760     do
761     {
762         dwResult = RegEnumKeyW(hSubKey,
763                                dwCurKey,
764                                szName,
765                                _countof(szName));
766 
767         if (dwResult == ERROR_SUCCESS)
768         {
769             if (ImportAppProfile(pGlobalData, hwndDlg, hSubKey, szName))
770             {
771                 dwNumApps++;
772             }
773         }
774         dwCurKey++;
775     } while (dwResult == ERROR_SUCCESS);
776 
777     RegCloseKey(hSubKey);
778 
779     return (dwNumApps != 0);
780 }
781 
782 
783 BOOL
784 LoadSoundProfiles(PGLOBAL_DATA pGlobalData, HWND hwndDlg)
785 {
786     HKEY hSubKey;
787     DWORD dwNumSchemes;
788 
789     if (RegOpenKeyExW(HKEY_CURRENT_USER,
790                       L"AppEvents\\Schemes",
791                       0,
792                       KEY_READ,
793                       &hSubKey) != ERROR_SUCCESS)
794     {
795         return FALSE;
796     }
797 
798     dwNumSchemes = EnumerateSoundProfiles(pGlobalData, hwndDlg, hSubKey);
799 
800 
801     if (dwNumSchemes)
802     {
803         ImportSoundProfiles(pGlobalData, hwndDlg, hSubKey);
804     }
805 
806     RegCloseKey(hSubKey);
807     return FALSE;
808 }
809 
810 
811 BOOL
812 LoadSoundFiles(HWND hwndDlg)
813 {
814     WCHAR szList[256];
815     WCHAR szPath[MAX_PATH];
816     PWCHAR ptr;
817     WIN32_FIND_DATAW FileData;
818     HANDLE hFile;
819     LRESULT lResult;
820     UINT length;
821 
822     /* Add no sound listview item */
823     if (LoadStringW(hApplet, IDS_NO_SOUND, szList, _countof(szList)))
824     {
825         szList[_countof(szList) - 1] = UNICODE_NULL;
826         ComboBox_AddString(GetDlgItem(hwndDlg, IDC_SOUND_LIST), szList);
827     }
828 
829     /* Load sound files */
830     length = GetWindowsDirectoryW(szPath, _countof(szPath));
831     if (length == 0 || length >= _countof(szPath) - CONST_STR_LEN(L"\\media\\*"))
832     {
833         return FALSE;
834     }
835 
836     //PathCchAppend(szPath, _countof(szPath), L"media\\*");
837     StringCchCatW(szPath, _countof(szPath), L"\\media\\*");
838 
839     hFile = FindFirstFileW(szPath, &FileData);
840     if (hFile == INVALID_HANDLE_VALUE)
841     {
842         return FALSE;
843     }
844 
845     do
846     {
847         if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
848             continue;
849 
850         ptr = wcsrchr(FileData.cFileName, L'\\');
851         if (ptr)
852         {
853             ptr++;
854         }
855         else
856         {
857             ptr = FileData.cFileName;
858         }
859         lResult = SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_ADDSTRING, 0, (LPARAM)ptr);
860         if (lResult != CB_ERR)
861         {
862             StringCchCopyW(szPath + (length + CONST_STR_LEN(L"\\media\\")),
863                            _countof(szPath) - (length + CONST_STR_LEN(L"\\media\\")),
864                            FileData.cFileName);
865             SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)_wcsdup(szPath));
866         }
867     } while (FindNextFileW(hFile, &FileData) != 0);
868 
869     FindClose(hFile);
870     return TRUE;
871 }
872 
873 static
874 VOID
875 FreeSoundFiles(HWND hwndDlg)
876 {
877     LRESULT lCount, lIndex, lResult;
878     PWCHAR pSoundPath;
879     HWND hwndComboBox;
880 
881     hwndComboBox = GetDlgItem(hwndDlg, IDC_SOUND_LIST);
882     lCount = ComboBox_GetCount(hwndComboBox);
883     if (lCount == CB_ERR)
884         return;
885 
886     for (lIndex = 0; lIndex < lCount; lIndex++)
887     {
888         lResult = ComboBox_GetItemData(hwndComboBox, lIndex);
889         if (lResult == CB_ERR)
890         {
891             continue;
892         }
893 
894         pSoundPath = (PWCHAR)lResult;
895         free(pSoundPath);
896     }
897 }
898 
899 BOOL
900 ShowSoundScheme(PGLOBAL_DATA pGlobalData, HWND hwndDlg)
901 {
902     LRESULT lIndex;
903     PSOUND_SCHEME_CONTEXT pScheme;
904     PAPP_MAP pAppMap;
905     PLABEL_MAP pLabelMap;
906     PLABEL_CONTEXT pLabelContext;
907     HWND hDlgCtrl, hList;
908     TVINSERTSTRUCTW tvItem;
909     HTREEITEM hTreeItem;
910 
911     hDlgCtrl = GetDlgItem(hwndDlg, IDC_SOUND_SCHEME);
912     hList = GetDlgItem(hwndDlg, IDC_SCHEME_LIST);
913 
914     if (pGlobalData->hSoundsImageList != NULL)
915     {
916         TreeView_SetImageList(hList, pGlobalData->hSoundsImageList, TVSIL_NORMAL);
917     }
918 
919     lIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
920     if (lIndex == CB_ERR)
921     {
922         return FALSE;
923     }
924 
925     lIndex = SendMessageW(hDlgCtrl, CB_GETITEMDATA, (WPARAM)lIndex, 0);
926     if (lIndex == CB_ERR)
927     {
928         return FALSE;
929     }
930     pScheme = (PSOUND_SCHEME_CONTEXT)lIndex;
931 
932     StringCchCopyW(pGlobalData->szDefault, _countof(pGlobalData->szDefault), pScheme->szName);
933 
934     pAppMap = pGlobalData->pAppMap;
935     while (pAppMap)
936     {
937         ZeroMemory(&tvItem, sizeof(tvItem));
938         tvItem.hParent = TVI_ROOT;
939         tvItem.hInsertAfter = TVI_FIRST;
940 
941         tvItem.item.mask = TVIF_STATE | TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
942         tvItem.item.state = TVIS_EXPANDED;
943         tvItem.item.stateMask = TVIS_EXPANDED;
944         tvItem.item.pszText = pAppMap->szDesc;
945         tvItem.item.iImage = IMAGE_SOUND_SECTION;
946         tvItem.item.iSelectedImage = IMAGE_SOUND_SECTION;
947         tvItem.item.lParam = (LPARAM)NULL;
948 
949         hTreeItem = TreeView_InsertItem(hList, &tvItem);
950 
951         pLabelMap = pAppMap->LabelMap;
952         while (pLabelMap)
953         {
954             pLabelContext = FindLabelContext(pGlobalData, pScheme, pAppMap->szName, pLabelMap->szName);
955 
956             ZeroMemory(&tvItem, sizeof(tvItem));
957             tvItem.hParent = hTreeItem;
958             tvItem.hInsertAfter = TVI_SORT;
959 
960             tvItem.item.mask = TVIF_STATE | TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
961             tvItem.item.state = TVIS_EXPANDED;
962             tvItem.item.stateMask = TVIS_EXPANDED;
963             tvItem.item.pszText = pLabelMap->szDesc;
964             if (pLabelContext->szValue && wcslen(pLabelContext->szValue) > 0)
965             {
966                 tvItem.item.iImage = IMAGE_SOUND_ASSIGNED;
967                 tvItem.item.iSelectedImage = IMAGE_SOUND_ASSIGNED;
968             }
969             else
970             {
971                 tvItem.item.iImage = IMAGE_SOUND_NONE;
972                 tvItem.item.iSelectedImage = IMAGE_SOUND_NONE;
973             }
974             tvItem.item.lParam = (LPARAM)FindLabelContext(pGlobalData, pScheme, pAppMap->szName, pLabelMap->szName);
975 
976             TreeView_InsertItem(hList, &tvItem);
977 
978             pLabelMap = pLabelMap->Next;
979         }
980         pAppMap = pAppMap->Next;
981     }
982     return TRUE;
983 }
984 
985 
986 BOOL
987 ApplyChanges(HWND hwndDlg)
988 {
989     HKEY hKey, hSubKey;
990     DWORD dwType;
991     LRESULT lIndex;
992     PSOUND_SCHEME_CONTEXT pScheme;
993     HWND hDlgCtrl;
994     PLABEL_CONTEXT pLabelContext;
995     WCHAR Buffer[100];
996 
997     hDlgCtrl = GetDlgItem(hwndDlg, IDC_SOUND_SCHEME);
998 
999     lIndex = SendMessageW(hDlgCtrl, CB_GETCURSEL, 0, 0);
1000     if (lIndex == CB_ERR)
1001     {
1002         return FALSE;
1003     }
1004 
1005     lIndex = SendMessageW(hDlgCtrl, CB_GETITEMDATA, (WPARAM)lIndex, 0);
1006     if (lIndex == CB_ERR)
1007     {
1008         return FALSE;
1009     }
1010     pScheme = (PSOUND_SCHEME_CONTEXT)lIndex;
1011 
1012     if (RegOpenKeyExW(HKEY_CURRENT_USER,
1013                       L"AppEvents\\Schemes",
1014                       0,
1015                       KEY_WRITE,
1016                       &hKey) != ERROR_SUCCESS)
1017     {
1018         return FALSE;
1019     }
1020 
1021     RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE)pScheme->szName, (wcslen(pScheme->szName) + 1) * sizeof(WCHAR));
1022     RegCloseKey(hKey);
1023 
1024     if (RegOpenKeyExW(HKEY_CURRENT_USER,
1025                       L"AppEvents\\Schemes\\Apps",
1026                       0,
1027                       KEY_WRITE,
1028                       &hKey) != ERROR_SUCCESS)
1029     {
1030         return FALSE;
1031     }
1032 
1033     pLabelContext = pScheme->LabelContext;
1034 
1035     while (pLabelContext)
1036     {
1037         StringCchPrintfW(Buffer, _countof(Buffer), L"%s\\%s\\.Current", pLabelContext->AppMap->szName, pLabelContext->LabelMap->szName);
1038 
1039         if (RegOpenKeyExW(hKey, Buffer, 0, KEY_WRITE, &hSubKey) == ERROR_SUCCESS)
1040         {
1041             dwType = (wcschr(pLabelContext->szValue, L'%') ? REG_EXPAND_SZ : REG_SZ);
1042             RegSetValueExW(hSubKey, NULL, 0, dwType, (LPBYTE)pLabelContext->szValue, (wcslen(pLabelContext->szValue) + 1) * sizeof(WCHAR));
1043             RegCloseKey(hSubKey);
1044         }
1045 
1046         pLabelContext = pLabelContext->Next;
1047     }
1048     RegCloseKey(hKey);
1049 
1050     SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)PSNRET_NOERROR);
1051     return TRUE;
1052 }
1053 
1054 
1055 HIMAGELIST
1056 InitImageList(UINT StartResource,
1057               UINT EndResource,
1058               UINT Width,
1059               UINT Height,
1060               ULONG type)
1061 {
1062     HANDLE hImage;
1063     HIMAGELIST himl;
1064     UINT i;
1065     INT ret;
1066 
1067     /* Create the toolbar icon image list */
1068     himl = ImageList_Create(Width,
1069                             Height,
1070                             ILC_MASK | ILC_COLOR32,
1071                             EndResource - StartResource,
1072                             0);
1073     if (himl == NULL)
1074         return NULL;
1075 
1076     ret = 0;
1077     for (i = StartResource; i <= EndResource && ret != -1; i++)
1078     {
1079         hImage = LoadImageW(hApplet,
1080                             MAKEINTRESOURCEW(i),
1081                             type,
1082                             Width,
1083                             Height,
1084                             LR_LOADTRANSPARENT);
1085         if (hImage == NULL)
1086         {
1087             ret = -1;
1088             break;
1089         }
1090 
1091         if (type == IMAGE_BITMAP)
1092         {
1093             ret = ImageList_AddMasked(himl,
1094                                       hImage,
1095                                       RGB(255, 0, 128));
1096         }
1097         else if (type == IMAGE_ICON)
1098         {
1099             ret = ImageList_AddIcon(himl,
1100                                     hImage);
1101         }
1102 
1103         DeleteObject(hImage);
1104     }
1105 
1106     if (ret == -1)
1107     {
1108         ImageList_Destroy(himl);
1109         himl = NULL;
1110     }
1111 
1112     return himl;
1113 }
1114 
1115 
1116 /* Sounds property page dialog callback */
1117 INT_PTR
1118 CALLBACK
1119 SoundsDlgProc(HWND hwndDlg,
1120               UINT uMsg,
1121               WPARAM wParam,
1122               LPARAM lParam)
1123 {
1124     PGLOBAL_DATA pGlobalData;
1125 
1126     OPENFILENAMEW ofn;
1127     WCHAR filename[MAX_PATH];
1128     WCHAR szFilter[256], szTitle[256];
1129     LPWSTR pFileName;
1130     LRESULT lResult;
1131 
1132     pGlobalData = (PGLOBAL_DATA)GetWindowLongPtrW(hwndDlg, DWLP_USER);
1133 
1134     switch (uMsg)
1135     {
1136         case WM_INITDIALOG:
1137         {
1138             pGlobalData = (PGLOBAL_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLOBAL_DATA));
1139             SetWindowLongPtrW(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
1140 
1141             pGlobalData->NumWavOut = waveOutGetNumDevs();
1142 
1143             SendMessageW(GetDlgItem(hwndDlg, IDC_PLAY_SOUND),
1144                          BM_SETIMAGE, (WPARAM)IMAGE_ICON,
1145                          (LPARAM)(HANDLE)LoadIconW(hApplet, MAKEINTRESOURCEW(IDI_PLAY_ICON)));
1146 
1147             pGlobalData->hSoundsImageList = InitImageList(IDI_SOUND_SECTION,
1148                                                           IDI_SOUND_ASSIGNED,
1149                                                           GetSystemMetrics(SM_CXSMICON),
1150                                                           GetSystemMetrics(SM_CXSMICON),
1151                                                           IMAGE_ICON);
1152 
1153             LoadEventLabels(pGlobalData);
1154             LoadSoundProfiles(pGlobalData, hwndDlg);
1155             LoadSoundFiles(hwndDlg);
1156             ShowSoundScheme(pGlobalData, hwndDlg);
1157 
1158             if (wParam == (WPARAM)GetDlgItem(hwndDlg, IDC_SOUND_SCHEME))
1159                 return TRUE;
1160             SetFocus(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME));
1161             return FALSE;
1162         }
1163         case WM_COMMAND:
1164         {
1165             switch (LOWORD(wParam))
1166             {
1167                 case IDC_BROWSE_SOUND:
1168                 {
1169                     ZeroMemory(&ofn, sizeof(ofn));
1170                     ofn.lStructSize = sizeof(ofn);
1171                     ofn.hwndOwner = hwndDlg;
1172                     ofn.lpstrFile = filename;
1173                     ofn.lpstrFile[0] = UNICODE_NULL;
1174                     ofn.nMaxFile = _countof(filename);
1175                     LoadStringW(hApplet, IDS_WAVE_FILES_FILTER, szFilter, _countof(szFilter));
1176                     ofn.lpstrFilter = MakeFilter(szFilter);
1177                     ofn.nFilterIndex = 0;
1178                     LoadStringW(hApplet, IDS_BROWSE_FOR_SOUND, szTitle, _countof(szTitle));
1179                     ofn.lpstrTitle = szTitle;
1180                     ofn.lpstrInitialDir = L"%SystemRoot%\\Media";
1181                     ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
1182 
1183                     if (GetOpenFileNameW(&ofn))
1184                     {
1185                         // FIXME search if list already contains that sound
1186 
1187                         // extract file name
1188                         pFileName = wcsrchr(filename, L'\\');
1189                         ASSERT(pFileName != NULL);
1190                         pFileName++;
1191 
1192                         // add to list
1193                         lResult = SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_ADDSTRING, 0, (LPARAM)pFileName);
1194                         if (lResult != CB_ERR)
1195                         {
1196                             // add path and select item
1197                             SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)_wcsdup(filename));
1198                             SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_SETCURSEL, (WPARAM)lResult, 0);
1199                         }
1200                     }
1201                     break;
1202                 }
1203                 case IDC_PLAY_SOUND:
1204                 {
1205                     LRESULT lIndex;
1206                     lIndex = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST));
1207                     if (lIndex == CB_ERR)
1208                     {
1209                         break;
1210                     }
1211 
1212                     lIndex = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex);
1213                     if (lIndex != CB_ERR)
1214                     {
1215                         PlaySoundW((PWCHAR)lIndex, NULL, SND_FILENAME);
1216                     }
1217                     break;
1218                 }
1219                 case IDC_SOUND_SCHEME:
1220                 {
1221                     if (HIWORD(wParam) == CBN_SELENDOK)
1222                     {
1223                         TreeView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_SCHEME_LIST));
1224                         ShowSoundScheme(pGlobalData, hwndDlg);
1225                         EnableWindow(GetDlgItem(hwndDlg, IDC_SOUND_LIST), FALSE);
1226                         EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_SOUND), FALSE);
1227                         EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE);
1228                         EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE_SOUND), FALSE);
1229                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1230                     }
1231                     break;
1232                 }
1233                 case IDC_SOUND_LIST:
1234                 {
1235                     if (HIWORD(wParam) == CBN_SELENDOK)
1236                     {
1237                         PLABEL_CONTEXT pLabelContext;
1238                         HTREEITEM hItem;
1239                         TVITEMW item;
1240                         LRESULT lIndex;
1241 
1242                         hItem = TreeView_GetSelection(GetDlgItem(hwndDlg, IDC_SCHEME_LIST));
1243                         if (hItem == NULL)
1244                         {
1245                             break;
1246                         }
1247 
1248                         lIndex = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST));
1249                         if (lIndex == CB_ERR)
1250                         {
1251                             break;
1252                         }
1253 
1254                         ZeroMemory(&item, sizeof(item));
1255                         item.mask = TVIF_PARAM;
1256                         item.hItem = hItem;
1257                         if (TreeView_GetItem(GetDlgItem(hwndDlg, IDC_SCHEME_LIST), &item))
1258                         {
1259                             LRESULT lResult;
1260                             pLabelContext = (PLABEL_CONTEXT)item.lParam;
1261 
1262                             lResult = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex);
1263                             if (lResult == CB_ERR || lResult == 0)
1264                             {
1265                                 if (lIndex != pLabelContext->szValue[0])
1266                                 {
1267                                     /* Update the tree view item image */
1268                                     item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
1269                                     item.iImage = IMAGE_SOUND_NONE;
1270                                     item.iSelectedImage = IMAGE_SOUND_NONE;
1271                                     TreeView_SetItem(GetDlgItem(hwndDlg, IDC_SCHEME_LIST), &item);
1272 
1273                                     PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1274 
1275                                     EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE);
1276                                 }
1277 
1278                                 pLabelContext->szValue[0] = UNICODE_NULL;
1279 
1280                                 break;
1281                             }
1282 
1283                             if (_wcsicmp(pLabelContext->szValue, (PWCHAR)lResult) || (lIndex != pLabelContext->szValue[0]))
1284                             {
1285                                 /* Update the tree view item image */
1286                                 item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
1287                                 item.iImage = IMAGE_SOUND_ASSIGNED;
1288                                 item.iSelectedImage = IMAGE_SOUND_ASSIGNED;
1289                                 TreeView_SetItem(GetDlgItem(hwndDlg, IDC_SCHEME_LIST), &item);
1290 
1291                                 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
1292 
1293                                 ///
1294                                 /// Should store in current member
1295                                 ///
1296                                 StringCchCopyW(pLabelContext->szValue, _countof(pLabelContext->szValue), (PWCHAR)lResult);
1297                             }
1298 
1299                             if (wcslen((PWCHAR)lResult) && lIndex != 0 && pGlobalData->NumWavOut != 0)
1300                             {
1301                                 EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), TRUE);
1302                             }
1303                             else
1304                             {
1305                                 EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE);
1306                             }
1307                         }
1308                     }
1309                     break;
1310                 }
1311             }
1312             break;
1313         }
1314         case WM_DESTROY:
1315         {
1316             FreeSoundFiles(hwndDlg);
1317             FreeSoundProfiles(hwndDlg);
1318             FreeAppMap(pGlobalData);
1319             FreeLabelMap(pGlobalData);
1320             if (pGlobalData->hSoundsImageList)
1321                 ImageList_Destroy(pGlobalData->hSoundsImageList);
1322             HeapFree(GetProcessHeap(), 0, pGlobalData);
1323             break;
1324         }
1325         case WM_NOTIFY:
1326         {
1327             PLABEL_CONTEXT pLabelContext;
1328             PWCHAR ptr;
1329 
1330             LPNMHDR lpnm = (LPNMHDR)lParam;
1331 
1332             switch (lpnm->code)
1333             {
1334                 case PSN_APPLY:
1335                 {
1336                     ApplyChanges(hwndDlg);
1337                     break;
1338                 }
1339                 case TVN_SELCHANGED:
1340                 {
1341                     LPNMTREEVIEWW nm = (LPNMTREEVIEWW)lParam;
1342                     LRESULT lCount, lIndex, lResult;
1343 
1344                     pLabelContext = (PLABEL_CONTEXT)nm->itemNew.lParam;
1345                     if (pLabelContext == NULL)
1346                     {
1347                         EnableWindow(GetDlgItem(hwndDlg, IDC_SOUND_LIST), FALSE);
1348                         EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_SOUND), FALSE);
1349                         EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE_SOUND), FALSE);
1350                         EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE);
1351                         return FALSE;
1352                     }
1353 
1354                     EnableWindow(GetDlgItem(hwndDlg, IDC_SOUND_LIST), TRUE);
1355                     EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_SOUND), TRUE);
1356                     EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE_SOUND), TRUE);
1357 
1358                     if (wcslen(pLabelContext->szValue) == 0)
1359                     {
1360                         lIndex = ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST), 0);
1361                         EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE);
1362                         break;
1363                     }
1364 
1365                     if (pGlobalData->NumWavOut != 0)
1366                         EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), TRUE);
1367 
1368                     lCount = ComboBox_GetCount(GetDlgItem(hwndDlg, IDC_SOUND_LIST));
1369                     for (lIndex = 0; lIndex < lCount; lIndex++)
1370                     {
1371                         lResult = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex);
1372                         if (lResult == CB_ERR || lResult == 0)
1373                             continue;
1374 
1375                         if (!wcscmp((PWCHAR)lResult, pLabelContext->szValue))
1376                         {
1377                             ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex);
1378                             return FALSE;
1379                         }
1380                     }
1381 
1382                     ptr = wcsrchr(pLabelContext->szValue, L'\\');
1383                     if (ptr)
1384                     {
1385                         ptr++;
1386                     }
1387                     else
1388                     {
1389                         ptr = pLabelContext->szValue;
1390                     }
1391 
1392                     lIndex = ComboBox_AddString(GetDlgItem(hwndDlg, IDC_SOUND_LIST), ptr);
1393                     if (lIndex != CB_ERR)
1394                     {
1395                         ComboBox_SetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex, _wcsdup(pLabelContext->szValue));
1396                         ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex);
1397                     }
1398                     break;
1399                 }
1400             }
1401         }
1402         break;
1403     }
1404 
1405     return FALSE;
1406 }
1407