Improved: Configurator.exe now has experimental support for installing the APO even if the sound device previously did not use any APOs. (shown as "APO can be installed (experimental)")

This commit is contained in:
jthedering committed 2013-02-12 19:25:49 +00:00
1 parent ef61580c19
commit 3f07980abc
11 files changed
+284 -52

No files matched your search

+5
View File
@@ -89,6 +89,11 @@ void Configurator::onInitDialog(HWND hDlg)
LoadStringW(hInstance, IDS_ALREADY_INSTALLED, stringBuf, sizeof(stringBuf)/sizeof(wchar_t));
ListView_SetItemText(deviceList, itemCount, 2, stringBuf);
}
else if(it->originalApoGuid == APOGUID_NOKEY)
{
LoadStringW(hInstance, IDS_CAN_BE_INSTALLED_EXPERIMENTAL, stringBuf, sizeof(stringBuf)/sizeof(wchar_t));
ListView_SetItemText(deviceList, itemCount, 2, stringBuf);
}
else
{
LoadStringW(hInstance, IDS_CAN_BE_INSTALLED, stringBuf, sizeof(stringBuf)/sizeof(wchar_t));
Binary file not shown.
Binary file not shown.
+48 -13
View File
@@ -30,6 +30,7 @@ using namespace std;
static const wchar_t* connectionValueName = L"{a45c254e-df1c-4efd-8020-67d146a850e0},2";
static const wchar_t* deviceValueName = L"{b3f8fa53-0004-438e-9003-51a46e139bfc},6";
static const wchar_t* apoGuidValueName = L"{d04e05a6-594b-4fb6-a80d-01af5eed7d1d},1";
static const wchar_t* fxTitleValueName = L"{b725f130-47ef-101a-a5f1-02608c9eebac},10";
vector<DeviceAPOInfo> DeviceAPOInfo::loadAllInfos()
{
@@ -49,21 +50,32 @@ vector<DeviceAPOInfo> DeviceAPOInfo::loadAllInfos()
bool DeviceAPOInfo::load(const wstring& deviceGuid)
{
if(!RegistryHelper::keyExists(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties"))
return false;
this->deviceGuid = deviceGuid;
connectionName = RegistryHelper::readValue(renderKeyPath L"\\" + deviceGuid + L"\\Properties", connectionValueName);
deviceName = RegistryHelper::readValue(renderKeyPath L"\\" + deviceGuid + L"\\Properties", deviceValueName);
originalApoGuid = RegistryHelper::readValue(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName);
GUID apoGuid;
if(!SUCCEEDED(CLSIDFromString(originalApoGuid.c_str(), &apoGuid)))
return false;
isInstalled = false;
if(apoGuid == __uuidof(EqualizerAPO))
isInstalled = true;
if(!RegistryHelper::keyExists(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties"))
{
unsigned long deviceState = RegistryHelper::readDWORDValue(renderKeyPath L"\\" + deviceGuid, L"DeviceState");
if(deviceState == 0x10000004)
// Ignore special internal devices
return false;
originalApoGuid = APOGUID_NOKEY;
}
else
{
originalApoGuid = RegistryHelper::readValue(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName);
GUID apoGuid;
if(!SUCCEEDED(CLSIDFromString(originalApoGuid.c_str(), &apoGuid)))
return false;
if(apoGuid == __uuidof(EqualizerAPO))
isInstalled = true;
}
return true;
}
@@ -74,8 +86,28 @@ void DeviceAPOInfo::install()
RegistryHelper::writeValue(APP_REGPATH L"\\Child APOs", deviceGuid, originalApoGuid);
RegistryHelper::saveToFile(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName,
L"backup_" + StringHelper::replaceIllegalCharacters(deviceName) + L"_" + StringHelper::replaceIllegalCharacters(connectionName) + L".reg");
if(originalApoGuid == APOGUID_NOKEY)
{
try
{
RegistryHelper::createKey(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties");
}
catch(RegistryException e)
{
// Permissions were not sufficient, so change them
RegistryHelper::takeOwnership(renderKeyPath L"\\" + deviceGuid);
RegistryHelper::makeWritable(renderKeyPath L"\\" + deviceGuid);
RegistryHelper::createKey(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties");
}
RegistryHelper::writeValue(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", fxTitleValueName, L"Equalizer APO");
}
else
{
RegistryHelper::saveToFile(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName,
L"backup_" + StringHelper::replaceIllegalCharacters(deviceName) + L"_" + StringHelper::replaceIllegalCharacters(connectionName) + L".reg");
}
RegistryHelper::writeValue(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName, RegistryHelper::getGuidString(__uuidof(EqualizerAPO)));
}
@@ -84,7 +116,10 @@ void DeviceAPOInfo::uninstall()
{
wstring originalChildApoGuid = RegistryHelper::readValue(APP_REGPATH L"\\Child APOs", deviceGuid);
RegistryHelper::writeValue(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName, originalChildApoGuid);
if(originalChildApoGuid == APOGUID_NOKEY)
RegistryHelper::deleteKey(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties");
else
RegistryHelper::writeValue(renderKeyPath L"\\" + deviceGuid + L"\\FxProperties", apoGuidValueName, originalChildApoGuid);
RegistryHelper::deleteValue(APP_REGPATH L"\\Child APOs", deviceGuid);
+2
View File
@@ -22,6 +22,8 @@
#include <string>
#include <vector>
#define APOGUID_NOKEY L"!KEY"
class DeviceAPOInfo
{
public:
+42 -38
View File
@@ -130,47 +130,51 @@ HRESULT EqualizerAPO::Initialize(UINT32 cbDataSize, BYTE* pbyData)
TraceF(L"Child APO GUID: %s", apoGuid.c_str());
GUID childGuid;
hr = CLSIDFromString(apoGuid.c_str(), &childGuid);
if(FAILED(hr))
if(apoGuid != APOGUID_NOKEY)
{
LogF(L"Can't convert guid string to guid");
return hr;
GUID childGuid;
hr = CLSIDFromString(apoGuid.c_str(), &childGuid);
if(FAILED(hr))
{
LogF(L"Can't convert guid string to guid");
return hr;
}
hr = CoCreateInstance(childGuid, NULL, CLSCTX_INPROC_SERVER, __uuidof(IAudioProcessingObject), (void**)&childAPO);
if(FAILED(hr))
{
LogF(L"Error in CoCreateInstance for child apo");
resetChild();
return hr;
}
hr = childAPO->QueryInterface(__uuidof(IAudioProcessingObjectRT), (void**)&childRT);
if(FAILED(hr))
{
LogF(L"Error in QueryInterface for child apo RT");
resetChild();
return hr;
}
hr = childAPO->QueryInterface(__uuidof(IAudioProcessingObjectConfiguration), (void**)&childCfg);
if(FAILED(hr))
{
LogF(L"Error in QueryInterface for child apo configuration");
resetChild();
return hr;
}
hr = childAPO->Initialize(cbDataSize, pbyData);
if(FAILED(hr))
{
LogF(L"Error in Initialize of child apo");
resetChild();
return hr;
}
TraceF(L"Successfully created and initialized child APO");
}
hr = CoCreateInstance(childGuid, NULL, CLSCTX_INPROC_SERVER, __uuidof(IAudioProcessingObject), (void**)&childAPO);
if(FAILED(hr))
{
LogF(L"Error in CoCreateInstance for child apo");
resetChild();
return hr;
}
hr = childAPO->QueryInterface(__uuidof(IAudioProcessingObjectRT), (void**)&childRT);
if(FAILED(hr))
{
LogF(L"Error in QueryInterface for child apo RT");
resetChild();
return hr;
}
hr = childAPO->QueryInterface(__uuidof(IAudioProcessingObjectConfiguration), (void**)&childCfg);
if(FAILED(hr))
{
LogF(L"Error in QueryInterface for child apo configuration");
resetChild();
return hr;
}
hr = childAPO->Initialize(cbDataSize, pbyData);
if(FAILED(hr))
{
LogF(L"Error in Initialize of child apo");
resetChild();
return hr;
}
TraceF(L"Successfully created and initialized child APO");
return hr;
}
+155
View File
@@ -22,6 +22,7 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ObjBase.h>
#include <aclapi.h>
#include "RegistryHelper.h"
@@ -72,6 +73,48 @@ wstring RegistryHelper::readValue(wstring key, wstring valuename)
return result;
}
unsigned long RegistryHelper::readDWORDValue(wstring key, wstring valuename)
{
unsigned long result;
LSTATUS status;
HKEY keyHandle;
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &keyHandle);
if(status != ERROR_SUCCESS)
throw RegistryException(L"Error while opening registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status));
DWORD type;
DWORD bufSize;
status = RegQueryValueExW(keyHandle, valuename.c_str(), NULL, &type, NULL, &bufSize);
if(status != ERROR_SUCCESS)
{
RegCloseKey(keyHandle);
throw RegistryException(L"Error while reading registry value HKEY_LOCAL_MACHINE\\" + key + L"\\" + valuename + L": " + getSystemErrorString(status));
}
if(type != REG_DWORD)
{
RegCloseKey(keyHandle);
throw RegistryException(L"Registry value HKEY_LOCAL_MACHINE\\" + key + L"\\" + valuename + L" has wrong type");
}
BYTE* buf = new BYTE[bufSize];
status = RegQueryValueExW(keyHandle, valuename.c_str(), NULL, NULL, buf, &bufSize);
RegCloseKey(keyHandle);
if(status != ERROR_SUCCESS)
{
delete buf;
throw RegistryException(L"Error while reading registry value HKEY_LOCAL_MACHINE\\" + key + L"\\" + valuename + L": " + getSystemErrorString(status));
}
result = ((unsigned long*)buf)[0];
delete buf;
return result;
}
void RegistryHelper::writeValue(wstring key, wstring valuename, wstring value)
{
LSTATUS status;
@@ -123,6 +166,118 @@ void RegistryHelper::deleteKey(wstring key)
throw RegistryException(L"Error while deleting registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status));
}
void RegistryHelper::makeWritable(wstring key)
{
LSTATUS status;
HKEY keyHandle;
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, READ_CONTROL | WRITE_DAC | KEY_WOW64_64KEY, &keyHandle);
if(status != ERROR_SUCCESS)
throw RegistryException(L"Error while opening registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status));
DWORD descriptorSize = 0;
RegGetKeySecurity(keyHandle, DACL_SECURITY_INFORMATION, NULL, &descriptorSize);
PSECURITY_DESCRIPTOR oldSd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, descriptorSize);
status = RegGetKeySecurity(keyHandle, DACL_SECURITY_INFORMATION, oldSd, &descriptorSize);
if(status != ERROR_SUCCESS)
throw RegistryException(L"Error while getting security information for registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status));
BOOL aclPresent, aclDefaulted;
PACL oldAcl = NULL;
if(!GetSecurityDescriptorDacl(oldSd, &aclPresent, &oldAcl, &aclDefaulted))
throw RegistryException(L"Error in GetSecurityDescriptorDacl while ensuring writability");
PSID sid = NULL;
SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
if(!AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &sid))
throw RegistryException(L"Error in AllocateAndInitializeSid while ensuring writability");
EXPLICIT_ACCESS ea;
ea.grfAccessPermissions = KEY_ALL_ACCESS;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea.Trustee.ptstrName = (LPWSTR)sid;
PACL acl = NULL;
if(ERROR_SUCCESS != SetEntriesInAcl(1, &ea, oldAcl, &acl))
throw RegistryException(L"Error in SetEntriesInAcl while ensuring writability");
PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if(NULL == sd)
throw RegistryException(L"Error in LocalAlloc while ensuring writability");
if(!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION))
throw RegistryException(L"Error in InitializeSecurityDescriptor while ensuring writability");
if(!SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE))
throw RegistryException(L"Error in SetSecurityDescriptorDacl while ensuring writability");
status = RegSetKeySecurity(keyHandle, DACL_SECURITY_INFORMATION, sd);
if(status != ERROR_SUCCESS)
throw RegistryException(L"Error while setting security information for registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status));
FreeSid(sid);
LocalFree(acl);
HeapFree(GetProcessHeap(), 0, oldSd);
LocalFree(sd);
}
void RegistryHelper::takeOwnership(wstring key)
{
HANDLE tokenHandle;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenHandle))
throw RegistryException(L"Error in OpenProcessToken while taking ownership");
LUID luid;
if(!LookupPrivilegeValue(NULL, SE_TAKE_OWNERSHIP_NAME, &luid))
throw RegistryException(L"Error in LookupPrivilegeValue while taking ownership");
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges(tokenHandle, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
throw RegistryException(L"Error in AdjustTokenPrivileges while taking ownership");
LSTATUS status;
HKEY keyHandle;
status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, WRITE_OWNER | KEY_WOW64_64KEY, &keyHandle);
if(status != ERROR_SUCCESS)
throw RegistryException(L"Error while opening registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status));
PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if(NULL == sd)
throw RegistryException(L"Error in SetPrivilege while taking ownership");
if(!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION))
throw RegistryException(L"Error in InitializeSecurityDescriptor while taking ownership");
PSID sid = NULL;
SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
if(!AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, &sid))
throw RegistryException(L"Error in AllocateAndInitializeSid while taking ownership");
if(!SetSecurityDescriptorOwner(sd, sid, FALSE))
throw RegistryException(L"Error in SetSecurityDescriptorOwner while taking ownership");
status = RegSetKeySecurity(keyHandle, OWNER_SECURITY_INFORMATION, sd);
if(status != ERROR_SUCCESS)
throw RegistryException(L"Error while setting security information for registry key HKEY_LOCAL_MACHINE\\" + key + L": " + getSystemErrorString(status));
tp.Privileges[0].Attributes = 0;
if(!AdjustTokenPrivileges(tokenHandle, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
throw RegistryException(L"Error in AdjustTokenPrivileges while taking ownership");
FreeSid(sid);
LocalFree(sd);
}
bool RegistryHelper::keyExists(wstring key)
{
bool result;
+3
View File
@@ -29,10 +29,13 @@ class RegistryHelper
{
public:
static std::wstring readValue(std::wstring key, std::wstring valuename);
static unsigned long readDWORDValue(std::wstring key, std::wstring valuename);
static void writeValue(std::wstring key, std::wstring valuename, std::wstring value);
static void deleteValue(std::wstring key, std::wstring valuename);
static void createKey(std::wstring key);
static void deleteKey(std::wstring key);
static void makeWritable(std::wstring key);
static void takeOwnership(std::wstring key);
static std::vector<std::wstring> enumSubKeys(std::wstring key);
static bool keyExists(std::wstring key);
static unsigned long valueCount(std::wstring key);
+10
View File
@@ -1,4 +1,7 @@
!include "MUI2.nsh"
!include "NSISpcre.nsh"
!insertmacro REReplace
!searchparse /file ..\version.h `#define MAJOR ` MAJOR
!searchparse /file ..\version.h `#define MINOR ` MINOR
@@ -74,6 +77,12 @@ Function .onInit
;Use default installation folder otherwise
StrCmp $INSTDIR "" 0 +2
StrCpy $INSTDIR "$PROGRAMFILES64\EqualizerAPO"
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
;Try to replace version number in start menu folder
${REReplace} $0 "Equalizer APO [0-9]+\.[0-9]+" "$StartMenuFolder" "Equalizer APO ${MAJOR}.${MINOR}" 1
StrCmp $0 "" +2 0
StrCpy $StartMenuFolder "$0"
Call initCheck
FunctionEnd
@@ -130,6 +139,7 @@ Section "Install" SecInstall
!insertmacro MUI_STARTMENU_WRITE_END
WriteRegStr HKLM ${UNINST_REGPATH} "DisplayName" "Equalizer APO"
WriteRegStr HKLM ${UNINST_REGPATH} "DisplayVersion" "${MAJOR}.${MINOR}"
WriteRegStr HKLM ${UNINST_REGPATH} "UninstallString" '"$INSTDIR\Uninstall.exe"'
WriteRegDWORD HKLM ${UNINST_REGPATH} "NoModify" 1
WriteRegDWORD HKLM ${UNINST_REGPATH} "NoRepair" 1
+18
View File
@@ -1,3 +1,21 @@
/*
This file is part of EqualizerAPO, a system-wide equalizer.
Copyright (C) 2013 Jonas Thedering
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string>
#include <sstream>
+1 -1
View File
@@ -1,2 +1,2 @@
#define MAJOR 0
#define MINOR 6
#define MINOR 7