diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/omBrowser/enumAsync.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/omBrowser/enumAsync.cpp')
-rw-r--r-- | Src/omBrowser/enumAsync.cpp | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/Src/omBrowser/enumAsync.cpp b/Src/omBrowser/enumAsync.cpp new file mode 100644 index 00000000..7d90174a --- /dev/null +++ b/Src/omBrowser/enumAsync.cpp @@ -0,0 +1,347 @@ +#include "main.h" +#include "./enumAsync.h" +#include "./ifc_omservice.h" +#include "./ifc_omserviceenum.h" +#include "./ifc_wasabihelper.h" +#include "./serviceList.h" + +EnumAsyncWrapper::EnumAsyncWrapper(ifc_omserviceenum *enumerator) + : ref(1), enumerator(enumerator), userCallback(NULL), userData(NULL), + completed(NULL), state(stateReady), resultCode(E_PENDING), serviceList(NULL) +{ + if (NULL != enumerator) + enumerator->AddRef(); + + InitializeCriticalSection(&lock); +} + +EnumAsyncWrapper::~EnumAsyncWrapper() +{ + EnterCriticalSection(&lock); + + if (NULL != enumerator) + enumerator->Release(); + + if (NULL != completed) + CloseHandle(completed); + + if (NULL != serviceList) + serviceList->Release(); + + LeaveCriticalSection(&lock); + + DeleteCriticalSection(&lock); +} + +HRESULT EnumAsyncWrapper::CreateInstance(ifc_omserviceenum *enumerator, EnumAsyncWrapper **instance) +{ + if (NULL == instance) return E_POINTER; + *instance = NULL; + + if (NULL == enumerator) + return E_INVALIDARG; + + *instance = new EnumAsyncWrapper(enumerator); + if (NULL == *instance) return E_OUTOFMEMORY; + + return S_OK; +} + +size_t EnumAsyncWrapper::AddRef() +{ + return InterlockedIncrement((LONG*)&ref); +} + +size_t EnumAsyncWrapper::Release() +{ + if (0 == ref) + return ref; + + LONG r = InterlockedDecrement((LONG*)&ref); + if (0 == r) + delete(this); + + return r; +} + +int EnumAsyncWrapper::QueryInterface(GUID interface_guid, void **object) +{ + if (NULL == object) return E_POINTER; + + if (IsEqualIID(interface_guid, IFC_OmStorageAsync)) + *object = static_cast<ifc_omstorageasync*>(this); + else + { + *object = NULL; + return E_NOINTERFACE; + } + + if (NULL == *object) + return E_UNEXPECTED; + + AddRef(); + return S_OK; +} + +HRESULT EnumAsyncWrapper::GetState(UINT *state) +{ + if (NULL == state) + return E_POINTER; + + EnterCriticalSection(&lock); + *state = this->state; + LeaveCriticalSection(&lock); + + return S_OK; +} + +HRESULT EnumAsyncWrapper::GetWaitHandle(HANDLE *handle) +{ + if (NULL == handle) + return E_POINTER; + + HRESULT hr = S_OK; + + EnterCriticalSection(&lock); + + if (NULL == completed) + { + completed = CreateEvent(NULL, TRUE, FALSE, NULL); + if (NULL == completed) + { + *handle = NULL; + DWORD error = GetLastError(); + hr = HRESULT_FROM_WIN32(error); + } + } + + if (SUCCEEDED(hr) && FALSE == DuplicateHandle(GetCurrentProcess(), completed, + GetCurrentProcess(), handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + *handle = NULL; + DWORD error = GetLastError(); + hr = HRESULT_FROM_WIN32(error); + } + + LeaveCriticalSection(&lock); + + return hr; +} + +HRESULT EnumAsyncWrapper::GetData(void **data) +{ + if (NULL == data) + return E_POINTER; + + EnterCriticalSection(&lock); + *data = userData; + LeaveCriticalSection(&lock); + + return S_OK; +} + +HRESULT EnumAsyncWrapper::GetCallback(AsyncCallback *callback) +{ + if (NULL == callback) + return E_POINTER; + + EnterCriticalSection(&lock); + *callback = userCallback; + LeaveCriticalSection(&lock); + + return S_OK; +} + +HRESULT EnumAsyncWrapper::SetData(void *data) +{ + EnterCriticalSection(&lock); + userData = data; + LeaveCriticalSection(&lock); + + return S_OK; +} + +HRESULT EnumAsyncWrapper::SetCallback(AsyncCallback callback) +{ + EnterCriticalSection(&lock); + userCallback = callback; + LeaveCriticalSection(&lock); + + return S_OK; +} + +HRESULT EnumAsyncWrapper::RequestAbort(BOOL fDrop) +{ + HRESULT hr = S_FALSE; + + EnterCriticalSection(&lock); + + if (stateInitializing == state || stateReceiving == state) + { + state = stateAborting; + if (FALSE != fDrop) + { + userCallback = NULL; + userData = NULL; + } + } + + LeaveCriticalSection(&lock); + + return hr; +} + +static int EnumAsyncWrapper_ThreadFunc(HANDLE handle, void *user_data, intptr_t id) +{ + EnumAsyncWrapper *instance = (EnumAsyncWrapper*)user_data; + if (NULL != instance) instance->Enumerate(); + return 0; +} + +HRESULT EnumAsyncWrapper::BeginEnumerate() +{ + ifc_wasabihelper *wasabi = NULL; + HRESULT hr; + + EnterCriticalSection(&lock); + + if (stateReady != state && stateCompleted != state) + { + hr = E_PENDING; + } + else + { + state = stateInitializing; + + if (NULL != serviceList) + { + serviceList->Release(); + serviceList = NULL; + } + + hr = Plugin_GetWasabiHelper(&wasabi); + if (SUCCEEDED(hr) && wasabi != NULL) + { + api_threadpool *threadpool; + hr = wasabi->GetThreadpoolApi(&threadpool); + if (SUCCEEDED(hr)) + { + if (0 != threadpool->RunFunction(NULL, EnumAsyncWrapper_ThreadFunc, this, 0, 0)) + { + hr = E_FAIL; + } + else + { + AddRef(); + } + threadpool->Release(); + } + else + { + hr = E_NOINTERFACE; + } + + wasabi->Release(); + } + + if (FAILED(hr)) + state = stateCompleted; + } + + LeaveCriticalSection(&lock); + return hr; +} + +HRESULT EnumAsyncWrapper::Enumerate() +{ + EnterCriticalSection(&lock); + state = stateReceiving; + resultCode = OmServiceList::CreateInstance(&serviceList); + LeaveCriticalSection(&lock); + + if (SUCCEEDED(resultCode)) + { + if (NULL == enumerator) + { + resultCode = E_UNEXPECTED; + } + else + { + ifc_omservice *service; + while(S_OK == enumerator->Next(1, &service, NULL)) + { + if (stateAborting == state) + { + resultCode = E_ABORT; + break; + } + + if (NULL != service) + { + serviceList->Add(service); + service->Release(); + } + } + } + } + + EnterCriticalSection(&lock); + state = stateCompleted; + HANDLE event = completed; + LeaveCriticalSection(&lock); + + if (NULL != event) + { + SetEvent(event); + } + + EnterCriticalSection(&lock); + AsyncCallback cb = userCallback; + LeaveCriticalSection(&lock); + + if (NULL != cb) + { + cb(this); + } + + Release(); + + return resultCode; +} + +HRESULT EnumAsyncWrapper::GetResultCode() +{ + return resultCode; +} + +HRESULT EnumAsyncWrapper::GetServiceList(ifc_omserviceenum **list) +{ + if (NULL == list) + return E_POINTER; + + if (NULL == serviceList) + { + *list = NULL; + return E_UNEXPECTED; + } + + EnterCriticalSection(&lock); + + *list = serviceList; + serviceList->AddRef(); + + LeaveCriticalSection(&lock); + + return S_OK; +} + +#define CBCLASS EnumAsyncWrapper +START_DISPATCH; +CB(ADDREF, AddRef) +CB(RELEASE, Release) +CB(QUERYINTERFACE, QueryInterface) +CB(API_GETSTATE, GetState) +CB(API_GETWAITHANDLE, GetWaitHandle) +CB(API_GETDATA, GetData) +END_DISPATCH; +#undef CBCLASS
\ No newline at end of file |