Razer Chroma SDK  v4.1
Razer Chroma SDK C++ Documentation
ChromaSDKImpl.cpp
#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;
typedef RZRESULT (*INITSDK)(APPINFOTYPE * pAppInfo);
typedef RZRESULT (*UNINIT)(void);
typedef RZRESULT (*CREATEEFFECT)(RZDEVICEID DeviceId, ChromaSDK::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId);
typedef RZRESULT (*CREATEKEYBOARDEFFECT)(ChromaSDK::Keyboard::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId);
typedef RZRESULT (*CREATEHEADSETEFFECT)(ChromaSDK::Headset::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId);
typedef RZRESULT (*CREATEMOUSEPADEFFECT)(ChromaSDK::Mousepad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId);
typedef RZRESULT (*CREATEMOUSEEFFECT)(ChromaSDK::Mouse::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId);
typedef RZRESULT (*CREATEKEYPADEFFECT)(ChromaSDK::Keypad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId);
typedef RZRESULT (*CREATECHROMALINKEFFECT)(ChromaSDK::ChromaLink::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId);
typedef RZRESULT (*SETEFFECT)(RZEFFECTID EffectId);
typedef RZRESULT (*DELETEEFFECT)(RZEFFECTID EffectId);
CREATEEFFECT CreateEffect = NULL;
CREATEKEYBOARDEFFECT CreateKeyboardEffect = NULL;
CREATEMOUSEEFFECT CreateMouseEffect = NULL;
CREATEHEADSETEFFECT CreateHeadsetEffect = NULL;
CREATEMOUSEPADEFFECT CreateMousematEffect = NULL;
CREATEKEYPADEFFECT CreateKeypadEffect = NULL;
CREATECHROMALINKEFFECT CreateChromaLinkEffect = NULL;
SETEFFECT SetEffect = NULL;
DELETEEFFECT DeleteEffect = 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)
{
RZEFFECTID *pEffectId = (RZEFFECTID*)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();
SetEffect(pEffectData->Effect[i].id);
Sleep(pEffectData->Effect[i].delay);
FrameControl.End();
}
}
else
{
while(pEffectData->repeat)
{
for(int i=0; i<pEffectData->numEffects; i++)
{
FrameControl.Begin();
SetEffect(pEffectData->Effect[i].id);
Sleep(pEffectData->Effect[i].delay);
FrameControl.End();
}
};
}
}
return 0;
}
// Source: https://docs.microsoft.com/en-us/windows/desktop/seccrypto/example-c-program--verifying-the-signature-of-a-pe-file
// Source: https://support.microsoft.com/en-us/help/323809/how-to-get-information-from-authenticode-signed-executables
BOOL IsValidPath(PTCHAR szFileName)
{
BOOL bResult = FALSE;
// Get the module name
TCHAR szModuleName[MAX_PATH] = L"";
_tcscpy_s(szModuleName, MAX_PATH, szFileName);
PathStripPath(szModuleName);
// Verify the path of the module
// Below are valid paths
// Windows/System32
// Windows/SysWOW64
// Program Files/Razer Chroma SDK/bin
// Program Files (x86)/Razer Chroma SDK/bin
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;
}
// Caller to free memory by calling LocalFree(*ppCertInfo)
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;
// Query for the data size
if (TRUE == CryptMsgGetParam(
hMsg,
CMSG_SIGNER_CERT_INFO_PARAM,
0,
NULL,
&cbData))
{
// Allocate memory for certificate information.
*ppCertInfo = LocalAlloc(LPTR, cbData);
if (*ppCertInfo != NULL)
{
// Get the certificate information
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)
{
// Compare the certificates
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;
/*
WVTPolicyGUID specifies the policy to apply on the file
WINTRUST_ACTION_GENERIC_VERIFY_V2 policy checks:
1) The certificate used to sign the file chains up to a root
certificate located in the trusted root certificate store. This
implies that the identity of the publisher has been verified by
a certification authority.
2) In cases where user interface is displayed (which this example
does not do), WinVerifyTrust will check for whether the
end entity certificate is stored in the trusted publisher store,
implying that the user trusts content from this publisher.
3) The end entity certificate has sufficient permission to sign
code, as indicated by the presence of a code signing EKU or no
EKU.
*/
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;
// WinVerifyTrust verifies signatures as specified by the GUID
// and Wintrust_Data.
LONG lStatus = WinVerifyTrust(
NULL,
&WVTPolicyGUID,
&WinTrustData);
switch (lStatus)
{
case ERROR_SUCCESS:
/*
Signed file:
- Hash that represents the subject is trusted.
- Trusted publisher without any verification errors.
- UI was disabled in dwUIChoice. No publisher or
time stamp chain errors.
- UI was enabled in dwUIChoice and the user clicked
"Yes" when asked to install and run the signed
subject.
*/
bResult = IsFileSignedByRazer(szFileName);
break;
case TRUST_E_NOSIGNATURE:
// The file was not signed or had a signature
// that was not valid.
// Get the reason for no signature.
dwLastError = GetLastError();
if (TRUST_E_NOSIGNATURE == dwLastError ||
TRUST_E_SUBJECT_FORM_UNKNOWN == dwLastError ||
TRUST_E_PROVIDER_UNKNOWN == dwLastError)
{
// The file was not signed.
}
else
{
// The signature was not valid or there was an error
// opening the file.
}
bResult = FALSE;
break;
case TRUST_E_EXPLICIT_DISTRUST:
// The hash that represents the subject or the publisher
// is not allowed by the admin or user.
bResult = FALSE;
break;
case TRUST_E_SUBJECT_NOT_TRUSTED:
// The user clicked "No" when asked to install and run.
bResult = FALSE;
break;
case CRYPT_E_SECURITY_SETTINGS:
/*
The hash that represents the subject or the publisher
was not explicitly trusted by the admin and the
admin policy has disabled user trust. No signature,
publisher or time stamp errors.
*/
bResult = FALSE;
break;
default:
// The UI was disabled in dwUIChoice or the admin policy
// has disabled user trust. lStatus contains the
// publisher or time stamp chain error.
dwLastError = GetLastError();
bResult = FALSE;
break;
}
// Any hWVTStateData must be released by a call with close.
WinTrustData.dwStateAction = WTD_STATEACTION_CLOSE;
lStatus = WinVerifyTrust(
NULL,
&WVTPolicyGUID,
&WinTrustData);
return bResult;
}
// This is "not" a foolproof method to verify "RzChromaSDK.dll" authenticity.
// There are other more appropriate methods but this is just a reference.
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::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 m_hModule is NULL, most likely Synapse's "CHROMA CONNECT" module isn't install. Or "RzChromaSDK.dll" isn't found in any of the system path defined in PATH system variable.
{
if(VerifyModule(m_hModule) == FALSE)
{
::FreeLibrary(m_hModule);
m_hModule = NULL;
return;
}
ChromaSDK::APPINFOTYPE appInfo = {};
_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"));
//appInfo.SupportedDevice =
// 0x01 | // Keyboards
// 0x02 | // Mice
// 0x04 | // Headset
// 0x08 | // Mousepads
// 0x10 | // Keypads
// 0x20; // ChromaLink devices
appInfo.SupportedDevice = (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20);
// appInfo.Category =
// 1 = Utility. (To specifiy this is an utility application)
// 2 = Game. (To specifiy this is a game);
appInfo.Category = 1;
INITSDK InitSDK = (INITSDK)::GetProcAddress(m_hModule, "InitSDK");
if(InitSDK != NULL)
{
RZRESULT rzResult = InitSDK(&appInfo);
if(rzResult == RZRESULT_SUCCESS)
{
CreateEffect = (CREATEEFFECT)::GetProcAddress(m_hModule, "CreateEffect");
CreateKeyboardEffect = (CREATEKEYBOARDEFFECT)::GetProcAddress(m_hModule, "CreateKeyboardEffect");
CreateMouseEffect = (CREATEMOUSEEFFECT)::GetProcAddress(m_hModule, "CreateMouseEffect");
CreateMousematEffect = (CREATEMOUSEPADEFFECT)::GetProcAddress(m_hModule, "CreateMousepadEffect");
CreateKeypadEffect = (CREATEKEYPADEFFECT)::GetProcAddress(m_hModule, "CreateKeypadEffect");
CreateHeadsetEffect = (CREATEHEADSETEFFECT)::GetProcAddress(m_hModule, "CreateHeadsetEffect");
CreateChromaLinkEffect = (CREATECHROMALINKEFFECT)::GetProcAddress(m_hModule, "CreateChromaLinkEffect");
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()
{
// Free memeory
while(!g_Effects.empty())
{
auto iterator = g_Effects.begin();
for(int i=0; i<iterator->second.numEffects; i++)
{
if(DeleteEffect != NULL)
{
DeleteEffect(iterator->second.Effect[i].id);
}
}
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");
if(UnInit != NULL)
{
RZRESULT rzResult = UnInit();
if(rzResult != RZRESULT_SUCCESS)
{
// Some error here
}
}
::FreeLibrary(m_hModule);
m_hModule = NULL;
}
}
void CChromaSDKImpl::CreateEffectImpl(RZDEVICEID DeviceId, ChromaSDK::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
{
if(CreateEffect == NULL) return;
auto res = CreateEffect(DeviceId, Effect, pParam, pEffectId);
if (res != RZRESULT_SUCCESS)
{
TRACE(_T("Error = 0x%X\n"), res);
}
}
void CChromaSDKImpl::CreateKeyboardEffectImpl(ChromaSDK::Keyboard::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
{
if(CreateKeyboardEffect == NULL) return;
CreateKeyboardEffect(Effect, pParam, pEffectId);
}
void CChromaSDKImpl::CreateMouseEffectImpl(ChromaSDK::Mouse::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
{
if(CreateMouseEffect == NULL) return;
CreateMouseEffect(Effect, pParam, pEffectId);
}
void CChromaSDKImpl::CreateMousematEffectImpl(ChromaSDK::Mousepad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
{
if(CreateMousematEffect == NULL) return;
CreateMousematEffect(Effect, pParam, pEffectId);
}
void CChromaSDKImpl::CreateKeypadEffectImpl(ChromaSDK::Keypad::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
{
if(CreateKeypadEffect == NULL) return;
CreateKeypadEffect(Effect, pParam, pEffectId);
}
void CChromaSDKImpl::CreateHeadsetEffectImpl(ChromaSDK::Headset::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
{
if(CreateHeadsetEffect == NULL) return;
CreateHeadsetEffect(Effect, pParam, pEffectId);
}
void CChromaSDKImpl::CreateChromaLinkEffectImpl(ChromaSDK::ChromaLink::EFFECT_TYPE Effect, PRZPARAM pParam, RZEFFECTID *pEffectId)
{
if(CreateChromaLinkEffect == NULL) return;
CreateChromaLinkEffect(Effect, pParam, pEffectId);
}
void CChromaSDKImpl::SetEffectImpl(RZEFFECTID EffectId)
{
if(SetEffect == NULL) return;
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
{
if(SetEffect == NULL) return;
SetEffect(EffectId);
}
}
void CChromaSDKImpl::DeleteEffectImpl(RZEFFECTID EffectId)
{
if(DeleteEffect == NULL) return;
auto iterator = g_Effects.find(EffectId);
if(iterator != g_Effects.end())
{
EFFECTDATATYPE EffectData = iterator->second;
for(int i=0; i<EffectData.numEffects; i++)
{
DeleteEffect(EffectData.Effect[i].id);
}
g_Effects.erase(iterator);
}
else
{
if(DeleteEffect == NULL) return;
DeleteEffect(EffectId);
}
}
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)
{
RZEFFECTID EffectId = GUID_NULL;
if(SUCCEEDED(::CoCreateGuid(&EffectId)))
{
EFFECTDATATYPE EffectData = {};
EffectData.numEffects = 0;
EffectData.repeat = Repeat;
g_Effects.insert(make_pair(EffectId, EffectData));
*pGroupEffectId = EffectId;
}
}
void CChromaSDKImpl::AddToGroup(RZEFFECTID GroupEffectId, RZEFFECTID EffectId, LONG DelayMS)
{
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 UnInit(void)
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 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