#include "stdafx.h"
#include <map>
#include <vector>
#include "ChromaSDKImpl.h"
#include <psapi.h>
#include <wintrust.h>
#include <Softpub.h>
#pragma comment (lib, "wintrust")
#pragma comment (lib, "Psapi")
#pragma comment (lib, "crypt32")
CChromaSDKImpl g_ChromaSDKImpl;
#ifdef _WIN64
#define CHROMASDKDLL _T("RzChromaSDK64.dll")
#else
#define CHROMASDKDLL _T("RzChromaSDK.dll")
#endif
using namespace std;
using namespace ChromaSDK;
CREATEMOUSEPADEFFECT CreateMousematEffect = NULL;
#define EVENT_NAME _T("{4784D90A-1179-4F7D-8558-52511D809190}")
#define MAX_EFFECTS 100
typedef struct _EFFECTDATATYPE
{
LONG numEffects;
BOOL repeat;
HANDLE thread;
struct _EFFECT
{
LONG delay;
} Effect[MAX_EFFECTS];
} EFFECTDATATYPE;
struct GUIDCompare
{
bool operator()(const GUID & Left, const GUID & Right) const
{
return memcmp(&Left , &Right,sizeof(Right)) < 0;
}
};
std::map<RZEFFECTID, EFFECTDATATYPE, GUIDCompare> g_Effects;
DWORD WINAPI Thread_RenderEffects(LPVOID lpParameter)
{
auto iterator = g_Effects.find(*pEffectId);
if(iterator != g_Effects.end())
{
EFFECTDATATYPE *pEffectData = &iterator->second;
CFrameController FrameControl(30);
if(pEffectData->repeat == FALSE)
{
for(int i=0; i<pEffectData->numEffects; i++)
{
FrameControl.Begin();
Sleep(pEffectData->Effect[i].delay);
FrameControl.End();
}
}
else
{
while(pEffectData->repeat)
{
for(int i=0; i<pEffectData->numEffects; i++)
{
FrameControl.Begin();
Sleep(pEffectData->Effect[i].delay);
FrameControl.End();
}
};
}
}
return 0;
}
BOOL IsValidPath(PTCHAR szFileName)
{
BOOL bResult = FALSE;
TCHAR szModuleName[MAX_PATH] = L"";
_tcscpy_s(szModuleName, MAX_PATH, szFileName);
PathStripPath(szModuleName);
DWORD dwLength = 0;
TCHAR szFileNameExpected[MAX_PATH] = L"";
TCHAR szPath[MAX_PATH] = L"";
dwLength = GetEnvironmentVariable(L"SystemRoot",
szPath,
MAX_PATH);
if(dwLength > 0)
{
_tcscpy_s(szFileNameExpected, dwLength+1, szPath);
_tcscat_s(szFileNameExpected, MAX_PATH, L"\\System32\\");
_tcscat_s(szFileNameExpected, MAX_PATH, szModuleName);
if(_tcsicmp(szFileNameExpected, szFileName) == 0)
{
bResult = TRUE;
}
}
dwLength = GetEnvironmentVariable(L"ProgramFiles",
szPath,
MAX_PATH);
if(dwLength > 0)
{
_tcscpy_s(szFileNameExpected, dwLength+1, szPath);
_tcscat_s(szFileNameExpected, MAX_PATH, L"\\Razer Chroma SDK\\bin\\");
_tcscat_s(szFileNameExpected, MAX_PATH, szModuleName);
if(_tcsicmp(szFileNameExpected, szFileName) == 0)
{
bResult = TRUE;
}
}
return bResult;
}
BOOL GetCertInfoFromFile(const wchar_t* pszFileName, void** ppCertInfo)
{
BOOL result = FALSE;
DWORD dwEncoding = 0;
DWORD dwContentType = 0;
DWORD dwFormatType = 0;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
if (TRUE == CryptQueryObject(
CERT_QUERY_OBJECT_FILE,
pszFileName,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY,
0,
&dwEncoding,
&dwContentType,
&dwFormatType,
&hStore,
&hMsg,
NULL))
{
DWORD cbData = 0;
if (TRUE == CryptMsgGetParam(
hMsg,
CMSG_SIGNER_CERT_INFO_PARAM,
0,
NULL,
&cbData))
{
*ppCertInfo = LocalAlloc(LPTR, cbData);
if (*ppCertInfo != NULL)
{
if (TRUE == CryptMsgGetParam(
hMsg,
CMSG_SIGNER_CERT_INFO_PARAM,
0,
*ppCertInfo,
&cbData))
{
result = TRUE;
}
}
}
CryptMsgClose(hMsg);
CertCloseStore(hStore, 0);
}
return result;
}
BOOL IsFileSignedByRazer(PTCHAR szFileName)
{
BOOL bResult = FALSE;
PCERT_INFO pChromaSDKDLLCertInfo = nullptr;
PCERT_INFO pChromaSDKServiceCertInfo = nullptr;
if (GetCertInfoFromFile(szFileName, (void**)&pChromaSDKDLLCertInfo) == TRUE)
{
HKEY hKey = NULL;
auto status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
LR"(SOFTWARE\RAZER CHROMA SDK)",
0,
KEY_QUERY_VALUE | KEY_WOW64_32KEY,
&hKey);
if (status == NO_ERROR)
{
TCHAR szFilename[MAX_PATH];
DWORD dwSize = sizeof(TCHAR) * MAX_PATH;
status = RegQueryValueEx(
hKey,
L"InstallPath",
NULL,
NULL,
(LPBYTE)szFilename,
&dwSize);
if (status == NO_ERROR)
{
PathAppend(szFilename, L"\\bin\\RzSDKService.exe");
if (GetCertInfoFromFile(szFilename, (void**)&pChromaSDKServiceCertInfo) == TRUE)
{
bResult = CertCompareCertificate(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
pChromaSDKDLLCertInfo,
pChromaSDKServiceCertInfo
);
LocalFree(pChromaSDKServiceCertInfo);
}
}
RegCloseKey(hKey);
}
LocalFree(pChromaSDKDLLCertInfo);
}
return bResult;
}
BOOL IsFileSigned(PTCHAR szFileName)
{
BOOL bResult = FALSE;
DWORD dwLastError = 0;
WINTRUST_FILE_INFO FileData = {};
FileData.cbStruct = sizeof(WINTRUST_FILE_INFO);
FileData.pcwszFilePath = szFileName;
FileData.hFile = NULL;
FileData.pgKnownSubject = NULL;
GUID WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_DATA WinTrustData = {};
WinTrustData.cbStruct = sizeof(WinTrustData);
WinTrustData.pPolicyCallbackData = NULL;
WinTrustData.pSIPClientData = NULL;
WinTrustData.dwUIChoice = WTD_UI_NONE;
WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
WinTrustData.dwUnionChoice = WTD_CHOICE_FILE;
WinTrustData.dwStateAction = WTD_STATEACTION_VERIFY;
WinTrustData.hWVTStateData = NULL;
WinTrustData.pwszURLReference = NULL;
WinTrustData.dwUIContext = 0;
WinTrustData.pFile = &FileData;
LONG lStatus = WinVerifyTrust(
NULL,
&WVTPolicyGUID,
&WinTrustData);
switch (lStatus)
{
case ERROR_SUCCESS:
bResult = IsFileSignedByRazer(szFileName);
break;
case TRUST_E_NOSIGNATURE:
dwLastError = GetLastError();
if (TRUST_E_NOSIGNATURE == dwLastError ||
TRUST_E_SUBJECT_FORM_UNKNOWN == dwLastError ||
TRUST_E_PROVIDER_UNKNOWN == dwLastError)
{
}
else
{
}
bResult = FALSE;
break;
case TRUST_E_EXPLICIT_DISTRUST:
bResult = FALSE;
break;
case TRUST_E_SUBJECT_NOT_TRUSTED:
bResult = FALSE;
break;
case CRYPT_E_SECURITY_SETTINGS:
bResult = FALSE;
break;
default:
dwLastError = GetLastError();
bResult = FALSE;
break;
}
WinTrustData.dwStateAction = WTD_STATEACTION_CLOSE;
lStatus = WinVerifyTrust(
NULL,
&WVTPolicyGUID,
&WinTrustData);
return bResult;
}
BOOL VerifyModule(HMODULE hModule)
{
TCHAR szFilePath[MAX_PATH];
if(GetModuleFileNameEx(GetCurrentProcess(),
hModule,
szFilePath,
MAX_PATH) > 0)
{
if((IsValidPath(szFilePath) == TRUE) &&
(IsFileSigned(szFilePath) == TRUE))
{
return TRUE;
}
}
return FALSE;
}
CChromaSDKImpl::CChromaSDKImpl():
m_hModule(NULL),
m_hEvent(NULL)
{
}
CChromaSDKImpl::~CChromaSDKImpl()
{
}
void CChromaSDKImpl::Initialize()
{
if(m_hModule == NULL)
{
m_hModule = ::LoadLibrary(CHROMASDKDLL);
if(m_hModule != NULL)
{
if(VerifyModule(m_hModule) == FALSE)
{
::FreeLibrary(m_hModule);
m_hModule = NULL;
return;
}
_tcscpy_s(appInfo.
Title, 256, _T(
"Razer Chroma SDK Sample Application"));
_tcscpy_s(appInfo.
Description, 1024, _T(
"A sample application using Razer Chroma SDK"));
_tcscpy_s(appInfo.
Author.
Name, 256, _T(
"Razer"));
_tcscpy_s(appInfo.Author.
Contact, 256, _T(
"https://developer.razer.com/chroma"));
INITSDK
InitSDK = (INITSDK)::GetProcAddress(m_hModule,
"InitSDK");
{
{
CreateEffect = (CREATEEFFECT)::GetProcAddress(m_hModule,
"CreateEffect");
CreateMouseEffect = (CREATEMOUSEEFFECT)::GetProcAddress(m_hModule,
"CreateMouseEffect");
CreateMousematEffect = (CREATEMOUSEPADEFFECT)::GetProcAddress(m_hModule, "CreateMousepadEffect");
CreateKeypadEffect = (CREATEKEYPADEFFECT)::GetProcAddress(m_hModule,
"CreateKeypadEffect");
SetEffect = (SETEFFECT)GetProcAddress(m_hModule,
"SetEffect");
DeleteEffect = (DELETEEFFECT)GetProcAddress(m_hModule,
"DeleteEffect");
}
}
}
}
if(m_hEvent == NULL)
{
m_hEvent = ::CreateEvent(NULL, TRUE, FALSE, EVENT_NAME);
}
}
void CChromaSDKImpl::UnInitialize()
{
while(!g_Effects.empty())
{
auto iterator = g_Effects.begin();
for(int i=0; i<iterator->second.numEffects; i++)
{
{
}
}
g_Effects.erase(iterator);
};
if(m_hEvent != NULL)
{
::CloseHandle(m_hEvent);
m_hEvent = NULL;
}
if(m_hModule != NULL)
{
UNINIT
UnInit = (UNINIT)::GetProcAddress(m_hModule,
"UnInit");
{
{
}
}
::FreeLibrary(m_hModule);
m_hModule = NULL;
}
}
{
auto res =
CreateEffect(DeviceId, Effect, pParam, pEffectId);
{
TRACE(_T("Error = 0x%X\n"), res);
}
}
{
}
{
}
{
if(CreateMousematEffect == NULL) return;
CreateMousematEffect(Effect, pParam, pEffectId);
}
{
}
{
}
{
}
void CChromaSDKImpl::SetEffectImpl(
RZEFFECTID EffectId)
{
auto iterator = g_Effects.find(EffectId);
if(iterator != g_Effects.end())
{
if(iterator->second.repeat == FALSE)
{
HANDLE hThread = CreateThread(NULL, 0, Thread_RenderEffects, (LPVOID)&iterator->first, 0, NULL);
if(hThread != NULL)
{
CloseHandle(hThread);
}
}
else
{
HANDLE hThread = CreateThread(NULL, 0, Thread_RenderEffects, (LPVOID)&iterator->first, 0, NULL);
if(hThread != NULL)
{
iterator->second.thread = hThread;
}
}
}
else
{
}
}
void CChromaSDKImpl::DeleteEffectImpl(
RZEFFECTID EffectId)
{
auto iterator = g_Effects.find(EffectId);
if(iterator != g_Effects.end())
{
EFFECTDATATYPE EffectData = iterator->second;
for(int i=0; i<EffectData.numEffects; i++)
{
}
g_Effects.erase(iterator);
}
else
{
}
}
void CChromaSDKImpl::StopEffectImpl(
RZEFFECTID EffectId)
{
auto iterator = g_Effects.find(EffectId);
if(iterator != g_Effects.end())
{
if((iterator->second.repeat == TRUE) &&
(iterator->second.thread != NULL))
{
iterator->second.repeat = FALSE;
CloseHandle(iterator->second.thread);
iterator->second.thread = NULL;
}
}
}
void CChromaSDKImpl::CreateEffectGroup(
RZEFFECTID *pGroupEffectId, BOOL Repeat)
{
if(SUCCEEDED(::CoCreateGuid(&EffectId)))
{
EFFECTDATATYPE EffectData = {};
EffectData.numEffects = 0;
EffectData.repeat = Repeat;
g_Effects.insert(make_pair(EffectId, EffectData));
*pGroupEffectId = EffectId;
}
}
{
auto iterator = g_Effects.find(GroupEffectId);
if(iterator != g_Effects.end())
{
LONG lIndex = iterator->second.numEffects;
iterator->second.Effect[lIndex].id = EffectId;
iterator->second.Effect[lIndex].delay = DelayMS;
iterator->second.numEffects++;
}
}
#define RZRESULT_SUCCESS
Success.
Definition: RzErrors.h:19
RZRESULT CreateChromaLinkEffect(ChromaSDK::ChromaLink::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
RZRESULT CreateHeadsetEffect(ChromaSDK::Headset::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
RZRESULT CreateKeypadEffect(ChromaSDK::Keypad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
RZRESULT CreateKeyboardEffect(ChromaSDK::Keyboard::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
RZRESULT DeleteEffect(RZEFFECTID EffectId)
RZRESULT CreateEffect(RZDEVICEID DeviceId, ChromaSDK::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
RZRESULT SetEffect(RZEFFECTID EffectId)
RZRESULT InitSDK(ChromaSDK::APPINFOTYPE *pAppInfo)
RZRESULT CreateMouseEffect(ChromaSDK::Mouse::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
void * PRZPARAM
Generic data structure pointer.
Definition: RzChromaSDKTypes.h:20
GUID RZDEVICEID
Device identifier.
Definition: RzChromaSDKTypes.h:17
EFFECT_TYPE
Chroma generic effects. Note: Not all devices supported the listed effects.
Definition: RzChromaSDKTypes.h:47
LONG RZRESULT
Return result.
Definition: RzChromaSDKTypes.h:15
GUID RZEFFECTID
Effect identifier.
Definition: RzChromaSDKTypes.h:16
EFFECT_TYPE
Chroma Link effect types.
Definition: RzChromaSDKTypes.h:866
EFFECT_TYPE
Chroma headset effect types.
Definition: RzChromaSDKTypes.h:673
EFFECT_TYPE
Chroma keyboard effect types.
Definition: RzChromaSDKTypes.h:368
EFFECT_TYPE
Chroma keypad effect types.
Definition: RzChromaSDKTypes.h:789
EFFECT_TYPE
Chroma mouse effect types.
Definition: RzChromaSDKTypes.h:560
EFFECT_TYPE
Chroma mousepad effect types.
Definition: RzChromaSDKTypes.h:709
TCHAR Name[256]
Name of the developer/company.
Definition: RzChromaSDKTypes.h:38
TCHAR Contact[256]
Contact information.
Definition: RzChromaSDKTypes.h:39
Application information.
Definition: RzChromaSDKTypes.h:32
DWORD Category
1 = Utility. (To specifiy this is an utility application); 2 = Game. (To specifiy this is a game);
Definition: RzChromaSDKTypes.h:42
TCHAR Description[1024]
Definition: RzChromaSDKTypes.h:34
DWORD SupportedDevice
Keyboard = 0x01, Mouse = 0x02, Headset = 0x04, Mousepad = 0x08, Keypad = 0x10, ChromaLink = 0x20.
Definition: RzChromaSDKTypes.h:41
TCHAR Title[256]
Title of the application.
Definition: RzChromaSDKTypes.h:33