| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 | #include "./setupLog.h"#include "../common.h"#include "../api__ml_online.h"#include "../config.h"#include "../../nu/trace.h"#include <ifc_omservice.h>#include <ifc_omwebstorage.h>#include <ifc_omstorageasync.h>#include <shlwapi.h>#include <strsafe.h>#define SETUPLOG_SEPARATOR			','#define SETUPLOG_SECTION			"Setup"#define SETUPLOG_KEY_SUBSCRIBED		"subscribed"#define SETUPLOG_KEY_UNSUBSCRIBED	"unsubscribed"struct LOGPARSERPARAM{	LOGPARSERPARAM() : instance(NULL), operation(0) {}	SetupLog *instance;	UINT operation;};static size_t SetupLog_GetMaxServiceIdCount(SetupLog::ServiceMap *serviceMap){	SetupLog::ServiceMap::iterator it;	size_t c1 = 0, c2 = 0;	for (it = serviceMap->begin(); it != serviceMap->end(); it++)	{		switch(it->second)		{			case SetupLog::opServiceAdded:				c1++;				break;			case SetupLog::opServiceRemoved:				c2++;				break;		}	}	return  (c1 > c2) ? c1 : c2;}static HRESULT SetupLog_FormatServiceId(SetupLog::ServiceMap *serviceMap, INT operation, LPSTR pszBuffer, size_t cchBufferMax){	if (NULL == pszBuffer) 		return E_INVALIDARG;	*pszBuffer = '\0';	if (NULL == serviceMap)		return S_OK;	HRESULT hr = S_OK;	size_t remaining = cchBufferMax;	LPSTR cursor = pszBuffer;	SetupLog::ServiceMap::iterator it;	const char format[] = { SETUPLOG_SEPARATOR, '%', 'u', '\0'};	for (it = serviceMap->begin(); it != serviceMap->end() && SUCCEEDED(hr); it++)	{		if (it->second == operation)		{			hr = StringCchPrintfExA(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE, 					((cursor == pszBuffer) ? (format + 1) : format), it->first);		}	}	return hr;}static LPCSTR SetupLog_GetOperationKey(UINT operation){	switch(operation)	{		case SetupLog::opServiceAdded: return SETUPLOG_KEY_SUBSCRIBED;		case SetupLog::opServiceRemoved: return SETUPLOG_KEY_UNSUBSCRIBED;	}	return NULL;}static LPCWSTR SetupLog_GetOperationAction(UINT operation){	switch(operation)	{		case SetupLog::opServiceAdded: return L"add";		case SetupLog::opServiceRemoved: return L"remove";	}	return NULL;}static BOOL SetupLog_WriteOperationLog(UINT operation, LPCSTR pszValue){	LPCSTR pszKey = SetupLog_GetOperationKey(operation);	if (NULL == pszKey) return FALSE;	return Config_WriteStr(SETUPLOG_SECTION, pszKey, pszValue);}static HRESULT SetupLog_ReadOperationLog(UINT operation, LPSTR pszBuffer, UINT cchBufferMax, UINT *cchReaded){		LPCSTR pszKey = SetupLog_GetOperationKey(operation);	if (NULL == pszKey) return E_INVALIDARG;	DWORD readed = Config_ReadStr(SETUPLOG_SECTION, pszKey, NULL, pszBuffer, cchBufferMax);	if (NULL != cchReaded)	{		*cchReaded = readed;	}		return S_OK;}SetupLog::SetupLog() : ref(1){}SetupLog::~SetupLog(){}SetupLog *SetupLog::Open(){	SetupLog *instance = new SetupLog();	if (NULL == instance) return NULL;	INT cchBuffer =  32000;	LPSTR buffer = Plugin_MallocAnsiString(cchBuffer);	if (NULL == buffer)	{		instance->Release();		return NULL;	}	UINT cchReaded = 0;	const UINT szOperations[] = {	opServiceAdded, 									opServiceRemoved, };	UINT serviceId;	for (INT i = 0; i < ARRAYSIZE(szOperations); i++)	{		if (SUCCEEDED(SetupLog_ReadOperationLog(szOperations[i], buffer, cchBuffer, &cchReaded)) && cchReaded > 0)		{						LPSTR cursor = buffer;			LPSTR block = cursor;			for(;;)			{				if (SETUPLOG_SEPARATOR == *cursor || '\0' == *cursor)				{					while (' ' == *block && block < cursor) block++;										if (block < cursor &&						FALSE != StrToIntExA(block, STIF_SUPPORT_HEX, (INT*)&serviceId) &&						0 != serviceId)					{						instance->LogServiceById(serviceId, szOperations[i]);					}					if ('\0' == *cursor)						break;					cursor++;					block = cursor;				}				else				{					cursor++;				}			}		}	}	Plugin_FreeAnsiString(buffer);	return instance;}ULONG SetupLog::AddRef(){	return InterlockedIncrement((LONG*)&ref);}ULONG SetupLog::Release(){	if (0 == ref)		return ref;		LONG r = InterlockedDecrement((LONG*)&ref);	if (0 == r)		delete(this);		return r;}BOOL SetupLog::IsOperationSupported(UINT operation){	switch(operation)	{		case SetupLog::opServiceAdded:		case SetupLog::opServiceRemoved:			return TRUE;	}	return FALSE;}HRESULT SetupLog::LogServiceById(UINT serviceUid, UINT operation){	if (0 == serviceUid || FALSE == IsOperationSupported(operation)) 		return E_INVALIDARG;	serviceMap[serviceUid] = operation;	return S_OK;}HRESULT SetupLog::LogService(ifc_omservice *service, UINT operation){	if (NULL == service || !IsOperationSupported(operation))		return E_INVALIDARG;		return LogServiceById(service->GetId(), operation);}HRESULT SetupLog::Save(){	LPSTR buffer = NULL;	size_t cchBuffer = SetupLog_GetMaxServiceIdCount(&serviceMap) * 11; 	if (0 != cchBuffer)	{		cchBuffer += 1;		buffer = Plugin_MallocAnsiString(cchBuffer);		if (NULL == buffer)			return E_OUTOFMEMORY;	}	const UINT szOperations[] = {	opServiceAdded, 									opServiceRemoved, };	for (INT i = 0; i < ARRAYSIZE(szOperations); i++)	{		LPCSTR value = (NULL != buffer && 					SUCCEEDED(SetupLog_FormatServiceId(&serviceMap, szOperations[i], buffer, cchBuffer)) && 					'\0' != *buffer) ? buffer : NULL;		SetupLog_WriteOperationLog(szOperations[i], value);	}	if (NULL != buffer)		Plugin_FreeAnsiString(buffer);	return S_OK;}HRESULT SetupLog::Erase(){	HRESULT hr = S_OK;	if (FALSE == Config_WriteStr(SETUPLOG_SECTION, SETUPLOG_KEY_SUBSCRIBED, NULL))		hr = E_FAIL;	if (FALSE == Config_WriteStr(SETUPLOG_SECTION, SETUPLOG_KEY_UNSUBSCRIBED, NULL))		hr = E_FAIL;	return hr;}struct LOGSENDJOBPARAM{	LOGSENDJOBPARAM() : totalJobs(0), storage(NULL), completeEvent(NULL) {}	ULONG totalJobs;	CRITICAL_SECTION lock;	ifc_omstorage *storage;	HANDLE completeEvent;};static void CALLBACK SetupLog_SendCompleted(ifc_omstorageasync *async){	if (NULL != async)	{		LOGSENDJOBPARAM *param = NULL;		if (SUCCEEDED(async->GetData((void**)¶m)) && NULL != param)		{			EnterCriticalSection(¶m->lock);			if (NULL != param->storage)			{				param->storage->EndLoad(async, NULL);				param->storage->Release();			}						LONG r = InterlockedDecrement((LONG*)¶m->totalJobs);			if (0 == r)			{				if (NULL != param->completeEvent)					SetEvent(param->completeEvent);				LeaveCriticalSection(¶m->lock);				DeleteCriticalSection(¶m->lock);				free(param);				param = NULL;			}			else			{				LeaveCriticalSection(¶m->lock);			}		}	}}HRESULT SetupLog::Send(HANDLE completeEvent){	size_t cchAlloc = serviceMap.size();	if (0 == cchAlloc)	{		if (NULL != completeEvent) SetEvent(completeEvent);		return S_OK;	}	UINT *buffer = (UINT*)calloc(cchAlloc, sizeof(UINT));	LOGSENDJOBPARAM *param = (LOGSENDJOBPARAM*)calloc(1, sizeof(LOGSENDJOBPARAM));	if (NULL == buffer || NULL == param)	{		if (NULL != buffer) { free(buffer); buffer = NULL; }		if (NULL != param) { free(param); param = NULL; }		if (NULL != completeEvent) { SetEvent(completeEvent); completeEvent = NULL; }		return E_OUTOFMEMORY;	}	ifc_omstorage *storage = NULL;	HRESULT hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageUrl, &storage);	if (SUCCEEDED(hr) && storage != NULL)	{		const UINT szOperations[] = {	opServiceAdded, 										opServiceRemoved, };		param->totalJobs = 0;		param->completeEvent = completeEvent;		param->storage = storage;		InitializeCriticalSection(¶m->lock);		EnterCriticalSection(¶m->lock);		for (INT i = 0; i < ARRAYSIZE(szOperations); i++)		{			size_t count = 0;			hr = S_OK;			for (SetupLog::ServiceMap::iterator it = serviceMap.begin(); it != serviceMap.end() && SUCCEEDED(hr); it++)			{				if (it->second == szOperations[i])				{					buffer[count] = it->first;					count++;				}			}			if (0 != count)			{				LPWSTR url = NULL;				LPCWSTR action = SetupLog_GetOperationAction(szOperations[i]);				if (NULL != action && 					SUCCEEDED(Plugin_BuildActionUrl(&url, action, buffer, count)))				{					ifc_omstorageasync *async = NULL;;					if (SUCCEEDED(storage->BeginLoad(url, NULL, SetupLog_SendCompleted, param, &async)))					{						InterlockedIncrement((LONG*)¶m->totalJobs);						storage->AddRef();						async->Release();					}					Plugin_FreeString(url);				}			}		}		if (0 == param->totalJobs)		{			LeaveCriticalSection(¶m->lock);			DeleteCriticalSection(¶m->lock);			hr = E_FAIL;			if (param) { free(param); param = NULL; }		}		else		{			LeaveCriticalSection(¶m->lock);		}		storage->Release();	}	if (buffer) { free(buffer); buffer = NULL; }	return hr;}
 |