loaderIni.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. #include "main.h"
  2. #include "./loaderIni.h"
  3. #include "./service.h"
  4. #include "./ifc_wasabihelper.h"
  5. #include "./ifc_omservicehost.h"
  6. #include "./ifc_omstorage.h"
  7. #include "./ifc_omstoragehandler.h"
  8. #include "./ifc_omstoragehandlerenum.h"
  9. #include <shlwapi.h>
  10. #include <strsafe.h>
  11. #define OMS_GROUP "OnlineService"
  12. #define OMS_ID "id"
  13. #define OMS_NAME "name"
  14. #define OMS_URL "url"
  15. #define OMS_ICON "icon"
  16. #define OMS_FLAGS "flags"
  17. #define OMS_RATING "rating"
  18. #define OMS_VERSION "version"
  19. #define OMS_DESCRIPTION "description"
  20. #define OMS_AUTHORFIRST "authorFirst"
  21. #define OMS_AUTHORLAST "authorLast"
  22. #define OMS_PUBLISHED "publishedDate"
  23. #define OMS_UPDATED "updatedDate"
  24. #define OMS_THUMBNAIL "thumbnail"
  25. #define OMS_SCREENSHOT "screenshot"
  26. #define OMS_GENERATION "generation"
  27. typedef HRESULT (ifc_omservice::*SVCSTRGET)(LPWSTR, UINT);
  28. typedef HRESULT (ifc_omservice::*SVCUINTGET)(UINT*);
  29. typedef HRESULT (ifc_omservicedetails::*DETAILGET)(LPWSTR, UINT);
  30. #define WRITE_OBJECT_STR(__mofifiedFlag, __class, __getterType, __object, __getter, __key)\
  31. {if (0 != (ifc_omserviceeditor::##__mofifiedFlag & modified)) {\
  32. HRESULT r = WriteObjectStr<__class, __getterType>((__key), (__object), &##__class::##__getter);\
  33. if (FAILED(r)) {hr = E_FAIL;} else { saved |= ifc_omserviceeditor::##__mofifiedFlag; }}}
  34. #define WRITE_OBJECT_STR_FALLBACK(__mofifiedFlag, __class, __getterType, __object, __getter1, __getter2, __key)\
  35. {if (0 != (ifc_omserviceeditor::##__mofifiedFlag & modified)) {\
  36. HRESULT r = WriteObjectStr<__class, __getterType>((__key), (__object), &##__class::##__getter1);\
  37. if (S_FALSE == r) r = WriteObjectStr<__class, __getterType>((__key), (__object), &##__class::##__getter2);\
  38. if (FAILED(r)) {hr = E_FAIL;} else { saved |= ifc_omserviceeditor::##__mofifiedFlag; }}}
  39. #define WRITE_OBJECT_UINT(__mofifiedFlag, __class, __getterType, __object, __getter, __key, __writeFlags)\
  40. {if (0 != (ifc_omserviceeditor::##__mofifiedFlag & modified)) {\
  41. HRESULT r = WriteObjectUInt<__class, __getterType>((__key), (__object), &##__class::##__getter, __writeFlags);\
  42. if (FAILED(r)) {hr = E_FAIL;} else { saved |= ifc_omserviceeditor::##__mofifiedFlag; }}}
  43. #define WRITE_SERVICE_STR(__mofifiedFlag, __getter, __key) WRITE_OBJECT_STR(__mofifiedFlag, ifc_omservice, SVCSTRGET, service, __getter, __key)
  44. #define WRITE_SERVICE_STR_FALLBACK(__mofifiedFlag, __getter1, __getter2, __key) WRITE_OBJECT_STR_FALLBACK(__mofifiedFlag, ifc_omservice, SVCSTRGET, service, __getter1, __getter2, __key)
  45. #define WRITE_SERVICE_UINT(__mofifiedFlag, __getter, __key, __writeZero) WRITE_OBJECT_UINT(__mofifiedFlag, ifc_omservice, SVCUINTGET, service, __getter, __key, __writeZero)
  46. #define WRITE_DETAILS_STR(__mofifiedFlag, __getter, __key) WRITE_OBJECT_STR(__mofifiedFlag, ifc_omservicedetails, DETAILGET, details, __getter, __key)
  47. LoaderIni::LoaderIni()
  48. : bufferAnsi(NULL), bufferAnsiMax(0), buffer(NULL), bufferMax(0), handlerEnum(NULL)
  49. {
  50. memset(pathAnsi, 0, sizeof(pathAnsi));
  51. }
  52. LoaderIni::~LoaderIni()
  53. {
  54. //Plugin_FreeAnsiString(pathAnsi);
  55. Plugin_FreeAnsiString(bufferAnsi);
  56. Plugin_FreeString(buffer);
  57. if (NULL != handlerEnum)
  58. handlerEnum->Release();
  59. }
  60. HRESULT LoaderIni::Load(LPCWSTR pszAddress, ifc_omservicehost *host, ifc_omservice **serviceOut)
  61. {
  62. if (NULL == serviceOut)
  63. return E_POINTER;
  64. *serviceOut = NULL;
  65. HRESULT hr = MakeAnsiPath(pszAddress);
  66. if (FAILED(hr)) return hr;
  67. UINT id = ReadInt(OMS_ID, 0);
  68. if (0 == id) return E_UNEXPECTED;
  69. OmService *service;
  70. hr = OmService::CreateInstance(id, host, &service);
  71. if (FAILED(hr)) return hr;
  72. ifc_omserviceeditor *editor;
  73. if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEditor, (void**)&editor)))
  74. editor->BeginUpdate();
  75. else
  76. editor = NULL;
  77. service->SetAddress(pszAddress);
  78. #define READ_SERVICE_STR(__key, __putter)\
  79. { LPCSTR value; HRESULT r = ReadAnsi((__key), NULL, &value);\
  80. if (SUCCEEDED(r)) { if ('\0' != *value) r = service->##__putter((LPCWSTR)value, TRUE); }\
  81. if (FAILED(r)) hr = E_FAIL;}
  82. READ_SERVICE_STR(OMS_NAME, SetName);
  83. READ_SERVICE_STR(OMS_URL, SetUrl);
  84. READ_SERVICE_STR(OMS_ICON, SetIcon);
  85. UINT val = ReadInt(OMS_FLAGS, 0);
  86. if (0 != val) service->SetFlags(val, val & ~ifc_omservice::RuntimeFlagsMask);
  87. val = ReadInt(OMS_RATING, 0);
  88. if (0 != val) service->SetRating(val);
  89. val = ReadInt(OMS_VERSION, 0);
  90. if (0 != val) service->SetVersion(val);
  91. val = ReadInt(OMS_GENERATION, 0);
  92. if (0 != val) service->SetGeneration(val);
  93. READ_SERVICE_STR(OMS_DESCRIPTION, SetDescription);
  94. READ_SERVICE_STR(OMS_AUTHORFIRST, SetAuthorFirst);
  95. READ_SERVICE_STR(OMS_AUTHORLAST, SetAuthorLast);
  96. READ_SERVICE_STR(OMS_PUBLISHED, SetPublished);
  97. READ_SERVICE_STR(OMS_UPDATED, SetUpdated);
  98. READ_SERVICE_STR(OMS_THUMBNAIL, SetThumbnail);
  99. READ_SERVICE_STR(OMS_SCREENSHOT, SetScreenshot);
  100. if (NULL != handlerEnum)
  101. {
  102. handlerEnum->Reset();
  103. ifc_omstoragehandler *storageHandler;
  104. while (S_OK == handlerEnum->Next(1, &storageHandler, NULL))
  105. {
  106. LPCWSTR pszKey;
  107. if (SUCCEEDED(storageHandler->GetKey(&pszKey)))
  108. {
  109. if (SUCCEEDED(WideCharToAnsiBuffer(CP_UTF8, 0, pszKey, -1, NULL, NULL)))
  110. {
  111. LPCSTR keyAnsi = bufferAnsi;
  112. LPCSTR valueAnsi;
  113. if (SUCCEEDED(ReadAnsi(keyAnsi, NULL, &valueAnsi)) &&
  114. NULL != valueAnsi && L'\0' != *valueAnsi)
  115. {
  116. if (SUCCEEDED(MultiByteToBuffer(CP_UTF8, 0, valueAnsi, -1)))
  117. storageHandler->Invoke(service, pszKey, buffer);
  118. }
  119. }
  120. }
  121. storageHandler->Release();
  122. }
  123. }
  124. if (NULL != editor)
  125. {
  126. editor->SetModified(0, ((UINT)-1));
  127. editor->EndUpdate();
  128. editor->Release();
  129. }
  130. *serviceOut = service;
  131. return hr;
  132. }
  133. HRESULT LoaderIni::Reload(ifc_omservice *service)
  134. {
  135. if (NULL == service)
  136. return E_INVALIDARG;
  137. HRESULT hr = RequestBuffer(&buffer, &bufferMax, MAX_PATH * 2);
  138. if (FAILED(hr)) return hr;
  139. hr = service->GetAddress(buffer, bufferMax);
  140. if (FAILED(hr)) return hr;
  141. if (L'\0' == *buffer) return E_UNEXPECTED;
  142. hr = MakeAnsiPath(buffer);
  143. if (FAILED(hr)) return hr;
  144. UINT id = ReadInt(OMS_ID, 0);
  145. if (id != service->GetId()) return E_UNEXPECTED;
  146. ifc_omserviceeditor *editor;
  147. hr = service->QueryInterface(IFC_OmServiceEditor, (void**)&editor);
  148. if (SUCCEEDED(hr))
  149. {
  150. #define READ_EDITOR_STR(__key, __putter)\
  151. { LPCSTR value; HRESULT r = ReadAnsi((__key), NULL, &value);\
  152. if (SUCCEEDED(r)) { r = editor->##__putter((LPCWSTR)value, TRUE); }\
  153. if (FAILED(r)) hr = E_FAIL;}
  154. editor->BeginUpdate();
  155. READ_EDITOR_STR(OMS_NAME, SetName);
  156. READ_EDITOR_STR(OMS_URL, SetUrl);
  157. READ_EDITOR_STR(OMS_ICON, SetIcon);
  158. UINT val;
  159. val = ReadInt(OMS_FLAGS, 0);
  160. editor->SetFlags(val, val & ~ifc_omservice::RuntimeFlagsMask);
  161. val = ReadInt(OMS_RATING, 0);
  162. editor->SetRating(val);
  163. val = ReadInt(OMS_VERSION, 0);
  164. editor->SetVersion(val);
  165. val = ReadInt(OMS_GENERATION, 0);
  166. editor->SetGeneration(val);
  167. READ_EDITOR_STR(OMS_DESCRIPTION, SetDescription);
  168. READ_EDITOR_STR(OMS_AUTHORFIRST, SetAuthorFirst);
  169. READ_EDITOR_STR(OMS_AUTHORLAST, SetAuthorLast);
  170. READ_EDITOR_STR(OMS_PUBLISHED, SetPublished);
  171. READ_EDITOR_STR(OMS_UPDATED, SetUpdated);
  172. READ_EDITOR_STR(OMS_THUMBNAIL, SetThumbnail);
  173. READ_EDITOR_STR(OMS_SCREENSHOT, SetScreenshot);
  174. }
  175. else
  176. {
  177. editor = NULL;
  178. }
  179. if (NULL != handlerEnum)
  180. {
  181. handlerEnum->Reset();
  182. ifc_omstoragehandler *storageHandler;
  183. while (S_OK == handlerEnum->Next(1, &storageHandler, NULL))
  184. {
  185. LPCWSTR pszKey;
  186. if (SUCCEEDED(storageHandler->GetKey(&pszKey)))
  187. {
  188. if (SUCCEEDED(WideCharToAnsiBuffer(CP_UTF8, 0, pszKey, -1, NULL, NULL)))
  189. {
  190. LPCSTR keyAnsi = bufferAnsi;
  191. LPCSTR valueAnsi;
  192. if (SUCCEEDED(ReadAnsi(keyAnsi, NULL, &valueAnsi)) &&
  193. NULL != valueAnsi && L'\0' != *valueAnsi)
  194. {
  195. if (SUCCEEDED(MultiByteToBuffer(CP_UTF8, 0, valueAnsi, -1)))
  196. storageHandler->Invoke(service, pszKey, buffer);
  197. }
  198. }
  199. }
  200. storageHandler->Release();
  201. }
  202. }
  203. if (NULL != editor)
  204. {
  205. editor->EndUpdate();
  206. editor->Release();
  207. }
  208. return hr;
  209. }
  210. HRESULT LoaderIni::Save(ifc_omservice *service, UINT flags)
  211. {
  212. if(NULL == service)
  213. return E_INVALIDARG;
  214. HRESULT hr;
  215. BOOL generatedName;
  216. hr = RequestBuffer(&buffer, &bufferMax, MAX_PATH * 2);
  217. if (FAILED(hr)) return hr;
  218. hr = GetServicePath(service, buffer, bufferMax, &generatedName);
  219. if (FAILED(hr)) return hr;
  220. if (FALSE != generatedName)
  221. service->SetAddress(buffer);
  222. hr = MakeAnsiPath(buffer);
  223. if (FAILED(hr)) return hr;
  224. if (0 == (ifc_omstorage::saveModifiedOnly & flags))
  225. WritePrivateProfileSectionA(OMS_GROUP, NULL, pathAnsi);
  226. UINT modified = ((UINT)-1);
  227. UINT saved = 0;
  228. if (0 != (ifc_omstorage::saveModifiedOnly & flags))
  229. {
  230. ifc_omserviceeditor *editor;
  231. if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEditor, (void**)&editor)))
  232. {
  233. editor->GetModified(&modified);
  234. editor->Release();
  235. if (0 == modified)
  236. return S_FALSE;
  237. }
  238. }
  239. if (FAILED(WriteUint(OMS_ID, service->GetId(), flagWriteZero)))
  240. return E_FAIL;
  241. WRITE_SERVICE_STR(modifiedName, GetName, OMS_NAME);
  242. WRITE_SERVICE_STR_FALLBACK(modifiedUrl, GetUrlDirect, GetUrl, OMS_URL);
  243. WRITE_SERVICE_STR(modifiedIcon, GetIcon, OMS_ICON);
  244. if (0 != (ifc_omserviceeditor::modifiedFlags & modified))
  245. {
  246. UINT val;
  247. if (SUCCEEDED(service->GetFlags(&val)) && SUCCEEDED(WriteUint(OMS_FLAGS, val & ~ifc_omservice::RuntimeFlagsMask, flagHexMode)))
  248. saved |= ifc_omserviceeditor::modifiedFlags;
  249. }
  250. WRITE_SERVICE_UINT(modifiedRating, GetRating, OMS_RATING, flagWriteNormal);
  251. WRITE_SERVICE_UINT(modifiedVersion, GetVersion, OMS_VERSION, flagWriteNormal);
  252. WRITE_SERVICE_UINT(modifiedGeneration, GetGeneration, OMS_GENERATION, flagWriteNormal);
  253. ifc_omservicedetails *details;
  254. if (SUCCEEDED(service->QueryInterface(IFC_OmServiceDetails, (void**)&details)))
  255. {
  256. WRITE_DETAILS_STR(modifiedDescription, GetDescription, OMS_DESCRIPTION);
  257. WRITE_DETAILS_STR(modifiedAuthorFirst, GetAuthorFirst, OMS_AUTHORFIRST);
  258. WRITE_DETAILS_STR(modifiedAuthorLast, GetAuthorLast, OMS_AUTHORLAST);
  259. WRITE_DETAILS_STR(modifiedPublished, GetPublished, OMS_PUBLISHED);
  260. WRITE_DETAILS_STR(modifiedUpdated, GetUpdated, OMS_UPDATED);
  261. WRITE_DETAILS_STR(modifiedThumbnail, GetThumbnail, OMS_THUMBNAIL);
  262. WRITE_DETAILS_STR(modifiedScreenshot, GetScreenshot, OMS_SCREENSHOT);
  263. details->Release();
  264. }
  265. if (0 != (ifc_omstorage::saveClearModified & flags) && 0 != saved)
  266. {
  267. ifc_omserviceeditor *editor;
  268. if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEditor, (void**)&editor)))
  269. {
  270. editor->SetModified(0, saved);
  271. editor->Release();
  272. }
  273. }
  274. return hr;
  275. }
  276. HRESULT LoaderIni::RegisterHandlers(ifc_omstoragehandlerenum *enumerator)
  277. {
  278. if (NULL != handlerEnum)
  279. handlerEnum->Release();
  280. handlerEnum = enumerator;
  281. if (NULL != handlerEnum)
  282. handlerEnum->AddRef();
  283. return S_OK;
  284. }
  285. HRESULT LoaderIni::RequestAnsiBuffer(LPSTR *ppBuffer, UINT *pBufferMax, UINT requestSize)
  286. {
  287. if (*pBufferMax >= requestSize)
  288. return S_OK;
  289. UINT size = (0 != *pBufferMax) ? (*pBufferMax * 2) : 128;
  290. while (size < requestSize) size = size*2;
  291. Plugin_FreeAnsiString(*ppBuffer);
  292. *ppBuffer = Plugin_MallocAnsiString(size);
  293. if (NULL == *ppBuffer)
  294. {
  295. *ppBuffer = 0;
  296. *pBufferMax = 0;
  297. return E_OUTOFMEMORY;
  298. }
  299. *pBufferMax = size;
  300. return S_OK;
  301. }
  302. HRESULT LoaderIni::RequestBuffer(LPWSTR *ppBuffer, UINT *pBufferMax, UINT requestSize)
  303. {
  304. if (*pBufferMax >= requestSize)
  305. return S_OK;
  306. UINT size = (0 != *pBufferMax) ? (*pBufferMax * 2) : 128;
  307. while (size < requestSize) size = size*2;
  308. Plugin_FreeString(*ppBuffer);
  309. *ppBuffer = Plugin_MallocString(size);
  310. if (NULL == *ppBuffer)
  311. {
  312. *ppBuffer = 0;
  313. *pBufferMax = 0;
  314. return E_OUTOFMEMORY;
  315. }
  316. *pBufferMax = size;
  317. return S_OK;
  318. }
  319. HRESULT LoaderIni::MakeAnsiPath(LPCWSTR pszAddress)
  320. {
  321. BOOL fUsedDefaultChar = FALSE;
  322. WCHAR szShort[MAX_PATH] = {0};
  323. UINT cch = WideCharToMultiByte(CP_ACP, 0, pszAddress, -1, NULL, 0, NULL, &fUsedDefaultChar);
  324. if (0 == cch || FALSE != fUsedDefaultChar)
  325. {
  326. cch = GetShortPathName(pszAddress, szShort, ARRAYSIZE(szShort));
  327. if (0 != cch)
  328. {
  329. pszAddress = szShort;
  330. cch = WideCharToMultiByte(CP_ACP, 0, pszAddress, -1, NULL, 0, NULL, &fUsedDefaultChar);
  331. }
  332. if (0 == cch || FALSE != fUsedDefaultChar)
  333. {
  334. if (NULL != pathAnsi) *pathAnsi = L'\0';
  335. return E_FAIL;
  336. }
  337. }
  338. cch = WideCharToMultiByte(CP_ACP, 0, pszAddress, cch, pathAnsi, MAX_PATH, NULL, NULL);
  339. if (0 == cch)
  340. {
  341. DWORD errorCode = GetLastError();
  342. *pathAnsi = L'\0';
  343. return HRESULT_FROM_WIN32(errorCode);
  344. }
  345. pathAnsi[cch] = '\0';
  346. return S_OK;
  347. }
  348. HRESULT LoaderIni::GetServicePath(ifc_omservice *service, LPWSTR pszBuffer, UINT cchBufferMax, BOOL *fGenerated)
  349. {
  350. if (NULL == pszBuffer) return E_POINTER;
  351. pszBuffer[0] = L'\0';
  352. if (NULL == service) return E_INVALIDARG;
  353. HRESULT hr;
  354. WCHAR szPath[MAX_PATH * 2] = {0};
  355. hr = service->GetAddress(szPath, ARRAYSIZE(szPath));
  356. if (FAILED(hr)) return hr;
  357. ifc_omservicehost *host = NULL;
  358. ifc_omservicehostext *hostExt;
  359. if (SUCCEEDED(service->QueryInterface(IFC_OmServiceHostExt, (void**)&hostExt)))
  360. {
  361. if (FAILED(hostExt->GetHost(&host)))
  362. host = NULL;
  363. hostExt->Release();
  364. }
  365. BOOL nameGenerated = FALSE;
  366. if (L'\0' == *szPath)
  367. {
  368. hr = (NULL != host) ?
  369. host->GetDefaultName(service, szPath, ARRAYSIZE(szPath)) :
  370. StringCchPrintf(szPath, ARRAYSIZE(szPath), L"omService_{%010u}", service->GetId());
  371. if (L'\0' == *szPath)
  372. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  373. nameGenerated = TRUE;
  374. }
  375. if (SUCCEEDED(hr))
  376. {
  377. hr = Plugin_ResolveRelativePath(szPath, host, pszBuffer, cchBufferMax);
  378. if (SUCCEEDED(hr) && FALSE != nameGenerated)
  379. {
  380. LPWSTR pExt = PathFindExtension(pszBuffer);
  381. if (pExt != pszBuffer && L'.' == *pExt && SUCCEEDED(StringCchCopy(szPath, ARRAYSIZE(szPath), pExt)))
  382. {
  383. UINT pExtMax = cchBufferMax - (UINT)(pExt - pszBuffer);
  384. UINT attempt = 0;
  385. while (FALSE != PathFileExists(pszBuffer))
  386. {
  387. if (FAILED(StringCchPrintf(pExt, pExtMax, L"(%u)%s", ++attempt, szPath)))
  388. {
  389. StringCchCopy(pExt, pExtMax, szPath);
  390. break;
  391. }
  392. }
  393. }
  394. }
  395. if (SUCCEEDED(hr) && SUCCEEDED(StringCchCopy(szPath, ARRAYSIZE(szPath), pszBuffer)))
  396. {
  397. PathRemoveFileSpec(szPath);
  398. Plugin_EnsurePathExist(szPath);
  399. }
  400. }
  401. if (FAILED(hr))
  402. pszBuffer[0] = L'\0';
  403. if (NULL != host)
  404. host->Release();
  405. if (NULL != fGenerated)
  406. *fGenerated = nameGenerated;
  407. return hr;
  408. }
  409. HRESULT LoaderIni::WideCharToAnsiBuffer(UINT codePage, DWORD flags, LPCWSTR pszWideChar, INT cchWideChar, LPCSTR pDefaultChar, BOOL *pUsedDefaultChar)
  410. {
  411. UINT cch = WideCharToMultiByte(codePage, flags, pszWideChar, cchWideChar, NULL, 0, pDefaultChar, pUsedDefaultChar);
  412. if (0 == cch)
  413. {
  414. DWORD errorCode = GetLastError();
  415. return HRESULT_FROM_WIN32(errorCode);
  416. }
  417. HRESULT hr = RequestAnsiBuffer(&bufferAnsi, &bufferAnsiMax, cch);
  418. if (FAILED(hr)) return hr;
  419. if (0 == WideCharToMultiByte(codePage, flags, pszWideChar, cchWideChar, bufferAnsi, bufferAnsiMax, pDefaultChar, pUsedDefaultChar))
  420. {
  421. DWORD errorCode = GetLastError();
  422. return HRESULT_FROM_WIN32(errorCode);
  423. }
  424. return S_OK;
  425. }
  426. HRESULT LoaderIni::MultiByteToBuffer(UINT codePage, DWORD flags, LPCSTR pszMultiByte, INT cbMultiByte)
  427. {
  428. UINT cch = MultiByteToWideChar(codePage, flags, pszMultiByte, cbMultiByte, NULL, 0);
  429. if (0 == cch)
  430. {
  431. DWORD errorCode = GetLastError();
  432. return HRESULT_FROM_WIN32(errorCode);
  433. }
  434. HRESULT hr = RequestBuffer(&buffer, &bufferMax, cch);
  435. if (FAILED(hr)) return hr;
  436. if (0 == MultiByteToWideChar(codePage, flags, pszMultiByte, cbMultiByte, buffer, bufferMax))
  437. {
  438. DWORD errorCode = GetLastError();
  439. return HRESULT_FROM_WIN32(errorCode);
  440. }
  441. return S_OK;
  442. }
  443. HRESULT LoaderIni::Write(LPCSTR pszKey, LPCWSTR pszValue)
  444. {
  445. LPCSTR valueAnsi;
  446. if (NULL == pszValue) valueAnsi = NULL;
  447. else if (L'\0' == *pszValue) valueAnsi = '\0';
  448. else
  449. {
  450. HRESULT hr = WideCharToAnsiBuffer(CP_UTF8, 0, pszValue, -1, NULL, NULL);
  451. if (FAILED(hr)) return hr;
  452. valueAnsi = bufferAnsi;
  453. }
  454. return WriteAnsi(pszKey, valueAnsi);
  455. }
  456. HRESULT LoaderIni::WriteAnsi(LPCSTR pszKey, LPCSTR pszValue)
  457. {
  458. if (FALSE == WritePrivateProfileStringA(OMS_GROUP, pszKey, pszValue, pathAnsi))
  459. {
  460. DWORD errorCode = GetLastError();
  461. return HRESULT_FROM_WIN32(errorCode);
  462. }
  463. return S_OK;
  464. }
  465. HRESULT LoaderIni::WriteUint(LPCSTR pszKey, UINT uValue, UINT flags)
  466. {
  467. HRESULT hr;
  468. CHAR szBuffer[16] = {0}, *pVal;
  469. if (0 == uValue && 0 == (flagWriteZero & flags))
  470. {
  471. hr = S_OK;
  472. pVal = NULL;
  473. }
  474. else
  475. {
  476. hr = StringCchPrintfA(szBuffer, ARRAYSIZE(szBuffer), ((0 == (flagHexMode & flags)) ? "%u" : "0x%08X"), uValue);
  477. pVal = szBuffer;
  478. }
  479. if (SUCCEEDED(hr))
  480. {
  481. hr = WriteAnsi(pszKey, pVal);
  482. }
  483. return hr;
  484. }
  485. HRESULT LoaderIni::ReadAnsi(LPCSTR pszKey, LPCSTR pszDefault, LPCSTR *ppszValue)
  486. {
  487. HRESULT hr;
  488. if (NULL == bufferAnsi)
  489. {
  490. hr = RequestAnsiBuffer(&bufferAnsi, &bufferAnsiMax, 2);
  491. if (FAILED(hr))
  492. {
  493. *ppszValue = pszDefault;
  494. return hr;
  495. }
  496. }
  497. for(;;)
  498. {
  499. UINT copied = GetPrivateProfileStringA(OMS_GROUP, pszKey, pszDefault, bufferAnsi, bufferAnsiMax, pathAnsi);
  500. if (copied != bufferAnsiMax - 1) break;
  501. hr = RequestAnsiBuffer(&bufferAnsi, &bufferAnsiMax, bufferAnsiMax * 2);
  502. if (FAILED(hr))
  503. {
  504. *ppszValue = pszDefault;
  505. return hr;
  506. }
  507. }
  508. *ppszValue = bufferAnsi;
  509. return S_OK;
  510. }
  511. UINT LoaderIni::ReadInt(LPCSTR pszKey, UINT nDefault)
  512. {
  513. return GetPrivateProfileIntA(OMS_GROUP, pszKey, nDefault, pathAnsi);
  514. }
  515. template <class Object, class Getter>
  516. HRESULT LoaderIni::WriteObjectStr(LPCSTR pszKey, Object *object, Getter getter)
  517. {
  518. HRESULT hr;
  519. if (NULL == buffer)
  520. {
  521. hr = RequestBuffer(&buffer, &bufferMax, 256);
  522. if (FAILED(hr)) return hr;
  523. }
  524. for (;;)
  525. {
  526. hr = (object->*getter)(buffer, bufferMax);
  527. if (SUCCEEDED(hr)) break;
  528. if (E_NOTIMPL == hr) return S_FALSE;
  529. if (OMSVC_E_INSUFFICIENT_BUFFER != hr) return hr;
  530. hr = RequestBuffer(&buffer, &bufferMax, bufferMax * 2);
  531. if (FAILED(hr)) return hr;
  532. }
  533. return Write(pszKey, buffer);
  534. }
  535. template <class Object, class Getter>
  536. HRESULT LoaderIni::WriteObjectUInt(LPCSTR pszKey, Object *object, Getter getter, UINT flags)
  537. {
  538. UINT val;
  539. HRESULT hr = (object->*getter)(&val);
  540. if (FAILED(hr))
  541. {
  542. return (E_NOTIMPL == hr) ? S_FALSE : hr;
  543. }
  544. return WriteUint(pszKey, val, flags);
  545. }