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