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