diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/nu/ConfigCOM.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/nu/ConfigCOM.cpp')
-rw-r--r-- | Src/nu/ConfigCOM.cpp | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/Src/nu/ConfigCOM.cpp b/Src/nu/ConfigCOM.cpp new file mode 100644 index 00000000..3c3dfea8 --- /dev/null +++ b/Src/nu/ConfigCOM.cpp @@ -0,0 +1,373 @@ +#include "ConfigCOM.h" +#include "AutoChar.h" +#include "../Winamp/JSAPI.h" + +#include <shlwapi.h> +#include <strsafe.h> + +#define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) + + +ConfigCOM::ConfigCOM() + : ref(1), index(31337), pathA(NULL), nameA(NULL) +{ +} + +ConfigCOM::~ConfigCOM() +{ + ConfigMap::iterator config_it; + for(config_it = config_map.begin(); config_it != config_map.end(); config_it++) + { + free(config_it->second); + } + config_map.clear(); + if (NULL != pathA) free(pathA); + if (NULL != nameA) free(nameA); +} + +HRESULT ConfigCOM::CreateInstanceW(const wchar_t *pszName, const char *pszPath, ConfigCOM **config) +{ + if (NULL == config) return E_POINTER; + *config = NULL; + + if (NULL == pszName) + return E_INVALIDARG; + + + *config = new ConfigCOM(); + if (NULL == *config) return E_OUTOFMEMORY; + + char *buffer = NULL; + int cbBuffer = WideCharToMultiByte(CP_UTF8, 0, pszName, -1, 0, 0, NULL, NULL); + if (0 != cbBuffer) + { + buffer = (char*)calloc(cbBuffer, sizeof(char)); + if (NULL != buffer && 0 == WideCharToMultiByte(CP_UTF8, 0, pszName, -1, buffer, cbBuffer, NULL, NULL)) + { + free(buffer); + buffer = NULL; + } + } + + if (NULL == buffer) + { + (*config)->Release(); + *config = NULL; + return E_OUTOFMEMORY; + } + + (*config)->nameA = buffer; + if (NULL != pszPath) + (*config)->SetPathA(pszPath); + return S_OK; + +} + +HRESULT ConfigCOM::CreateInstanceA(const char *pszName, const char *pszPath, ConfigCOM **config) +{ + if (NULL == config) return E_POINTER; + *config = NULL; + + if (NULL == pszName) + return E_INVALIDARG; + + + *config = new ConfigCOM(); + if (NULL == *config) return E_OUTOFMEMORY; + + char *nameA = _strdup(pszName); + if (NULL == nameA) + { + (*config)->Release(); + *config = NULL; + return E_OUTOFMEMORY; + } + + (*config)->nameA = nameA; + if (NULL != pszPath) + (*config)->SetPathA(pszPath); + + return S_OK; +} + +STDMETHODIMP_(ULONG) ConfigCOM::AddRef(void) +{ + return InterlockedIncrement((LONG*)&ref); +} + +STDMETHODIMP_(ULONG) ConfigCOM::Release(void) +{ + if (0 == ref) + return ref; + + LONG r = InterlockedDecrement((LONG*)&ref); + if (0 == r) + delete(this); + + return r; +} +STDMETHODIMP ConfigCOM::QueryInterface(REFIID riid, PVOID *ppvObject) +{ + if (!ppvObject) + return E_POINTER; + + else if (IsEqualIID(riid, IID_IDispatch)) + *ppvObject = (IDispatch *)this; + else if (IsEqualIID(riid, IID_IUnknown)) + *ppvObject = this; + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } + + AddRef(); + return S_OK; +} + +STDMETHODIMP ConfigCOM::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid) +{ + UNREFERENCED_PARAMETER(riid); + + bool unknowns = false; + for (unsigned int i = 0;i != cNames;i++) + { + bool found = false; + AutoChar item(rgszNames[i], CP_UTF8); + + ConfigMap::iterator config_it; + for(config_it = config_map.begin();config_it != config_map.end(); config_it++) + { + if (config_it->second && + CSTR_EQUAL == CompareStringA(lcid, NORM_IGNORECASE, config_it->second, -1, item, -1)) + { + found = true; + rgdispid[i] = config_it->first; + } + } + if (!found) // if they reference a config item, well by golly they want that config item. + { + config_map[++index] = _strdup(item); + rgdispid[i] = index; + } + + } + if (unknowns) + return DISP_E_UNKNOWNNAME; + + return S_OK; +} + +STDMETHODIMP ConfigCOM::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo) +{ + UNREFERENCED_PARAMETER(itinfo); + UNREFERENCED_PARAMETER(lcid); + UNREFERENCED_PARAMETER(pptinfo); + + return E_NOTIMPL; +} + +STDMETHODIMP ConfigCOM::GetTypeInfoCount(unsigned int FAR * pctinfo) +{ + UNREFERENCED_PARAMETER(pctinfo); + + return E_NOTIMPL; +} + + +STDMETHODIMP ConfigCOM::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr) +{ + UNREFERENCED_PARAMETER(riid); + UNREFERENCED_PARAMETER(lcid); + UNREFERENCED_PARAMETER(pexecinfo); + + ConfigMap::iterator config_it = config_map.find(dispid); + if (config_it == config_map.end()) + return DISP_E_MEMBERNOTFOUND; + + if (0 != (DISPATCH_PROPERTYPUT & wFlags)) + { + VARIANTARG *varArg; + JSAPI_VERIFY_PARAMCOUNT(pdispparams, 1); + + varArg = &pdispparams->rgvarg[0]; + switch(V_VT(varArg)) + { + case VT_BSTR: + WriteString(config_it->second, V_BSTR(varArg)); + break; + + case VT_BOOL: + { + BOOL boolVal; + switch(V_BOOL(varArg)) + { + case VARIANT_TRUE: + boolVal = TRUE; + break; + case VARIANT_FALSE: + boolVal = FALSE; + break; + default: + *puArgErr = 0; + return DISP_E_BADVARTYPE; + } + + WriteBool(config_it->second, boolVal); + } + break; + + case VT_I4: + WriteLong(config_it->second, V_I4(varArg)); + break; + default: + *puArgErr = 0; + return DISP_E_TYPEMISMATCH; + } + return S_OK; + } + + if (0 != (DISPATCH_PROPERTYGET & wFlags)) + { + JSAPI_VERIFY_PARAMCOUNT(pdispparams, 0); + if (NULL == pvarResult) + return DISP_E_PARAMNOTOPTIONAL; + + VariantInit(pvarResult); + BSTR tag = ReadBSTR(config_it->second, NULL); + if (NULL != tag) + { + V_VT(pvarResult) = VT_BSTR; + V_BSTR(pvarResult) = tag; + } + else + { + V_VT(pvarResult) = VT_NULL; + } + + return S_OK; + } + + return ResultFromScode(E_INVALIDARG); +} +BOOL ConfigCOM::WriteStringAnsi(const char *key, const char* string) +{ + return WritePrivateProfileStringA(nameA, key, string, pathA); +} +BOOL ConfigCOM::WriteString(const char *key, const wchar_t *string) +{ + AutoChar buffer(string, CP_UTF8); + return WriteStringAnsi(key, buffer); +} + +BOOL ConfigCOM::WriteBool(const char *key, BOOL value) +{ + return WriteStringAnsi(key, (FALSE != value) ? "true" : "false"); +} + +BOOL ConfigCOM::WriteLong(const char *key, long value) +{ + char item[64] = {0}; + if (FAILED(StringCchPrintfA(item, ARRAYSIZE(item), "%ld", value))) + return FALSE; + return WriteStringAnsi(key, item); +} + +DWORD ConfigCOM::ReadString(const char *key, const char *defaultVal, char *buffer, int bufferMax) +{ + return GetPrivateProfileStringA(nameA, key, defaultVal, buffer, bufferMax, pathA); +} + +LONG ConfigCOM::ReadLong(const char *key, long defaultVal) +{ + return GetPrivateProfileIntA(nameA, key, defaultVal, pathA); +} + +BOOL ConfigCOM::ReadBool(const char *key, BOOL defaultVal) +{ + char szBuffer[32] = {0}; + INT cchLen = ReadString(key, NULL, szBuffer, ARRAYSIZE(szBuffer)); + if (0 == cchLen) return defaultVal; + + if (1 == cchLen) + { + switch(*szBuffer) + { + case '0': + case 'n': + case 'f': + return FALSE; + case '1': + case 'y': + case 't': + return TRUE; + } + } + else + { + if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "yes", -1, szBuffer, cchLen) || + CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "true", -1, szBuffer, cchLen)) + { + return TRUE; + } + + if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "no", -1, szBuffer, cchLen) || + CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "false", -1, szBuffer, cchLen)) + { + return FALSE; + } + } + + INT v; + if (FALSE != StrToIntExA(szBuffer, STIF_SUPPORT_HEX, &v)) + return (0 != v); + + return defaultVal; +} + +BSTR ConfigCOM::ReadBSTR(const char *key, const wchar_t *defaultVal) +{ + char szBuffer[16384] = {0}; + + ReadString(key, "__emptee__", szBuffer, ARRAYSIZE(szBuffer)); + if (CSTR_EQUAL != CompareStringA(CSTR_INVARIANT, 0, szBuffer, -1, "__emptee__", -1)) + { + int size = MultiByteToWideChar(CP_UTF8, 0, szBuffer, -1, 0,0); + if (0 != size) + { + BSTR result; + result = SysAllocStringLen(0, size-1); + if (NULL == result) return NULL; + + if (0 != MultiByteToWideChar(CP_UTF8, 0, szBuffer, -1, result, size)) + return result; + + SysFreeString(result); + } + } + return (NULL != defaultVal) ? SysAllocString(defaultVal) : NULL; +} + +void ConfigCOM::SetPathA(const char *pszPath) +{ + if (NULL != pathA) + { + free(pathA); + pathA = NULL; + } + + if (NULL == pszPath) + { + pathA = NULL; + return; + } + + pathA = _strdup(pszPath); +} + + +BOOL ConfigCOM::IsEqual(const char *pszName) +{ + if (NULL == pszName) return FALSE; + return (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, nameA, -1, pszName, -1)); +}
\ No newline at end of file |