setupLog.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. #include "./setupLog.h"
  2. #include "../common.h"
  3. #include "../api__ml_online.h"
  4. #include "../config.h"
  5. #include "../../nu/trace.h"
  6. #include <ifc_omservice.h>
  7. #include <ifc_omwebstorage.h>
  8. #include <ifc_omstorageasync.h>
  9. #include <shlwapi.h>
  10. #include <strsafe.h>
  11. #define SETUPLOG_SEPARATOR ','
  12. #define SETUPLOG_SECTION "Setup"
  13. #define SETUPLOG_KEY_SUBSCRIBED "subscribed"
  14. #define SETUPLOG_KEY_UNSUBSCRIBED "unsubscribed"
  15. struct LOGPARSERPARAM
  16. {
  17. LOGPARSERPARAM() : instance(NULL), operation(0) {}
  18. SetupLog *instance;
  19. UINT operation;
  20. };
  21. static size_t SetupLog_GetMaxServiceIdCount(SetupLog::ServiceMap *serviceMap)
  22. {
  23. SetupLog::ServiceMap::iterator it;
  24. size_t c1 = 0, c2 = 0;
  25. for (it = serviceMap->begin(); it != serviceMap->end(); it++)
  26. {
  27. switch(it->second)
  28. {
  29. case SetupLog::opServiceAdded:
  30. c1++;
  31. break;
  32. case SetupLog::opServiceRemoved:
  33. c2++;
  34. break;
  35. }
  36. }
  37. return (c1 > c2) ? c1 : c2;
  38. }
  39. static HRESULT SetupLog_FormatServiceId(SetupLog::ServiceMap *serviceMap, INT operation, LPSTR pszBuffer, size_t cchBufferMax)
  40. {
  41. if (NULL == pszBuffer)
  42. return E_INVALIDARG;
  43. *pszBuffer = '\0';
  44. if (NULL == serviceMap)
  45. return S_OK;
  46. HRESULT hr = S_OK;
  47. size_t remaining = cchBufferMax;
  48. LPSTR cursor = pszBuffer;
  49. SetupLog::ServiceMap::iterator it;
  50. const char format[] = { SETUPLOG_SEPARATOR, '%', 'u', '\0'};
  51. for (it = serviceMap->begin(); it != serviceMap->end() && SUCCEEDED(hr); it++)
  52. {
  53. if (it->second == operation)
  54. {
  55. hr = StringCchPrintfExA(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
  56. ((cursor == pszBuffer) ? (format + 1) : format), it->first);
  57. }
  58. }
  59. return hr;
  60. }
  61. static LPCSTR SetupLog_GetOperationKey(UINT operation)
  62. {
  63. switch(operation)
  64. {
  65. case SetupLog::opServiceAdded: return SETUPLOG_KEY_SUBSCRIBED;
  66. case SetupLog::opServiceRemoved: return SETUPLOG_KEY_UNSUBSCRIBED;
  67. }
  68. return NULL;
  69. }
  70. static LPCWSTR SetupLog_GetOperationAction(UINT operation)
  71. {
  72. switch(operation)
  73. {
  74. case SetupLog::opServiceAdded: return L"add";
  75. case SetupLog::opServiceRemoved: return L"remove";
  76. }
  77. return NULL;
  78. }
  79. static BOOL SetupLog_WriteOperationLog(UINT operation, LPCSTR pszValue)
  80. {
  81. LPCSTR pszKey = SetupLog_GetOperationKey(operation);
  82. if (NULL == pszKey) return FALSE;
  83. return Config_WriteStr(SETUPLOG_SECTION, pszKey, pszValue);
  84. }
  85. static HRESULT SetupLog_ReadOperationLog(UINT operation, LPSTR pszBuffer, UINT cchBufferMax, UINT *cchReaded)
  86. {
  87. LPCSTR pszKey = SetupLog_GetOperationKey(operation);
  88. if (NULL == pszKey) return E_INVALIDARG;
  89. DWORD readed = Config_ReadStr(SETUPLOG_SECTION, pszKey, NULL, pszBuffer, cchBufferMax);
  90. if (NULL != cchReaded)
  91. {
  92. *cchReaded = readed;
  93. }
  94. return S_OK;
  95. }
  96. SetupLog::SetupLog() : ref(1)
  97. {
  98. }
  99. SetupLog::~SetupLog()
  100. {
  101. }
  102. SetupLog *SetupLog::Open()
  103. {
  104. SetupLog *instance = new SetupLog();
  105. if (NULL == instance) return NULL;
  106. INT cchBuffer = 32000;
  107. LPSTR buffer = Plugin_MallocAnsiString(cchBuffer);
  108. if (NULL == buffer)
  109. {
  110. instance->Release();
  111. return NULL;
  112. }
  113. UINT cchReaded = 0;
  114. const UINT szOperations[] = { opServiceAdded,
  115. opServiceRemoved, };
  116. UINT serviceId;
  117. for (INT i = 0; i < ARRAYSIZE(szOperations); i++)
  118. {
  119. if (SUCCEEDED(SetupLog_ReadOperationLog(szOperations[i], buffer, cchBuffer, &cchReaded)) && cchReaded > 0)
  120. {
  121. LPSTR cursor = buffer;
  122. LPSTR block = cursor;
  123. for(;;)
  124. {
  125. if (SETUPLOG_SEPARATOR == *cursor || '\0' == *cursor)
  126. {
  127. while (' ' == *block && block < cursor) block++;
  128. if (block < cursor &&
  129. FALSE != StrToIntExA(block, STIF_SUPPORT_HEX, (INT*)&serviceId) &&
  130. 0 != serviceId)
  131. {
  132. instance->LogServiceById(serviceId, szOperations[i]);
  133. }
  134. if ('\0' == *cursor)
  135. break;
  136. cursor++;
  137. block = cursor;
  138. }
  139. else
  140. {
  141. cursor++;
  142. }
  143. }
  144. }
  145. }
  146. Plugin_FreeAnsiString(buffer);
  147. return instance;
  148. }
  149. ULONG SetupLog::AddRef()
  150. {
  151. return InterlockedIncrement((LONG*)&ref);
  152. }
  153. ULONG SetupLog::Release()
  154. {
  155. if (0 == ref)
  156. return ref;
  157. LONG r = InterlockedDecrement((LONG*)&ref);
  158. if (0 == r)
  159. delete(this);
  160. return r;
  161. }
  162. BOOL SetupLog::IsOperationSupported(UINT operation)
  163. {
  164. switch(operation)
  165. {
  166. case SetupLog::opServiceAdded:
  167. case SetupLog::opServiceRemoved:
  168. return TRUE;
  169. }
  170. return FALSE;
  171. }
  172. HRESULT SetupLog::LogServiceById(UINT serviceUid, UINT operation)
  173. {
  174. if (0 == serviceUid || FALSE == IsOperationSupported(operation))
  175. return E_INVALIDARG;
  176. serviceMap[serviceUid] = operation;
  177. return S_OK;
  178. }
  179. HRESULT SetupLog::LogService(ifc_omservice *service, UINT operation)
  180. {
  181. if (NULL == service || !IsOperationSupported(operation))
  182. return E_INVALIDARG;
  183. return LogServiceById(service->GetId(), operation);
  184. }
  185. HRESULT SetupLog::Save()
  186. {
  187. LPSTR buffer = NULL;
  188. size_t cchBuffer = SetupLog_GetMaxServiceIdCount(&serviceMap) * 11;
  189. if (0 != cchBuffer)
  190. {
  191. cchBuffer += 1;
  192. buffer = Plugin_MallocAnsiString(cchBuffer);
  193. if (NULL == buffer)
  194. return E_OUTOFMEMORY;
  195. }
  196. const UINT szOperations[] = { opServiceAdded,
  197. opServiceRemoved, };
  198. for (INT i = 0; i < ARRAYSIZE(szOperations); i++)
  199. {
  200. LPCSTR value = (NULL != buffer &&
  201. SUCCEEDED(SetupLog_FormatServiceId(&serviceMap, szOperations[i], buffer, cchBuffer)) &&
  202. '\0' != *buffer) ? buffer : NULL;
  203. SetupLog_WriteOperationLog(szOperations[i], value);
  204. }
  205. if (NULL != buffer)
  206. Plugin_FreeAnsiString(buffer);
  207. return S_OK;
  208. }
  209. HRESULT SetupLog::Erase()
  210. {
  211. HRESULT hr = S_OK;
  212. if (FALSE == Config_WriteStr(SETUPLOG_SECTION, SETUPLOG_KEY_SUBSCRIBED, NULL))
  213. hr = E_FAIL;
  214. if (FALSE == Config_WriteStr(SETUPLOG_SECTION, SETUPLOG_KEY_UNSUBSCRIBED, NULL))
  215. hr = E_FAIL;
  216. return hr;
  217. }
  218. struct LOGSENDJOBPARAM
  219. {
  220. LOGSENDJOBPARAM() : totalJobs(0), storage(NULL), completeEvent(NULL) {}
  221. ULONG totalJobs;
  222. CRITICAL_SECTION lock;
  223. ifc_omstorage *storage;
  224. HANDLE completeEvent;
  225. };
  226. static void CALLBACK SetupLog_SendCompleted(ifc_omstorageasync *async)
  227. {
  228. if (NULL != async)
  229. {
  230. LOGSENDJOBPARAM *param = NULL;
  231. if (SUCCEEDED(async->GetData((void**)&param)) && NULL != param)
  232. {
  233. EnterCriticalSection(&param->lock);
  234. if (NULL != param->storage)
  235. {
  236. param->storage->EndLoad(async, NULL);
  237. param->storage->Release();
  238. }
  239. LONG r = InterlockedDecrement((LONG*)&param->totalJobs);
  240. if (0 == r)
  241. {
  242. if (NULL != param->completeEvent)
  243. SetEvent(param->completeEvent);
  244. LeaveCriticalSection(&param->lock);
  245. DeleteCriticalSection(&param->lock);
  246. free(param);
  247. param = NULL;
  248. }
  249. else
  250. {
  251. LeaveCriticalSection(&param->lock);
  252. }
  253. }
  254. }
  255. }
  256. HRESULT SetupLog::Send(HANDLE completeEvent)
  257. {
  258. size_t cchAlloc = serviceMap.size();
  259. if (0 == cchAlloc)
  260. {
  261. if (NULL != completeEvent) SetEvent(completeEvent);
  262. return S_OK;
  263. }
  264. UINT *buffer = (UINT*)calloc(cchAlloc, sizeof(UINT));
  265. LOGSENDJOBPARAM *param = (LOGSENDJOBPARAM*)calloc(1, sizeof(LOGSENDJOBPARAM));
  266. if (NULL == buffer || NULL == param)
  267. {
  268. if (NULL != buffer) { free(buffer); buffer = NULL; }
  269. if (NULL != param) { free(param); param = NULL; }
  270. if (NULL != completeEvent) { SetEvent(completeEvent); completeEvent = NULL; }
  271. return E_OUTOFMEMORY;
  272. }
  273. ifc_omstorage *storage = NULL;
  274. HRESULT hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageUrl, &storage);
  275. if (SUCCEEDED(hr) && storage != NULL)
  276. {
  277. const UINT szOperations[] = { opServiceAdded,
  278. opServiceRemoved, };
  279. param->totalJobs = 0;
  280. param->completeEvent = completeEvent;
  281. param->storage = storage;
  282. InitializeCriticalSection(&param->lock);
  283. EnterCriticalSection(&param->lock);
  284. for (INT i = 0; i < ARRAYSIZE(szOperations); i++)
  285. {
  286. size_t count = 0;
  287. hr = S_OK;
  288. for (SetupLog::ServiceMap::iterator it = serviceMap.begin(); it != serviceMap.end() && SUCCEEDED(hr); it++)
  289. {
  290. if (it->second == szOperations[i])
  291. {
  292. buffer[count] = it->first;
  293. count++;
  294. }
  295. }
  296. if (0 != count)
  297. {
  298. LPWSTR url = NULL;
  299. LPCWSTR action = SetupLog_GetOperationAction(szOperations[i]);
  300. if (NULL != action &&
  301. SUCCEEDED(Plugin_BuildActionUrl(&url, action, buffer, count)))
  302. {
  303. ifc_omstorageasync *async = NULL;;
  304. if (SUCCEEDED(storage->BeginLoad(url, NULL, SetupLog_SendCompleted, param, &async)))
  305. {
  306. InterlockedIncrement((LONG*)&param->totalJobs);
  307. storage->AddRef();
  308. async->Release();
  309. }
  310. Plugin_FreeString(url);
  311. }
  312. }
  313. }
  314. if (0 == param->totalJobs)
  315. {
  316. LeaveCriticalSection(&param->lock);
  317. DeleteCriticalSection(&param->lock);
  318. hr = E_FAIL;
  319. if (param) { free(param); param = NULL; }
  320. }
  321. else
  322. {
  323. LeaveCriticalSection(&param->lock);
  324. }
  325. storage->Release();
  326. }
  327. if (buffer) { free(buffer); buffer = NULL; }
  328. return hr;
  329. }