2013-03-16 20:25:38 +00:00
|
|
|
/*
|
2007-09-12 17:51:51 +00:00
|
|
|
* PROJECT: ReactOS Multimedia Control Panel
|
2015-09-22 17:04:32 +00:00
|
|
|
* FILE: dll/cpl/mmsys/sounds.c
|
2007-09-12 17:51:51 +00:00
|
|
|
* PURPOSE: ReactOS Multimedia Control Panel
|
|
|
|
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
|
|
|
|
* Johannes Anderwald <janderwald@reactos.com>
|
2008-02-06 11:36:37 +00:00
|
|
|
* Dmitry Chapyshev <dmitry@reactos.org>
|
2016-07-25 20:24:30 +00:00
|
|
|
* Victor Martinez Calvo <victor.martinez@reactos.org>
|
2017-05-06 10:14:29 +00:00
|
|
|
* Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
2007-09-12 17:51:51 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "mmsys.h"
|
|
|
|
|
2014-01-19 10:35:30 +00:00
|
|
|
#include <commdlg.h>
|
2017-05-06 10:14:29 +00:00
|
|
|
#include <windowsx.h>
|
2016-07-25 20:24:30 +00:00
|
|
|
#include <strsafe.h>
|
|
|
|
|
2014-01-19 10:35:30 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
struct __APP_MAP__;
|
|
|
|
|
|
|
|
typedef struct __LABEL_MAP__
|
2007-09-12 20:22:41 +00:00
|
|
|
{
|
2009-09-20 15:47:32 +00:00
|
|
|
TCHAR * szName;
|
|
|
|
TCHAR * szDesc;
|
|
|
|
TCHAR * szIcon;
|
|
|
|
struct __APP_MAP__ * AppMap;
|
|
|
|
struct __LABEL_MAP__ * Next;
|
2011-11-29 14:55:58 +00:00
|
|
|
} LABEL_MAP, *PLABEL_MAP;
|
2007-09-12 20:22:41 +00:00
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
typedef struct __APP_MAP__
|
2007-09-12 20:22:41 +00:00
|
|
|
{
|
|
|
|
TCHAR szName[MAX_PATH];
|
|
|
|
TCHAR szDesc[MAX_PATH];
|
|
|
|
TCHAR szIcon[MAX_PATH];
|
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
struct __APP_MAP__ *Next;
|
|
|
|
PLABEL_MAP LabelMap;
|
2011-11-29 14:55:58 +00:00
|
|
|
} APP_MAP, *PAPP_MAP;
|
2009-09-20 15:47:32 +00:00
|
|
|
|
|
|
|
typedef struct __LABEL_CONTEXT__
|
|
|
|
{
|
|
|
|
PLABEL_MAP LabelMap;
|
|
|
|
PAPP_MAP AppMap;
|
|
|
|
TCHAR szValue[MAX_PATH];
|
|
|
|
struct __LABEL_CONTEXT__ *Next;
|
2011-11-29 14:55:58 +00:00
|
|
|
} LABEL_CONTEXT, *PLABEL_CONTEXT;
|
2007-09-12 20:22:41 +00:00
|
|
|
|
|
|
|
typedef struct __SOUND_SCHEME_CONTEXT__
|
|
|
|
{
|
|
|
|
TCHAR szName[MAX_PATH];
|
|
|
|
TCHAR szDesc[MAX_PATH];
|
2009-09-20 15:47:32 +00:00
|
|
|
PLABEL_CONTEXT LabelContext;
|
2011-11-29 14:55:58 +00:00
|
|
|
} SOUND_SCHEME_CONTEXT, *PSOUND_SCHEME_CONTEXT;
|
2007-09-12 20:22:41 +00:00
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
static PLABEL_MAP s_Map = NULL;
|
|
|
|
static PAPP_MAP s_App = NULL;
|
|
|
|
|
|
|
|
TCHAR szDefault[MAX_PATH];
|
|
|
|
|
2017-05-06 09:27:32 +00:00
|
|
|
/* A filter string is a list separated by NULL and ends with double NULLs. */
|
|
|
|
LPWSTR MakeFilter(LPWSTR psz)
|
|
|
|
{
|
|
|
|
WCHAR *pch;
|
|
|
|
|
|
|
|
ASSERT(psz[0] != UNICODE_NULL &&
|
|
|
|
psz[wcslen(psz) - 1] == L'|');
|
|
|
|
for (pch = psz; *pch != UNICODE_NULL; pch++)
|
|
|
|
{
|
|
|
|
/* replace vertical bar with NULL */
|
|
|
|
if (*pch == L'|')
|
|
|
|
{
|
|
|
|
*pch = UNICODE_NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return psz;
|
|
|
|
}
|
2009-09-20 15:47:32 +00:00
|
|
|
|
|
|
|
PLABEL_MAP FindLabel(PAPP_MAP pAppMap, TCHAR * szName)
|
2007-09-13 03:11:15 +00:00
|
|
|
{
|
2009-09-20 15:47:32 +00:00
|
|
|
PLABEL_MAP pMap = s_Map;
|
2007-09-13 03:11:15 +00:00
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
while (pMap)
|
2009-09-20 15:47:32 +00:00
|
|
|
{
|
2009-09-20 17:44:52 +00:00
|
|
|
ASSERT(pMap);
|
|
|
|
ASSERT(pMap->szName);
|
2009-09-20 15:47:32 +00:00
|
|
|
if (!_tcscmp(pMap->szName, szName))
|
|
|
|
return pMap;
|
|
|
|
|
|
|
|
pMap = pMap->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
pMap = pAppMap->LabelMap;
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
while (pMap)
|
2009-09-20 15:47:32 +00:00
|
|
|
{
|
2009-09-20 17:44:52 +00:00
|
|
|
ASSERT(pMap);
|
|
|
|
ASSERT(pMap->szName);
|
2009-09-20 15:47:32 +00:00
|
|
|
if (!_tcscmp(pMap->szName, szName))
|
|
|
|
return pMap;
|
2007-09-13 03:11:15 +00:00
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
pMap = pMap->Next;
|
|
|
|
}
|
|
|
|
|
2009-09-20 17:44:52 +00:00
|
|
|
pMap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LABEL_MAP));
|
|
|
|
if (!pMap)
|
|
|
|
return NULL;
|
2009-09-20 15:47:32 +00:00
|
|
|
|
2009-09-20 17:44:52 +00:00
|
|
|
pMap->szName = pMap->szDesc = _tcsdup(szName);
|
|
|
|
if (!pMap->szName)
|
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, pMap);
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2009-09-20 17:44:52 +00:00
|
|
|
pMap->AppMap = pAppMap;
|
|
|
|
pMap->Next = s_Map;
|
|
|
|
s_Map = pMap;
|
|
|
|
|
|
|
|
return pMap;
|
2009-09-20 15:47:32 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
VOID RemoveLabel(PLABEL_MAP pMap)
|
|
|
|
{
|
|
|
|
PLABEL_MAP pCurMap = s_Map;
|
|
|
|
|
|
|
|
if (pCurMap == pMap)
|
|
|
|
{
|
|
|
|
s_Map = s_Map->Next;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
while (pCurMap)
|
2009-09-20 15:47:32 +00:00
|
|
|
{
|
|
|
|
if (pCurMap->Next == pMap)
|
|
|
|
{
|
|
|
|
pCurMap->Next = pCurMap->Next->Next;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pCurMap = pCurMap->Next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PAPP_MAP FindApp(TCHAR * szName)
|
|
|
|
{
|
|
|
|
PAPP_MAP pMap = s_App;
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
while (pMap)
|
2009-09-20 15:47:32 +00:00
|
|
|
{
|
|
|
|
if (!_tcscmp(pMap->szName, szName))
|
|
|
|
return pMap;
|
|
|
|
|
|
|
|
pMap = pMap->Next;
|
|
|
|
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
PLABEL_CONTEXT FindLabelContext(PSOUND_SCHEME_CONTEXT pSoundScheme, TCHAR * AppName, TCHAR * LabelName)
|
|
|
|
{
|
|
|
|
PLABEL_CONTEXT pLabelContext;
|
|
|
|
|
|
|
|
pLabelContext = pSoundScheme->LabelContext;
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
while (pLabelContext)
|
2009-09-20 15:47:32 +00:00
|
|
|
{
|
|
|
|
ASSERT(pLabelContext->AppMap);
|
|
|
|
ASSERT(pLabelContext->LabelMap);
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
if (!_tcsicmp(pLabelContext->AppMap->szName, AppName) && !_tcsicmp(pLabelContext->LabelMap->szName, LabelName))
|
2009-09-20 15:47:32 +00:00
|
|
|
{
|
|
|
|
return pLabelContext;
|
|
|
|
}
|
|
|
|
pLabelContext = pLabelContext->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
pLabelContext = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LABEL_CONTEXT));
|
|
|
|
if (!pLabelContext)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pLabelContext->AppMap = FindApp(AppName);
|
|
|
|
pLabelContext->LabelMap = FindLabel(pLabelContext->AppMap, LabelName);
|
|
|
|
ASSERT(pLabelContext->AppMap);
|
|
|
|
ASSERT(pLabelContext->LabelMap);
|
|
|
|
pLabelContext->szValue[0] = _T('\0');
|
|
|
|
pLabelContext->Next = pSoundScheme->LabelContext;
|
|
|
|
pSoundScheme->LabelContext = pLabelContext;
|
|
|
|
|
|
|
|
return pLabelContext;
|
|
|
|
}
|
2007-09-12 20:22:41 +00:00
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2007-09-12 17:51:51 +00:00
|
|
|
BOOL
|
2007-09-13 03:11:15 +00:00
|
|
|
LoadEventLabel(HKEY hKey, TCHAR * szSubKey)
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
HKEY hSubKey;
|
2017-05-06 08:43:56 +00:00
|
|
|
DWORD cbValue;
|
2007-09-12 17:51:51 +00:00
|
|
|
TCHAR szDesc[MAX_PATH];
|
|
|
|
TCHAR szData[MAX_PATH];
|
2007-09-13 03:11:15 +00:00
|
|
|
PLABEL_MAP pMap;
|
2007-09-12 17:51:51 +00:00
|
|
|
|
|
|
|
if (RegOpenKeyEx(hKey,
|
|
|
|
szSubKey,
|
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hSubKey) != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-05-06 08:43:56 +00:00
|
|
|
cbValue = sizeof(szDesc);
|
2007-09-12 17:51:51 +00:00
|
|
|
if (RegQueryValueEx(hSubKey,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(LPBYTE)szDesc,
|
2017-05-06 08:43:56 +00:00
|
|
|
&cbValue) != ERROR_SUCCESS)
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
RegCloseKey(hSubKey);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-05-06 08:43:56 +00:00
|
|
|
cbValue = sizeof(szData);
|
2007-09-12 17:51:51 +00:00
|
|
|
if (RegQueryValueEx(hSubKey,
|
|
|
|
_T("DispFileName"),
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(LPBYTE)szData,
|
2017-05-06 08:43:56 +00:00
|
|
|
&cbValue) != ERROR_SUCCESS)
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
RegCloseKey(hSubKey);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-09-20 17:44:52 +00:00
|
|
|
pMap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LABEL_MAP));
|
2007-09-13 03:11:15 +00:00
|
|
|
if (!pMap)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
pMap->szName = _tcsdup(szSubKey);
|
|
|
|
pMap->szDesc = _tcsdup(szDesc);
|
|
|
|
pMap->szIcon = _tcsdup(szData);
|
2007-09-12 17:51:51 +00:00
|
|
|
|
2007-09-13 03:11:15 +00:00
|
|
|
if (s_Map)
|
|
|
|
{
|
|
|
|
pMap->Next = s_Map;
|
|
|
|
s_Map = pMap;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s_Map = pMap;
|
|
|
|
s_Map->Next = 0;
|
|
|
|
}
|
2007-09-12 17:51:51 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2007-09-12 17:51:51 +00:00
|
|
|
BOOL
|
2007-09-13 03:11:15 +00:00
|
|
|
LoadEventLabels()
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
HKEY hSubKey;
|
|
|
|
DWORD dwCurKey;
|
|
|
|
TCHAR szName[MAX_PATH];
|
|
|
|
DWORD dwName;
|
|
|
|
DWORD dwResult;
|
|
|
|
DWORD dwCount;
|
2007-09-13 03:11:15 +00:00
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
|
|
_T("AppEvents\\EventLabels"),
|
2007-09-12 17:51:51 +00:00
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hSubKey) != ERROR_SUCCESS)
|
|
|
|
{
|
2007-10-19 23:21:45 +00:00
|
|
|
return FALSE;
|
2007-09-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dwCurKey = 0;
|
|
|
|
dwCount = 0;
|
|
|
|
do
|
|
|
|
{
|
2017-05-06 08:22:50 +00:00
|
|
|
dwName = _countof(szName);
|
2007-09-12 17:51:51 +00:00
|
|
|
dwResult = RegEnumKeyEx(hSubKey,
|
|
|
|
dwCurKey,
|
|
|
|
szName,
|
|
|
|
&dwName,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (dwResult == ERROR_SUCCESS)
|
|
|
|
{
|
2007-09-13 03:11:15 +00:00
|
|
|
if (LoadEventLabel(hSubKey, szName))
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
dwCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dwCurKey++;
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
} while (dwResult == ERROR_SUCCESS);
|
2007-09-12 17:51:51 +00:00
|
|
|
|
|
|
|
RegCloseKey(hSubKey);
|
|
|
|
return (dwCount != 0);
|
|
|
|
}
|
2007-09-13 03:11:15 +00:00
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2007-09-12 17:51:51 +00:00
|
|
|
BOOL
|
2007-09-12 20:22:41 +00:00
|
|
|
AddSoundProfile(HWND hwndDlg, HKEY hKey, TCHAR * szSubKey, BOOL SetDefault)
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
HKEY hSubKey;
|
|
|
|
TCHAR szValue[MAX_PATH];
|
2017-05-06 08:43:56 +00:00
|
|
|
DWORD cbValue, dwResult;
|
2016-07-25 20:24:30 +00:00
|
|
|
LRESULT lResult;
|
|
|
|
PSOUND_SCHEME_CONTEXT pScheme;
|
2007-09-12 17:51:51 +00:00
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
if (RegOpenKeyEx(hKey,
|
2007-09-12 17:51:51 +00:00
|
|
|
szSubKey,
|
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hSubKey) != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-05-06 08:43:56 +00:00
|
|
|
cbValue = sizeof(szValue);
|
2007-09-12 17:51:51 +00:00
|
|
|
dwResult = RegQueryValueEx(hSubKey,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(LPBYTE)szValue,
|
2017-05-06 08:43:56 +00:00
|
|
|
&cbValue);
|
2007-09-12 17:51:51 +00:00
|
|
|
RegCloseKey(hSubKey);
|
2007-09-12 20:22:41 +00:00
|
|
|
|
2016-07-25 20:24:30 +00:00
|
|
|
if (dwResult != ERROR_SUCCESS)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* Try to add the new profile */
|
2017-05-06 10:14:29 +00:00
|
|
|
lResult = ComboBox_AddString(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), szValue);
|
2016-07-25 20:24:30 +00:00
|
|
|
if (lResult == CB_ERR)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* Allocate the profile scheme buffer */
|
|
|
|
pScheme = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOUND_SCHEME_CONTEXT));
|
|
|
|
if (pScheme == NULL)
|
|
|
|
{
|
|
|
|
/* We failed to allocate the buffer, no need to keep a dangling string in the combobox */
|
2017-05-06 10:14:29 +00:00
|
|
|
ComboBox_DeleteString(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lResult);
|
2016-07-25 20:24:30 +00:00
|
|
|
return FALSE;
|
2007-09-12 17:51:51 +00:00
|
|
|
}
|
2016-07-25 20:24:30 +00:00
|
|
|
|
|
|
|
StringCchCopy(pScheme->szDesc, MAX_PATH, szValue);
|
|
|
|
StringCchCopy(pScheme->szName, MAX_PATH, szSubKey);
|
|
|
|
|
|
|
|
/* Associate the value with the item in the combobox */
|
2017-05-06 10:14:29 +00:00
|
|
|
ComboBox_SetItemData(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lResult, pScheme);
|
2016-07-25 20:24:30 +00:00
|
|
|
|
2017-05-06 09:27:32 +00:00
|
|
|
/* Optionally, select the profile */
|
2016-07-25 20:24:30 +00:00
|
|
|
if (SetDefault)
|
2017-05-06 10:14:29 +00:00
|
|
|
{
|
|
|
|
ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lResult);
|
|
|
|
}
|
2016-07-25 20:24:30 +00:00
|
|
|
|
|
|
|
return TRUE;
|
2007-09-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
DWORD
|
|
|
|
EnumerateSoundProfiles(HWND hwndDlg, HKEY hKey)
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
HKEY hSubKey;
|
|
|
|
DWORD dwName, dwCurKey, dwResult, dwNumSchemes;
|
2017-05-06 08:43:56 +00:00
|
|
|
DWORD cbDefault;
|
2007-09-12 17:51:51 +00:00
|
|
|
TCHAR szName[MAX_PATH];
|
|
|
|
|
2017-05-06 08:43:56 +00:00
|
|
|
cbDefault = sizeof(szDefault);
|
2007-09-12 17:51:51 +00:00
|
|
|
if (RegQueryValueEx(hKey,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(LPBYTE)szDefault,
|
2017-05-06 08:43:56 +00:00
|
|
|
&cbDefault) != ERROR_SUCCESS)
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (RegOpenKeyEx(hKey,
|
|
|
|
_T("Names"),
|
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hSubKey) != ERROR_SUCCESS)
|
|
|
|
{
|
2007-10-19 23:21:45 +00:00
|
|
|
return FALSE;
|
2007-09-12 17:51:51 +00:00
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2007-09-12 17:51:51 +00:00
|
|
|
dwNumSchemes = 0;
|
|
|
|
dwCurKey = 0;
|
|
|
|
do
|
|
|
|
{
|
2017-05-06 08:22:50 +00:00
|
|
|
dwName = _countof(szName);
|
2007-09-12 17:51:51 +00:00
|
|
|
dwResult = RegEnumKeyEx(hSubKey,
|
|
|
|
dwCurKey,
|
|
|
|
szName,
|
|
|
|
&dwName,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (dwResult == ERROR_SUCCESS)
|
|
|
|
{
|
2007-09-13 03:11:15 +00:00
|
|
|
if (AddSoundProfile(hwndDlg, hSubKey, szName, (!_tcsicmp(szName, szDefault))))
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
dwNumSchemes++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dwCurKey++;
|
2011-11-29 14:55:58 +00:00
|
|
|
} while (dwResult == ERROR_SUCCESS);
|
2007-09-12 17:51:51 +00:00
|
|
|
|
|
|
|
RegCloseKey(hSubKey);
|
2007-09-12 20:22:41 +00:00
|
|
|
return dwNumSchemes;
|
2007-09-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
PSOUND_SCHEME_CONTEXT FindSoundProfile(HWND hwndDlg, TCHAR * szName)
|
|
|
|
{
|
|
|
|
LRESULT lCount, lIndex, lResult;
|
|
|
|
PSOUND_SCHEME_CONTEXT pScheme;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2017-05-06 10:14:29 +00:00
|
|
|
lCount = ComboBox_GetCount(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME));
|
2007-09-12 20:22:41 +00:00
|
|
|
if (lCount == CB_ERR)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(lIndex = 0; lIndex < lCount; lIndex++)
|
|
|
|
{
|
2017-05-06 10:14:29 +00:00
|
|
|
lResult = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), lIndex);
|
2007-09-12 20:22:41 +00:00
|
|
|
if (lResult == CB_ERR)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
pScheme = (PSOUND_SCHEME_CONTEXT)lResult;
|
|
|
|
if (!_tcsicmp(pScheme->szName, szName))
|
|
|
|
{
|
|
|
|
return pScheme;
|
|
|
|
}
|
|
|
|
}
|
2009-09-20 15:47:32 +00:00
|
|
|
return NULL;
|
2007-09-12 20:22:41 +00:00
|
|
|
}
|
2011-11-29 14:55:58 +00:00
|
|
|
|
|
|
|
|
2007-09-12 17:51:51 +00:00
|
|
|
BOOL
|
2009-09-20 15:47:32 +00:00
|
|
|
ImportSoundLabel(HWND hwndDlg, HKEY hKey, TCHAR * szProfile, TCHAR * szLabelName, TCHAR * szAppName, PAPP_MAP AppMap, PLABEL_MAP LabelMap)
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
HKEY hSubKey;
|
2007-09-12 20:22:41 +00:00
|
|
|
TCHAR szValue[MAX_PATH];
|
2007-09-13 03:11:15 +00:00
|
|
|
TCHAR szBuffer[MAX_PATH];
|
2017-05-06 08:43:56 +00:00
|
|
|
DWORD cbValue, cchLength;
|
2007-09-12 20:22:41 +00:00
|
|
|
PSOUND_SCHEME_CONTEXT pScheme;
|
|
|
|
PLABEL_CONTEXT pLabelContext;
|
2009-09-20 15:47:32 +00:00
|
|
|
BOOL bCurrentProfile, bActiveProfile;
|
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
//MessageBox(hwndDlg, szProfile, szLabelName, MB_OK);
|
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
bCurrentProfile = !_tcsicmp(szProfile, _T(".Current"));
|
|
|
|
bActiveProfile = !_tcsicmp(szProfile, szDefault);
|
|
|
|
|
2007-09-12 17:51:51 +00:00
|
|
|
if (RegOpenKeyEx(hKey,
|
2007-09-12 20:22:41 +00:00
|
|
|
szProfile,
|
2007-09-12 17:51:51 +00:00
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hSubKey) != ERROR_SUCCESS)
|
|
|
|
{
|
2007-09-12 20:22:41 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-05-06 08:43:56 +00:00
|
|
|
cbValue = sizeof(szValue);
|
2007-09-12 20:22:41 +00:00
|
|
|
if (RegQueryValueEx(hSubKey,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(LPBYTE)szValue,
|
2017-05-06 08:43:56 +00:00
|
|
|
&cbValue) != ERROR_SUCCESS)
|
2007-09-12 20:22:41 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2009-09-20 15:47:32 +00:00
|
|
|
|
|
|
|
if (bCurrentProfile)
|
|
|
|
pScheme = FindSoundProfile(hwndDlg, szDefault);
|
|
|
|
else
|
|
|
|
pScheme = FindSoundProfile(hwndDlg, szProfile);
|
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
if (!pScheme)
|
|
|
|
{
|
|
|
|
//MessageBox(hwndDlg, szProfile, _T("no profile!!"), MB_OK);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2009-09-20 15:47:32 +00:00
|
|
|
pLabelContext = FindLabelContext(pScheme, AppMap->szName, LabelMap->szName);
|
2007-09-12 20:22:41 +00:00
|
|
|
|
2017-05-06 08:43:56 +00:00
|
|
|
cchLength = ExpandEnvironmentStrings(szValue, szBuffer, _countof(szBuffer));
|
|
|
|
if (cchLength == 0 || cchLength > _countof(szBuffer))
|
2007-09-13 03:11:15 +00:00
|
|
|
{
|
|
|
|
/* fixme */
|
|
|
|
return FALSE;
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
if (bCurrentProfile)
|
|
|
|
_tcscpy(pLabelContext->szValue, szBuffer);
|
|
|
|
else if (!bActiveProfile)
|
|
|
|
_tcscpy(pLabelContext->szValue, szBuffer);
|
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
2009-09-20 15:47:32 +00:00
|
|
|
ImportSoundEntry(HWND hwndDlg, HKEY hKey, TCHAR * szLabelName, TCHAR * szAppName, PAPP_MAP pAppMap)
|
2007-09-12 20:22:41 +00:00
|
|
|
{
|
|
|
|
HKEY hSubKey;
|
|
|
|
DWORD dwNumProfiles;
|
|
|
|
DWORD dwCurKey;
|
|
|
|
DWORD dwResult;
|
|
|
|
DWORD dwProfile;
|
|
|
|
TCHAR szProfile[MAX_PATH];
|
2009-09-20 15:47:32 +00:00
|
|
|
PLABEL_MAP pLabel;
|
2007-09-12 20:22:41 +00:00
|
|
|
|
|
|
|
if (RegOpenKeyEx(hKey,
|
|
|
|
szLabelName,
|
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hSubKey) != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2009-09-20 17:44:52 +00:00
|
|
|
pLabel = FindLabel(pAppMap, szLabelName);
|
2007-09-12 20:22:41 +00:00
|
|
|
|
2009-09-20 17:44:52 +00:00
|
|
|
ASSERT(pLabel);
|
2009-09-20 15:47:32 +00:00
|
|
|
RemoveLabel(pLabel);
|
|
|
|
|
|
|
|
pLabel->AppMap = pAppMap;
|
|
|
|
pLabel->Next = pAppMap->LabelMap;
|
|
|
|
pAppMap->LabelMap = pLabel;
|
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
dwNumProfiles = 0;
|
|
|
|
dwCurKey = 0;
|
|
|
|
do
|
|
|
|
{
|
2017-05-06 08:22:50 +00:00
|
|
|
dwProfile = _countof(szProfile);
|
2007-09-12 20:22:41 +00:00
|
|
|
dwResult = RegEnumKeyEx(hSubKey,
|
|
|
|
dwCurKey,
|
|
|
|
szProfile,
|
|
|
|
&dwProfile,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (dwResult == ERROR_SUCCESS)
|
|
|
|
{
|
2009-09-20 15:47:32 +00:00
|
|
|
if (ImportSoundLabel(hwndDlg, hSubKey, szProfile, szLabelName, szAppName, pAppMap, pLabel))
|
2007-09-12 20:22:41 +00:00
|
|
|
{
|
|
|
|
dwNumProfiles++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dwCurKey++;
|
2011-11-29 14:55:58 +00:00
|
|
|
} while (dwResult == ERROR_SUCCESS);
|
2007-09-12 17:51:51 +00:00
|
|
|
|
|
|
|
RegCloseKey(hSubKey);
|
2009-09-20 15:47:32 +00:00
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
return dwNumProfiles;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
ImportAppProfile(HWND hwndDlg, HKEY hKey, TCHAR * szAppName)
|
|
|
|
{
|
|
|
|
HKEY hSubKey;
|
|
|
|
TCHAR szDefault[MAX_PATH];
|
2017-05-06 08:43:56 +00:00
|
|
|
DWORD cbValue;
|
2007-09-12 20:22:41 +00:00
|
|
|
DWORD dwCurKey;
|
|
|
|
DWORD dwResult;
|
|
|
|
DWORD dwNumEntry;
|
|
|
|
DWORD dwName;
|
|
|
|
TCHAR szName[MAX_PATH];
|
2007-09-13 03:11:15 +00:00
|
|
|
TCHAR szIcon[MAX_PATH];
|
2009-09-20 15:47:32 +00:00
|
|
|
PAPP_MAP AppMap;
|
2007-09-12 20:22:41 +00:00
|
|
|
|
|
|
|
//MessageBox(hwndDlg, szAppName, _T("Importing...\n"), MB_OK);
|
2007-09-12 17:51:51 +00:00
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
AppMap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APP_MAP));
|
|
|
|
if (!AppMap)
|
|
|
|
return 0;
|
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
if (RegOpenKeyEx(hKey,
|
|
|
|
szAppName,
|
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hSubKey) != ERROR_SUCCESS)
|
|
|
|
{
|
2009-09-20 15:47:32 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, AppMap);
|
|
|
|
return 0;
|
2007-09-12 20:22:41 +00:00
|
|
|
}
|
|
|
|
|
2017-05-06 08:43:56 +00:00
|
|
|
cbValue = sizeof(szDefault);
|
2007-09-12 20:22:41 +00:00
|
|
|
if (RegQueryValueEx(hSubKey,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(LPBYTE)szDefault,
|
2017-05-06 08:43:56 +00:00
|
|
|
&cbValue) != ERROR_SUCCESS)
|
2007-09-12 20:22:41 +00:00
|
|
|
{
|
|
|
|
RegCloseKey(hSubKey);
|
2009-09-20 15:47:32 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, AppMap);
|
|
|
|
return 0;
|
2007-09-12 20:22:41 +00:00
|
|
|
}
|
|
|
|
|
2017-05-06 08:43:56 +00:00
|
|
|
cbValue = sizeof(szIcon);
|
2007-09-13 03:11:15 +00:00
|
|
|
if (RegQueryValueEx(hSubKey,
|
|
|
|
_T("DispFileName"),
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
(LPBYTE)szIcon,
|
2017-05-06 08:43:56 +00:00
|
|
|
&cbValue) != ERROR_SUCCESS)
|
2007-09-13 03:11:15 +00:00
|
|
|
{
|
|
|
|
szIcon[0] = _T('\0');
|
|
|
|
}
|
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
/* initialize app map */
|
|
|
|
_tcscpy(AppMap->szName, szAppName);
|
|
|
|
_tcscpy(AppMap->szDesc, szDefault);
|
|
|
|
_tcscpy(AppMap->szIcon, szIcon);
|
|
|
|
|
|
|
|
AppMap->Next = s_App;
|
|
|
|
s_App = AppMap;
|
|
|
|
|
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
dwCurKey = 0;
|
|
|
|
dwNumEntry = 0;
|
|
|
|
do
|
|
|
|
{
|
2017-05-06 08:22:50 +00:00
|
|
|
dwName = _countof(szName);
|
2007-09-12 20:22:41 +00:00
|
|
|
dwResult = RegEnumKeyEx(hSubKey,
|
|
|
|
dwCurKey,
|
|
|
|
szName,
|
|
|
|
&dwName,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (dwResult == ERROR_SUCCESS)
|
|
|
|
{
|
2009-09-20 15:47:32 +00:00
|
|
|
if (ImportSoundEntry(hwndDlg, hSubKey, szName, szAppName, AppMap))
|
2007-09-12 20:22:41 +00:00
|
|
|
{
|
|
|
|
dwNumEntry++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dwCurKey++;
|
2011-11-29 14:55:58 +00:00
|
|
|
} while (dwResult == ERROR_SUCCESS);
|
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
RegCloseKey(hSubKey);
|
|
|
|
return dwNumEntry;
|
|
|
|
}
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
BOOL
|
|
|
|
ImportSoundProfiles(HWND hwndDlg, HKEY hKey)
|
|
|
|
{
|
|
|
|
DWORD dwCurKey;
|
|
|
|
DWORD dwResult;
|
|
|
|
DWORD dwNumApps;
|
|
|
|
TCHAR szName[MAX_PATH];
|
|
|
|
HKEY hSubKey;
|
|
|
|
|
|
|
|
if (RegOpenKeyEx(hKey,
|
|
|
|
_T("Apps"),
|
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hSubKey) != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
dwNumApps = 0;
|
|
|
|
dwCurKey = 0;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
dwResult = RegEnumKey(hSubKey,
|
|
|
|
dwCurKey,
|
|
|
|
szName,
|
2017-05-06 08:22:50 +00:00
|
|
|
_countof(szName));
|
2007-09-12 20:22:41 +00:00
|
|
|
|
|
|
|
if (dwResult == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
if (ImportAppProfile(hwndDlg, hSubKey, szName))
|
|
|
|
{
|
|
|
|
dwNumApps++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dwCurKey++;
|
2011-11-29 14:55:58 +00:00
|
|
|
} while (dwResult == ERROR_SUCCESS);
|
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
RegCloseKey(hSubKey);
|
|
|
|
|
|
|
|
return (dwNumApps != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
2007-09-13 03:11:15 +00:00
|
|
|
LoadSoundProfiles(HWND hwndDlg)
|
2007-09-12 20:22:41 +00:00
|
|
|
{
|
|
|
|
HKEY hSubKey;
|
|
|
|
DWORD dwNumSchemes;
|
|
|
|
|
2007-09-13 03:11:15 +00:00
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
|
|
_T("AppEvents\\Schemes"),
|
2007-09-12 20:22:41 +00:00
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hSubKey) != ERROR_SUCCESS)
|
|
|
|
{
|
2007-10-19 23:21:45 +00:00
|
|
|
return FALSE;
|
2007-09-12 20:22:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dwNumSchemes = EnumerateSoundProfiles(hwndDlg, hSubKey);
|
|
|
|
|
|
|
|
|
|
|
|
if (dwNumSchemes)
|
|
|
|
{
|
|
|
|
//MessageBox(hwndDlg, _T("importing sound profiles..."), NULL, MB_OK);
|
2007-10-19 23:21:45 +00:00
|
|
|
ImportSoundProfiles(hwndDlg, hSubKey);
|
2007-09-12 20:22:41 +00:00
|
|
|
}
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2007-09-12 20:22:41 +00:00
|
|
|
RegCloseKey(hSubKey);
|
|
|
|
return FALSE;
|
2007-09-12 17:51:51 +00:00
|
|
|
}
|
2011-11-29 14:55:58 +00:00
|
|
|
|
|
|
|
|
2007-09-13 03:11:15 +00:00
|
|
|
BOOL
|
|
|
|
LoadSoundFiles(HWND hwndDlg)
|
|
|
|
{
|
2017-05-06 10:14:29 +00:00
|
|
|
TCHAR szList[256];
|
2008-10-30 09:58:12 +00:00
|
|
|
WCHAR szPath[MAX_PATH];
|
|
|
|
WCHAR * ptr;
|
|
|
|
WIN32_FIND_DATAW FileData;
|
2007-09-13 03:11:15 +00:00
|
|
|
HANDLE hFile;
|
|
|
|
LRESULT lResult;
|
|
|
|
UINT length;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2010-05-30 15:13:04 +00:00
|
|
|
/* Add no sound listview item */
|
2017-05-06 10:14:29 +00:00
|
|
|
if (LoadString(hApplet, IDS_NO_SOUND, szList, _countof(szList)))
|
2010-05-30 15:13:04 +00:00
|
|
|
{
|
2017-05-06 10:14:29 +00:00
|
|
|
szList[_countof(szList) - 1] = TEXT('\0');
|
|
|
|
ComboBox_AddString(GetDlgItem(hwndDlg, IDC_SOUND_LIST), szList);
|
2010-05-30 15:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Load sound files */
|
2008-10-30 09:58:12 +00:00
|
|
|
length = GetWindowsDirectoryW(szPath, MAX_PATH);
|
|
|
|
if (length == 0 || length >= MAX_PATH - 9)
|
2007-09-13 03:11:15 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-10-30 09:58:12 +00:00
|
|
|
if (szPath[length-1] != L'\\')
|
2007-09-13 03:11:15 +00:00
|
|
|
{
|
2008-10-30 09:58:12 +00:00
|
|
|
szPath[length] = L'\\';
|
2007-09-13 03:11:15 +00:00
|
|
|
length++;
|
|
|
|
}
|
2008-10-30 09:58:12 +00:00
|
|
|
wcscpy(&szPath[length], L"media\\*");
|
2007-09-13 03:11:15 +00:00
|
|
|
length += 7;
|
|
|
|
|
2008-10-30 09:58:12 +00:00
|
|
|
hFile = FindFirstFileW(szPath, &FileData);
|
2007-09-13 03:11:15 +00:00
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
|
|
continue;
|
|
|
|
|
2008-10-30 09:58:12 +00:00
|
|
|
ptr = wcsrchr(FileData.cFileName, L'\\');
|
2007-09-13 03:11:15 +00:00
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ptr = FileData.cFileName;
|
|
|
|
}
|
2008-10-30 09:58:12 +00:00
|
|
|
lResult = SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_ADDSTRING, (WPARAM)0, (LPARAM)ptr);
|
2007-09-13 03:11:15 +00:00
|
|
|
if (lResult != CB_ERR)
|
|
|
|
{
|
2008-10-30 09:58:12 +00:00
|
|
|
wcscpy(&szPath[length-1], FileData.cFileName);
|
2008-12-23 01:23:25 +00:00
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)_wcsdup(szPath));
|
2007-09-13 03:11:15 +00:00
|
|
|
}
|
2011-11-29 14:55:58 +00:00
|
|
|
} while (FindNextFileW(hFile, &FileData) != 0);
|
2007-09-13 03:11:15 +00:00
|
|
|
|
|
|
|
FindClose(hFile);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2007-09-12 17:51:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
2007-09-13 03:11:15 +00:00
|
|
|
ShowSoundScheme(HWND hwndDlg)
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
2007-09-13 03:11:15 +00:00
|
|
|
LRESULT lIndex;
|
|
|
|
PSOUND_SCHEME_CONTEXT pScheme;
|
2009-09-20 15:47:32 +00:00
|
|
|
PAPP_MAP pAppMap;
|
2007-09-13 03:11:15 +00:00
|
|
|
LV_ITEM listItem;
|
|
|
|
LV_COLUMN dummy;
|
|
|
|
HWND hDlgCtrl, hList;
|
|
|
|
RECT rect;
|
|
|
|
int ItemIndex;
|
|
|
|
hDlgCtrl = GetDlgItem(hwndDlg, IDC_SOUND_SCHEME);
|
|
|
|
hList = GetDlgItem(hwndDlg, IDC_SCHEME_LIST);
|
|
|
|
|
|
|
|
lIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
|
|
|
|
if (lIndex == CB_ERR)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2007-09-12 17:51:51 +00:00
|
|
|
|
2007-09-13 03:11:15 +00:00
|
|
|
lIndex = SendMessage(hDlgCtrl, CB_GETITEMDATA, (WPARAM)lIndex, (LPARAM)0);
|
|
|
|
if (lIndex == CB_ERR)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
pScheme = (PSOUND_SCHEME_CONTEXT)lIndex;
|
2009-09-20 15:47:32 +00:00
|
|
|
|
|
|
|
_tcscpy(szDefault, pScheme->szName);
|
2007-09-12 17:51:51 +00:00
|
|
|
|
2007-09-13 03:11:15 +00:00
|
|
|
/* add column for app */
|
|
|
|
GetClientRect(hList, &rect);
|
2017-05-06 08:22:50 +00:00
|
|
|
ZeroMemory(&dummy, sizeof(dummy));
|
2007-09-13 03:11:15 +00:00
|
|
|
dummy.mask = LVCF_WIDTH;
|
|
|
|
dummy.iSubItem = 0;
|
|
|
|
dummy.cx = rect.right - rect.left - GetSystemMetrics(SM_CXVSCROLL);
|
|
|
|
(void)ListView_InsertColumn(hList, 0, &dummy);
|
|
|
|
ItemIndex = 0;
|
2009-09-20 15:47:32 +00:00
|
|
|
|
|
|
|
pAppMap = s_App;
|
2011-11-29 14:55:58 +00:00
|
|
|
while (pAppMap)
|
2007-09-13 03:11:15 +00:00
|
|
|
{
|
2009-09-20 15:47:32 +00:00
|
|
|
PLABEL_MAP pLabelMap = pAppMap->LabelMap;
|
2011-11-29 14:55:58 +00:00
|
|
|
while (pLabelMap)
|
2007-09-13 03:11:15 +00:00
|
|
|
{
|
2017-05-06 08:22:50 +00:00
|
|
|
ZeroMemory(&listItem, sizeof(listItem));
|
2007-09-13 03:11:15 +00:00
|
|
|
listItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
|
2009-09-20 15:47:32 +00:00
|
|
|
listItem.pszText = pLabelMap->szDesc;
|
|
|
|
listItem.lParam = (LPARAM)FindLabelContext(pScheme, pAppMap->szName, pLabelMap->szName);
|
2007-09-13 03:11:15 +00:00
|
|
|
listItem.iItem = ItemIndex;
|
|
|
|
listItem.iImage = -1;
|
|
|
|
(void)ListView_InsertItem(hList, &listItem);
|
|
|
|
ItemIndex++;
|
2009-09-20 15:47:32 +00:00
|
|
|
|
|
|
|
pLabelMap = pLabelMap->Next;
|
2007-09-13 03:11:15 +00:00
|
|
|
}
|
2009-09-20 15:47:32 +00:00
|
|
|
pAppMap = pAppMap->Next;
|
2007-09-13 03:11:15 +00:00
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
2009-09-20 15:47:32 +00:00
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
|
2009-09-20 15:47:32 +00:00
|
|
|
BOOL
|
|
|
|
ApplyChanges(HWND hwndDlg)
|
|
|
|
{
|
|
|
|
HKEY hKey, hSubKey;
|
|
|
|
LRESULT lIndex;
|
|
|
|
PSOUND_SCHEME_CONTEXT pScheme;
|
|
|
|
HWND hDlgCtrl;
|
|
|
|
PLABEL_CONTEXT pLabelContext;
|
|
|
|
TCHAR Buffer[100];
|
|
|
|
|
|
|
|
hDlgCtrl = GetDlgItem(hwndDlg, IDC_SOUND_SCHEME);
|
|
|
|
|
|
|
|
lIndex = SendMessage(hDlgCtrl, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
|
|
|
|
if (lIndex == CB_ERR)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
lIndex = SendMessage(hDlgCtrl, CB_GETITEMDATA, (WPARAM)lIndex, (LPARAM)0);
|
|
|
|
if (lIndex == CB_ERR)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
pScheme = (PSOUND_SCHEME_CONTEXT)lIndex;
|
|
|
|
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
|
|
_T("AppEvents\\Schemes"),
|
|
|
|
0,
|
|
|
|
KEY_WRITE,
|
|
|
|
&hKey) != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)pScheme->szName, (_tcslen(pScheme->szName) +1) * sizeof(TCHAR));
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
|
|
_T("AppEvents\\Schemes\\Apps"),
|
|
|
|
0,
|
|
|
|
KEY_WRITE,
|
|
|
|
&hKey) != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pLabelContext = pScheme->LabelContext;
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
while (pLabelContext)
|
2009-09-20 15:47:32 +00:00
|
|
|
{
|
|
|
|
_stprintf(Buffer, _T("%s\\%s\\.Current"), pLabelContext->AppMap->szName, pLabelContext->LabelMap->szName);
|
|
|
|
|
|
|
|
if (RegOpenKeyEx(hKey, Buffer, 0, KEY_WRITE, &hSubKey) == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
RegSetValueEx(hSubKey, NULL, 0, REG_EXPAND_SZ, (LPBYTE)pLabelContext->szValue, (_tcslen(pLabelContext->szValue) +1) * sizeof(TCHAR));
|
|
|
|
RegCloseKey(hSubKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
pLabelContext = pLabelContext->Next;
|
|
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
|
2018-02-27 21:48:32 +00:00
|
|
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)PSNRET_NOERROR);
|
2009-09-20 15:47:32 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-12 17:51:51 +00:00
|
|
|
/* Sounds property page dialog callback */
|
|
|
|
INT_PTR
|
|
|
|
CALLBACK
|
|
|
|
SoundsDlgProc(HWND hwndDlg,
|
2008-02-06 11:36:37 +00:00
|
|
|
UINT uMsg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
2013-06-15 08:23:21 +00:00
|
|
|
OPENFILENAMEW ofn;
|
|
|
|
WCHAR filename[MAX_PATH];
|
2017-05-06 09:27:32 +00:00
|
|
|
WCHAR szFilter[256], szTitle[256];
|
2013-06-15 08:23:21 +00:00
|
|
|
LPWSTR pFileName;
|
|
|
|
LRESULT lResult;
|
|
|
|
|
2011-11-29 14:55:58 +00:00
|
|
|
switch (uMsg)
|
2007-09-12 17:51:51 +00:00
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
2008-02-06 11:36:37 +00:00
|
|
|
{
|
2009-08-15 14:49:44 +00:00
|
|
|
UINT NumWavOut = waveOutGetNumDevs();
|
2008-02-06 11:36:37 +00:00
|
|
|
|
|
|
|
SendMessage(GetDlgItem(hwndDlg, IDC_PLAY_SOUND),
|
|
|
|
BM_SETIMAGE,(WPARAM)IMAGE_ICON,
|
|
|
|
(LPARAM)(HANDLE)LoadIcon(hApplet, MAKEINTRESOURCE(IDI_PLAY_ICON)));
|
|
|
|
|
2007-09-13 03:11:15 +00:00
|
|
|
LoadEventLabels();
|
|
|
|
LoadSoundProfiles(hwndDlg);
|
|
|
|
LoadSoundFiles(hwndDlg);
|
|
|
|
ShowSoundScheme(hwndDlg);
|
2009-08-15 14:49:44 +00:00
|
|
|
|
|
|
|
if (!NumWavOut)
|
|
|
|
{
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME), FALSE);
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_SAVEAS_BTN), FALSE);
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE_BTN), FALSE);
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_SCHEME_LIST), FALSE);
|
|
|
|
}
|
|
|
|
|
2007-09-13 03:11:15 +00:00
|
|
|
if (wParam == (WPARAM)GetDlgItem(hwndDlg, IDC_SOUND_SCHEME))
|
|
|
|
return TRUE;
|
|
|
|
SetFocus(GetDlgItem(hwndDlg, IDC_SOUND_SCHEME));
|
|
|
|
return FALSE;
|
2008-02-06 11:36:37 +00:00
|
|
|
}
|
2007-09-13 03:11:15 +00:00
|
|
|
case WM_COMMAND:
|
|
|
|
{
|
2011-11-29 14:55:58 +00:00
|
|
|
switch (LOWORD(wParam))
|
2007-09-13 03:11:15 +00:00
|
|
|
{
|
2013-06-15 08:23:21 +00:00
|
|
|
case IDC_BROWSE_SOUND:
|
|
|
|
{
|
2017-05-06 08:22:50 +00:00
|
|
|
ZeroMemory(&ofn, sizeof(ofn));
|
|
|
|
ofn.lStructSize = sizeof(ofn);
|
2013-06-15 08:23:21 +00:00
|
|
|
ofn.hwndOwner = hwndDlg;
|
|
|
|
ofn.lpstrFile = filename;
|
|
|
|
ofn.lpstrFile[0] = L'\0';
|
2017-05-06 09:27:32 +00:00
|
|
|
ofn.nMaxFile = _countof(filename);
|
|
|
|
LoadStringW(hApplet, IDS_WAVE_FILES_FILTER, szFilter, _countof(szFilter));
|
|
|
|
ofn.lpstrFilter = MakeFilter(szFilter);
|
2013-06-15 08:23:21 +00:00
|
|
|
ofn.nFilterIndex = 0;
|
2017-05-06 09:27:32 +00:00
|
|
|
LoadStringW(hApplet, IDS_BROWSE_FOR_SOUND, szTitle, _countof(szTitle));
|
|
|
|
ofn.lpstrTitle = szTitle;
|
2013-06-15 08:23:21 +00:00
|
|
|
ofn.lpstrInitialDir = NULL;
|
2014-04-15 18:03:29 +00:00
|
|
|
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
2013-06-15 08:23:21 +00:00
|
|
|
|
2017-10-01 14:42:04 +00:00
|
|
|
if (GetOpenFileNameW(&ofn) != FALSE)
|
2013-06-15 08:23:21 +00:00
|
|
|
{
|
2017-05-06 08:22:50 +00:00
|
|
|
// FIXME search if list already contains that sound
|
2013-06-15 08:23:21 +00:00
|
|
|
|
|
|
|
// extract file name
|
|
|
|
pFileName = wcsrchr(filename, L'\\');
|
|
|
|
ASSERT(pFileName != NULL);
|
|
|
|
pFileName++;
|
|
|
|
|
|
|
|
// add to list
|
|
|
|
lResult = SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_ADDSTRING, (WPARAM)0, (LPARAM)pFileName);
|
|
|
|
if (lResult != CB_ERR)
|
|
|
|
{
|
|
|
|
// add path and select item
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)_wcsdup(filename));
|
|
|
|
SendDlgItemMessageW(hwndDlg, IDC_SOUND_LIST, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2007-09-13 03:11:15 +00:00
|
|
|
case IDC_PLAY_SOUND:
|
|
|
|
{
|
|
|
|
LRESULT lIndex;
|
2017-05-06 10:14:29 +00:00
|
|
|
lIndex = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST));
|
2007-09-13 03:11:15 +00:00
|
|
|
if (lIndex == CB_ERR)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2009-03-09 11:51:28 +00:00
|
|
|
|
2017-05-06 10:14:29 +00:00
|
|
|
lIndex = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex);
|
2009-03-09 11:51:28 +00:00
|
|
|
if (lIndex != CB_ERR)
|
|
|
|
{
|
|
|
|
PlaySound((TCHAR*)lIndex, NULL, SND_FILENAME);
|
|
|
|
}
|
2007-09-13 03:11:15 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case IDC_SOUND_SCHEME:
|
|
|
|
{
|
|
|
|
if (HIWORD(wParam) == CBN_SELENDOK)
|
|
|
|
{
|
|
|
|
(void)ListView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_SCHEME_LIST));
|
|
|
|
ShowSoundScheme(hwndDlg);
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_SOUND_LIST), FALSE);
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_SOUND), FALSE);
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE);
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE_SOUND), FALSE);
|
2009-09-20 15:47:32 +00:00
|
|
|
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
2007-09-13 03:11:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case IDC_SOUND_LIST:
|
|
|
|
{
|
|
|
|
if (HIWORD(wParam) == CBN_SELENDOK)
|
|
|
|
{
|
|
|
|
PLABEL_CONTEXT pLabelContext;
|
|
|
|
INT SelCount;
|
|
|
|
LVITEM item;
|
|
|
|
LRESULT lIndex;
|
2009-09-20 15:47:32 +00:00
|
|
|
SelCount = ListView_GetSelectionMark(GetDlgItem(hwndDlg, IDC_SCHEME_LIST));
|
2007-09-13 03:11:15 +00:00
|
|
|
if (SelCount == -1)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2017-05-06 10:14:29 +00:00
|
|
|
lIndex = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST));
|
2007-09-13 03:11:15 +00:00
|
|
|
if (lIndex == CB_ERR)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2017-05-06 08:22:50 +00:00
|
|
|
ZeroMemory(&item, sizeof(item));
|
2007-09-13 03:11:15 +00:00
|
|
|
item.mask = LVIF_PARAM;
|
|
|
|
item.iItem = SelCount;
|
|
|
|
if (ListView_GetItem(GetDlgItem(hwndDlg, IDC_SCHEME_LIST), &item))
|
|
|
|
{
|
2009-09-20 15:47:32 +00:00
|
|
|
LRESULT lResult;
|
2007-09-13 03:11:15 +00:00
|
|
|
pLabelContext = (PLABEL_CONTEXT)item.lParam;
|
2009-09-20 15:47:32 +00:00
|
|
|
|
2017-05-06 10:14:29 +00:00
|
|
|
lResult = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex);
|
2009-09-20 15:47:32 +00:00
|
|
|
if (lResult == CB_ERR || lResult == 0)
|
|
|
|
{
|
|
|
|
if (lIndex != pLabelContext->szValue[0])
|
|
|
|
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
|
|
|
|
|
|
|
pLabelContext->szValue[0] = L'\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_tcsicmp(pLabelContext->szValue, (TCHAR*)lResult) || (lIndex != pLabelContext->szValue[0]))
|
|
|
|
{
|
|
|
|
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
|
|
|
///
|
2011-11-29 14:55:58 +00:00
|
|
|
/// Should store in current member
|
2009-09-20 15:47:32 +00:00
|
|
|
///
|
|
|
|
_tcscpy(pLabelContext->szValue, (TCHAR*)lResult);
|
|
|
|
}
|
|
|
|
if (_tcslen((TCHAR*)lResult) && lIndex != 0)
|
2007-09-13 03:11:15 +00:00
|
|
|
{
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), TRUE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_NOTIFY:
|
|
|
|
{
|
|
|
|
LVITEM item;
|
|
|
|
PLABEL_CONTEXT pLabelContext;
|
|
|
|
TCHAR * ptr;
|
2009-09-20 15:47:32 +00:00
|
|
|
|
|
|
|
LPNMHDR lpnm = (LPNMHDR)lParam;
|
|
|
|
|
2007-09-13 03:11:15 +00:00
|
|
|
switch(lpnm->code)
|
|
|
|
{
|
2009-09-20 15:47:32 +00:00
|
|
|
case PSN_APPLY:
|
|
|
|
{
|
|
|
|
ApplyChanges(hwndDlg);
|
|
|
|
break;
|
|
|
|
}
|
2007-09-13 03:11:15 +00:00
|
|
|
case LVN_ITEMCHANGED:
|
|
|
|
{
|
|
|
|
LPNMLISTVIEW nm = (LPNMLISTVIEW)lParam;
|
|
|
|
|
|
|
|
if ((nm->uNewState & LVIS_SELECTED) == 0)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2017-05-06 08:22:50 +00:00
|
|
|
ZeroMemory(&item, sizeof(item));
|
2007-09-13 03:11:15 +00:00
|
|
|
item.mask = LVIF_PARAM;
|
|
|
|
item.iItem = nm->iItem;
|
2010-05-30 15:13:04 +00:00
|
|
|
|
2007-09-13 03:11:15 +00:00
|
|
|
if (ListView_GetItem(GetDlgItem(hwndDlg, IDC_SCHEME_LIST), &item))
|
|
|
|
{
|
|
|
|
LRESULT lCount, lIndex, lResult;
|
|
|
|
pLabelContext = (PLABEL_CONTEXT)item.lParam;
|
|
|
|
if (!pLabelContext)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_SOUND_LIST), TRUE);
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT_SOUND), TRUE);
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE_SOUND), TRUE);
|
|
|
|
if (_tcslen(pLabelContext->szValue) == 0)
|
|
|
|
{
|
2017-05-06 10:14:29 +00:00
|
|
|
lIndex = ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST), 0);
|
2007-09-13 03:11:15 +00:00
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), FALSE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
EnableWindow(GetDlgItem(hwndDlg, IDC_PLAY_SOUND), TRUE);
|
2017-05-06 10:14:29 +00:00
|
|
|
lCount = ComboBox_GetCount(GetDlgItem(hwndDlg, IDC_SOUND_LIST));
|
2007-09-13 03:11:15 +00:00
|
|
|
for (lIndex = 0; lIndex < lCount; lIndex++)
|
|
|
|
{
|
2017-05-06 10:14:29 +00:00
|
|
|
lResult = ComboBox_GetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex);
|
2007-09-13 03:11:15 +00:00
|
|
|
if (lResult == CB_ERR || lResult == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!_tcscmp((TCHAR*)lResult, pLabelContext->szValue))
|
|
|
|
{
|
2017-05-06 10:14:29 +00:00
|
|
|
ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex);
|
2007-09-13 03:11:15 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ptr = _tcsrchr(pLabelContext->szValue, _T('\\'));
|
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ptr = pLabelContext->szValue;
|
|
|
|
}
|
2017-05-06 10:14:29 +00:00
|
|
|
lIndex = ComboBox_AddString(GetDlgItem(hwndDlg, IDC_SOUND_LIST), ptr);
|
2007-09-13 03:11:15 +00:00
|
|
|
if (lIndex != CB_ERR)
|
|
|
|
{
|
2017-05-06 10:14:29 +00:00
|
|
|
ComboBox_SetItemData(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex, _tcsdup(pLabelContext->szValue));
|
|
|
|
ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_SOUND_LIST), lIndex);
|
2007-09-13 03:11:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-09-12 17:51:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|