aboutsummaryrefslogtreecommitdiff
path: root/Src/nu/ConfigCOM.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/nu/ConfigCOM.cpp')
-rw-r--r--Src/nu/ConfigCOM.cpp373
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