ConfigCOM.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. #include "ConfigCOM.h"
  2. #include "AutoChar.h"
  3. #include "../Winamp/JSAPI.h"
  4. #include <shlwapi.h>
  5. #include <strsafe.h>
  6. #define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
  7. ConfigCOM::ConfigCOM()
  8. : ref(1), index(31337), pathA(NULL), nameA(NULL)
  9. {
  10. }
  11. ConfigCOM::~ConfigCOM()
  12. {
  13. ConfigMap::iterator config_it;
  14. for(config_it = config_map.begin(); config_it != config_map.end(); config_it++)
  15. {
  16. free(config_it->second);
  17. }
  18. config_map.clear();
  19. if (NULL != pathA) free(pathA);
  20. if (NULL != nameA) free(nameA);
  21. }
  22. HRESULT ConfigCOM::CreateInstanceW(const wchar_t *pszName, const char *pszPath, ConfigCOM **config)
  23. {
  24. if (NULL == config) return E_POINTER;
  25. *config = NULL;
  26. if (NULL == pszName)
  27. return E_INVALIDARG;
  28. *config = new ConfigCOM();
  29. if (NULL == *config) return E_OUTOFMEMORY;
  30. char *buffer = NULL;
  31. int cbBuffer = WideCharToMultiByte(CP_UTF8, 0, pszName, -1, 0, 0, NULL, NULL);
  32. if (0 != cbBuffer)
  33. {
  34. buffer = (char*)calloc(cbBuffer, sizeof(char));
  35. if (NULL != buffer && 0 == WideCharToMultiByte(CP_UTF8, 0, pszName, -1, buffer, cbBuffer, NULL, NULL))
  36. {
  37. free(buffer);
  38. buffer = NULL;
  39. }
  40. }
  41. if (NULL == buffer)
  42. {
  43. (*config)->Release();
  44. *config = NULL;
  45. return E_OUTOFMEMORY;
  46. }
  47. (*config)->nameA = buffer;
  48. if (NULL != pszPath)
  49. (*config)->SetPathA(pszPath);
  50. return S_OK;
  51. }
  52. HRESULT ConfigCOM::CreateInstanceA(const char *pszName, const char *pszPath, ConfigCOM **config)
  53. {
  54. if (NULL == config) return E_POINTER;
  55. *config = NULL;
  56. if (NULL == pszName)
  57. return E_INVALIDARG;
  58. *config = new ConfigCOM();
  59. if (NULL == *config) return E_OUTOFMEMORY;
  60. char *nameA = _strdup(pszName);
  61. if (NULL == nameA)
  62. {
  63. (*config)->Release();
  64. *config = NULL;
  65. return E_OUTOFMEMORY;
  66. }
  67. (*config)->nameA = nameA;
  68. if (NULL != pszPath)
  69. (*config)->SetPathA(pszPath);
  70. return S_OK;
  71. }
  72. STDMETHODIMP_(ULONG) ConfigCOM::AddRef(void)
  73. {
  74. return InterlockedIncrement((LONG*)&ref);
  75. }
  76. STDMETHODIMP_(ULONG) ConfigCOM::Release(void)
  77. {
  78. if (0 == ref)
  79. return ref;
  80. LONG r = InterlockedDecrement((LONG*)&ref);
  81. if (0 == r)
  82. delete(this);
  83. return r;
  84. }
  85. STDMETHODIMP ConfigCOM::QueryInterface(REFIID riid, PVOID *ppvObject)
  86. {
  87. if (!ppvObject)
  88. return E_POINTER;
  89. else if (IsEqualIID(riid, IID_IDispatch))
  90. *ppvObject = (IDispatch *)this;
  91. else if (IsEqualIID(riid, IID_IUnknown))
  92. *ppvObject = this;
  93. else
  94. {
  95. *ppvObject = NULL;
  96. return E_NOINTERFACE;
  97. }
  98. AddRef();
  99. return S_OK;
  100. }
  101. STDMETHODIMP ConfigCOM::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
  102. {
  103. UNREFERENCED_PARAMETER(riid);
  104. bool unknowns = false;
  105. for (unsigned int i = 0;i != cNames;i++)
  106. {
  107. bool found = false;
  108. AutoChar item(rgszNames[i], CP_UTF8);
  109. ConfigMap::iterator config_it;
  110. for(config_it = config_map.begin();config_it != config_map.end(); config_it++)
  111. {
  112. if (config_it->second &&
  113. CSTR_EQUAL == CompareStringA(lcid, NORM_IGNORECASE, config_it->second, -1, item, -1))
  114. {
  115. found = true;
  116. rgdispid[i] = config_it->first;
  117. }
  118. }
  119. if (!found) // if they reference a config item, well by golly they want that config item.
  120. {
  121. config_map[++index] = _strdup(item);
  122. rgdispid[i] = index;
  123. }
  124. }
  125. if (unknowns)
  126. return DISP_E_UNKNOWNNAME;
  127. return S_OK;
  128. }
  129. STDMETHODIMP ConfigCOM::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  130. {
  131. UNREFERENCED_PARAMETER(itinfo);
  132. UNREFERENCED_PARAMETER(lcid);
  133. UNREFERENCED_PARAMETER(pptinfo);
  134. return E_NOTIMPL;
  135. }
  136. STDMETHODIMP ConfigCOM::GetTypeInfoCount(unsigned int FAR * pctinfo)
  137. {
  138. UNREFERENCED_PARAMETER(pctinfo);
  139. return E_NOTIMPL;
  140. }
  141. STDMETHODIMP ConfigCOM::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
  142. {
  143. UNREFERENCED_PARAMETER(riid);
  144. UNREFERENCED_PARAMETER(lcid);
  145. UNREFERENCED_PARAMETER(pexecinfo);
  146. ConfigMap::iterator config_it = config_map.find(dispid);
  147. if (config_it == config_map.end())
  148. return DISP_E_MEMBERNOTFOUND;
  149. if (0 != (DISPATCH_PROPERTYPUT & wFlags))
  150. {
  151. VARIANTARG *varArg;
  152. JSAPI_VERIFY_PARAMCOUNT(pdispparams, 1);
  153. varArg = &pdispparams->rgvarg[0];
  154. switch(V_VT(varArg))
  155. {
  156. case VT_BSTR:
  157. WriteString(config_it->second, V_BSTR(varArg));
  158. break;
  159. case VT_BOOL:
  160. {
  161. BOOL boolVal;
  162. switch(V_BOOL(varArg))
  163. {
  164. case VARIANT_TRUE:
  165. boolVal = TRUE;
  166. break;
  167. case VARIANT_FALSE:
  168. boolVal = FALSE;
  169. break;
  170. default:
  171. *puArgErr = 0;
  172. return DISP_E_BADVARTYPE;
  173. }
  174. WriteBool(config_it->second, boolVal);
  175. }
  176. break;
  177. case VT_I4:
  178. WriteLong(config_it->second, V_I4(varArg));
  179. break;
  180. default:
  181. *puArgErr = 0;
  182. return DISP_E_TYPEMISMATCH;
  183. }
  184. return S_OK;
  185. }
  186. if (0 != (DISPATCH_PROPERTYGET & wFlags))
  187. {
  188. JSAPI_VERIFY_PARAMCOUNT(pdispparams, 0);
  189. if (NULL == pvarResult)
  190. return DISP_E_PARAMNOTOPTIONAL;
  191. VariantInit(pvarResult);
  192. BSTR tag = ReadBSTR(config_it->second, NULL);
  193. if (NULL != tag)
  194. {
  195. V_VT(pvarResult) = VT_BSTR;
  196. V_BSTR(pvarResult) = tag;
  197. }
  198. else
  199. {
  200. V_VT(pvarResult) = VT_NULL;
  201. }
  202. return S_OK;
  203. }
  204. return ResultFromScode(E_INVALIDARG);
  205. }
  206. BOOL ConfigCOM::WriteStringAnsi(const char *key, const char* string)
  207. {
  208. return WritePrivateProfileStringA(nameA, key, string, pathA);
  209. }
  210. BOOL ConfigCOM::WriteString(const char *key, const wchar_t *string)
  211. {
  212. AutoChar buffer(string, CP_UTF8);
  213. return WriteStringAnsi(key, buffer);
  214. }
  215. BOOL ConfigCOM::WriteBool(const char *key, BOOL value)
  216. {
  217. return WriteStringAnsi(key, (FALSE != value) ? "true" : "false");
  218. }
  219. BOOL ConfigCOM::WriteLong(const char *key, long value)
  220. {
  221. char item[64] = {0};
  222. if (FAILED(StringCchPrintfA(item, ARRAYSIZE(item), "%ld", value)))
  223. return FALSE;
  224. return WriteStringAnsi(key, item);
  225. }
  226. DWORD ConfigCOM::ReadString(const char *key, const char *defaultVal, char *buffer, int bufferMax)
  227. {
  228. return GetPrivateProfileStringA(nameA, key, defaultVal, buffer, bufferMax, pathA);
  229. }
  230. LONG ConfigCOM::ReadLong(const char *key, long defaultVal)
  231. {
  232. return GetPrivateProfileIntA(nameA, key, defaultVal, pathA);
  233. }
  234. BOOL ConfigCOM::ReadBool(const char *key, BOOL defaultVal)
  235. {
  236. char szBuffer[32] = {0};
  237. INT cchLen = ReadString(key, NULL, szBuffer, ARRAYSIZE(szBuffer));
  238. if (0 == cchLen) return defaultVal;
  239. if (1 == cchLen)
  240. {
  241. switch(*szBuffer)
  242. {
  243. case '0':
  244. case 'n':
  245. case 'f':
  246. return FALSE;
  247. case '1':
  248. case 'y':
  249. case 't':
  250. return TRUE;
  251. }
  252. }
  253. else
  254. {
  255. if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "yes", -1, szBuffer, cchLen) ||
  256. CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "true", -1, szBuffer, cchLen))
  257. {
  258. return TRUE;
  259. }
  260. if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "no", -1, szBuffer, cchLen) ||
  261. CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "false", -1, szBuffer, cchLen))
  262. {
  263. return FALSE;
  264. }
  265. }
  266. INT v;
  267. if (FALSE != StrToIntExA(szBuffer, STIF_SUPPORT_HEX, &v))
  268. return (0 != v);
  269. return defaultVal;
  270. }
  271. BSTR ConfigCOM::ReadBSTR(const char *key, const wchar_t *defaultVal)
  272. {
  273. char szBuffer[16384] = {0};
  274. ReadString(key, "__emptee__", szBuffer, ARRAYSIZE(szBuffer));
  275. if (CSTR_EQUAL != CompareStringA(CSTR_INVARIANT, 0, szBuffer, -1, "__emptee__", -1))
  276. {
  277. int size = MultiByteToWideChar(CP_UTF8, 0, szBuffer, -1, 0,0);
  278. if (0 != size)
  279. {
  280. BSTR result;
  281. result = SysAllocStringLen(0, size-1);
  282. if (NULL == result) return NULL;
  283. if (0 != MultiByteToWideChar(CP_UTF8, 0, szBuffer, -1, result, size))
  284. return result;
  285. SysFreeString(result);
  286. }
  287. }
  288. return (NULL != defaultVal) ? SysAllocString(defaultVal) : NULL;
  289. }
  290. void ConfigCOM::SetPathA(const char *pszPath)
  291. {
  292. if (NULL != pathA)
  293. {
  294. free(pathA);
  295. pathA = NULL;
  296. }
  297. if (NULL == pszPath)
  298. {
  299. pathA = NULL;
  300. return;
  301. }
  302. pathA = _strdup(pszPath);
  303. }
  304. BOOL ConfigCOM::IsEqual(const char *pszName)
  305. {
  306. if (NULL == pszName) return FALSE;
  307. return (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, 0, nameA, -1, pszName, -1));
  308. }