123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525 |
- //#include "main.h"
- #include "./dispatchCallback.h"
- #include <new.h>
- DispatchCallback::DispatchCallback()
- : ref(1), dispatch(NULL), threadId(0), threadHandle(NULL)
- {
- }
- DispatchCallback::~DispatchCallback()
- {
- if (NULL != dispatch)
- dispatch->Release();
- if (NULL != threadHandle)
- CloseHandle(threadHandle);
- }
- HRESULT DispatchCallback::CreateInstance(IDispatch *dispatch, DispatchCallback **instance)
- {
- if (NULL == instance)
- return E_POINTER;
- *instance = NULL;
- if (NULL == dispatch)
- return E_INVALIDARG;
- DispatchCallback *self = new DispatchCallback();
- if (NULL == self)
- return E_OUTOFMEMORY;
- self->dispatch = dispatch;
- self->dispatch->AddRef();
- self->threadId = GetCurrentThreadId();
- HANDLE processHandle = GetCurrentProcess();
- if (FALSE == DuplicateHandle(processHandle,
- GetCurrentThread(),
- processHandle,
- &self->threadHandle,
- 0,
- FALSE,
- DUPLICATE_SAME_ACCESS))
- {
- self->threadHandle = NULL;
- delete(self);
- return E_FAIL;
- }
- *instance = self;
- return S_OK;
- }
- unsigned long DispatchCallback::AddRef()
- {
- return InterlockedIncrement((long*)&ref);
- }
- unsigned long DispatchCallback::Release()
- {
- if (0 == ref)
- return ref;
- LONG r = InterlockedDecrement((long*)&ref);
- if (0 == r)
- delete(this);
- return r;
- }
- IDispatch *DispatchCallback::GetDispatch()
- {
- return dispatch;
- }
- unsigned long DispatchCallback::GetThreadId()
- {
- return threadId;
- }
- HANDLE DispatchCallback::GetThreadHandle()
- {
- return threadHandle;
- }
- DispatchCallbackEnum::DispatchCallbackEnum()
- : ref(1), buffer(NULL), size(0), cursor(0)
- {
- }
- DispatchCallbackEnum::~DispatchCallbackEnum()
- {
- if (NULL != buffer)
- {
- while(size--)
- {
- buffer[size]->Release();
- }
- }
- }
- HRESULT DispatchCallbackEnum::CreateInstance(DispatchCallback **objects, size_t count, DispatchCallbackEnum **instance)
- {
- DispatchCallback *callback = NULL;
- DispatchCallbackEnum *enumerator = NULL;
- if (NULL == instance)
- return E_POINTER;
- *instance = NULL;
- size_t size = sizeof(DispatchCallbackEnum) + (sizeof(DispatchCallback**) * count);
- void *storage = calloc(size, 1);
- if (NULL == storage)
- return E_OUTOFMEMORY;
- enumerator = new(storage) DispatchCallbackEnum();
- if (NULL == enumerator)
- {
- free(storage);
- return E_FAIL;
- }
- enumerator->buffer = (DispatchCallback**)(((BYTE*)enumerator) + sizeof(DispatchCallback));
- for (size_t index = 0; index < count; index++)
- {
- callback = objects[index];
- if (NULL != callback)
- {
- enumerator->buffer[enumerator->size] = callback;
- callback->AddRef();
- enumerator->size++;
- }
- }
- *instance = enumerator;
- return S_OK;
- }
- unsigned long DispatchCallbackEnum::AddRef()
- {
- return InterlockedIncrement((LONG*)&ref);
- }
- unsigned long DispatchCallbackEnum::Release()
- {
- if (0 == ref)
- return ref;
- LONG r = InterlockedDecrement((LONG*)&ref);
- if (0 == r)
- delete(this);
- return r;
- }
- HRESULT DispatchCallbackEnum::Next(DispatchCallback **objects, size_t bufferMax, size_t *fetched)
- {
- if (NULL == objects)
- return E_POINTER;
- if (0 == bufferMax)
- return E_INVALIDARG;
- if (cursor >= size)
- {
- if (NULL != fetched)
- *fetched = 0;
- return S_FALSE;
- }
- size_t available = size - cursor;
- size_t copied = ((available > bufferMax) ? bufferMax : available);
- DispatchCallback **source = buffer + cursor;
- CopyMemory(objects, source, copied * sizeof(DispatchCallback*));
- for(size_t index = 0; index < copied; index++)
- objects[index]->AddRef();
- cursor += copied;
- if (NULL != fetched)
- *fetched = copied;
- return (bufferMax == copied) ? S_OK : S_FALSE;
- }
- HRESULT DispatchCallbackEnum::Reset(void)
- {
- cursor = 0;
- return S_OK;
- }
- HRESULT DispatchCallbackEnum::Skip(size_t count)
- {
- cursor += count;
- if (cursor > size)
- cursor = size;
- return (cursor < size) ? S_OK : S_FALSE;
- }
- HRESULT DispatchCallbackEnum::GetCount(size_t *count)
- {
- if (NULL == count)
- return E_POINTER;
- *count = size;
- return S_OK;
- }
- HRESULT DispatchCallbackEnum::Notify(DispatchCallbackNotifyFunc notifyCb, DispatchCallbackFreeFunc freeCb, void *param)
- {
- DispatchCallbackApc *apc = NULL;
- unsigned long threadId = GetCurrentThreadId();
- if (NULL == buffer)
- return E_UNEXPECTED;
- HRESULT hr = DispatchCallbackApc::CreateInstance(notifyCb, freeCb, param, &apc);
- if (FAILED(hr) || apc == NULL)
- return hr;
- for (size_t index = 0; index < size; index++)
- {
- DispatchCallback *callback = buffer[index];
- if (callback)
- {
- if (callback->GetThreadId() == threadId)
- apc->Call(callback->GetDispatch());
- else
- apc->Queue(callback->GetThreadHandle(), callback->GetDispatch());
- }
- }
- apc->Release();
- return hr;
- }
- DispatchCallbackStore::DispatchCallbackStore()
- {
- InitializeCriticalSection(&lock);
- }
- DispatchCallbackStore::~DispatchCallbackStore()
- {
- UnregisterAll();
- DeleteCriticalSection(&lock);
- }
- void DispatchCallbackStore::Lock()
- {
- EnterCriticalSection(&lock);
- }
- void DispatchCallbackStore::Unlock()
- {
- LeaveCriticalSection(&lock);
- }
- CRITICAL_SECTION *DispatchCallbackStore::GetLock()
- {
- return &lock;
- }
- HRESULT DispatchCallbackStore::Register(IDispatch *dispatch)
- {
- DispatchCallback *callback = NULL;
- if (NULL == dispatch)
- return E_INVALIDARG;
- Lock();
- HRESULT hr = S_OK;
- size_t index = list.size();
- while(index--)
- {
- callback = list[index];
- if (callback->GetDispatch() == dispatch)
- {
- hr = S_FALSE;
- break;
- }
- }
- if (S_OK == hr)
- {
- hr = DispatchCallback::CreateInstance(dispatch, &callback);
- if (SUCCEEDED(hr))
- list.push_back(callback);
- }
- Unlock();
- return hr;
- }
- HRESULT DispatchCallbackStore::Unregister(IDispatch *dispatch)
- {
- if (NULL == dispatch)
- return E_INVALIDARG;
- Lock();
- HRESULT hr = S_FALSE;
- size_t index = list.size();
- while(index--)
- {
- DispatchCallback *callback = list[index];
- if (callback->GetDispatch() == dispatch)
- {
- list.erase(list.begin() + index);
- callback->Release();
- hr = S_OK;
- break;
- }
- }
- Unlock();
- return hr;
- }
- void DispatchCallbackStore::UnregisterAll()
- {
- Lock();
- size_t index = list.size();
- while(index--)
- {
- DispatchCallback *callback = list[index];
- callback->Release();
- }
- list.clear();
- Unlock();
- }
- HRESULT DispatchCallbackStore::Enumerate(DispatchCallbackEnum **enumerator)
- {
- if (NULL == enumerator || !(list.size() > 0))
- return E_POINTER;
-
- Lock();
- HRESULT hr = DispatchCallbackEnum::CreateInstance(&list[0], list.size(), enumerator);
- Unlock();
- return hr;
- }
- HRESULT DispatchCallbackStore::RegisterFromDispParam(DISPPARAMS *pdispparams, unsigned int position,
- unsigned int *puArgErr)
- {
- VARIANTARG varg;
- VariantInit(&varg);
- HRESULT hr = DispGetParam(pdispparams, position, VT_DISPATCH, &varg, puArgErr);
- if (SUCCEEDED(hr))
- {
- hr = Register(V_DISPATCH(&varg));
- VariantClear(&varg);
- }
- return hr;
- }
- HRESULT DispatchCallbackStore::UnregisterFromDispParam(DISPPARAMS *pdispparams, unsigned int position,
- unsigned int *puArgErr)
- {
- VARIANTARG varg;
- VariantInit(&varg);
- HRESULT hr = DispGetParam(pdispparams, position, VT_DISPATCH, &varg, puArgErr);
- if (SUCCEEDED(hr))
- {
- hr = Unregister(V_DISPATCH(&varg));
- VariantClear(&varg);
- }
- return hr;
- }
- HRESULT DispatchCallbackStore::Notify(DispatchCallbackNotifyFunc notifyCb, DispatchCallbackFreeFunc freeCb, void *param)
- {
- DispatchCallbackEnum *enumerator = NULL;
- HRESULT hr = Enumerate(&enumerator);
- if (SUCCEEDED(hr))
- {
- hr = enumerator->Notify(notifyCb, freeCb, param);
- enumerator->Release();
- }
- return hr;
- }
- DispatchCallbackApc::DispatchCallbackApc()
- : ref(1), notifyCb(NULL), freeCb(NULL), param(NULL)
- {
- }
- DispatchCallbackApc::~DispatchCallbackApc()
- {
- if (NULL != freeCb)
- freeCb(param);
- }
- HRESULT DispatchCallbackApc::CreateInstance(DispatchCallbackNotifyFunc notifyCb, DispatchCallbackFreeFunc freeCb,
- void *param, DispatchCallbackApc **instance)
- {
- if (NULL == instance)
- return E_POINTER;
- *instance = NULL;
- if (NULL == notifyCb)
- return E_INVALIDARG;
- DispatchCallbackApc *self = new DispatchCallbackApc();
- if (NULL == self)
- return E_OUTOFMEMORY;
- self->notifyCb = notifyCb;
- self->freeCb = freeCb;
- self->param = param;
- *instance = self;
- return S_OK;
- }
- unsigned long DispatchCallbackApc::AddRef()
- {
- return InterlockedIncrement((LONG*)&ref);
- }
- unsigned long DispatchCallbackApc::Release()
- {
- if (0 == ref)
- return ref;
- LONG r = InterlockedDecrement((LONG*)&ref);
- if (0 == r)
- delete(this);
- return r;
- }
- HRESULT DispatchCallbackApc::Call(IDispatch *dispatch)
- {
- if (NULL == notifyCb)
- return E_UNEXPECTED;
- notifyCb(dispatch, param);
- return S_OK;
- }
- HRESULT DispatchCallbackApc::Queue(HANDLE threadHandle, IDispatch *dispatch)
- {
- if (NULL == threadHandle || ((unsigned int)dispatch) < 65536)
- return E_INVALIDARG;
- DispatchCallbackApcParam *apcParam = new DispatchCallbackApcParam(dispatch, this);
- if (NULL == apcParam || ((unsigned int)apcParam) < 65536)
- return E_OUTOFMEMORY;
- if (0 == QueueUserAPC(QueueApcCallback, threadHandle, (ULONG_PTR)apcParam))
- {
- unsigned long errorCode = GetLastError();
- delete(apcParam);
- return HRESULT_FROM_WIN32(errorCode);
- }
- return S_OK;
- }
- void CALLBACK DispatchCallbackApc::QueueApcCallback(ULONG_PTR user)
- {
- DispatchCallbackApcParam *apcParam = (DispatchCallbackApcParam*)user;
- if (NULL == apcParam)
- return;
- DispatchCallbackApc *apc = apcParam->GetApc();
- if (NULL != apc)
- apc->Call(apcParam->GetDispatch()),
- delete(apcParam);
- }
- DispatchCallbackApcParam::DispatchCallbackApcParam(IDispatch *_dispatch, DispatchCallbackApc *_apc)
- : dispatch(_dispatch), apc(_apc)
- {
- if (NULL != dispatch && ((unsigned long)dispatch >= 65536))
- dispatch->AddRef();
- if (NULL != apc && ((unsigned long)apc >= 65536))
- apc->AddRef();
- }
- DispatchCallbackApcParam::~DispatchCallbackApcParam()
- {
- if (NULL != dispatch)
- dispatch->Release();
- if (NULL != apc)
- apc->Release();
- }
- IDispatch *DispatchCallbackApcParam::GetDispatch()
- {
- return dispatch;
- }
- DispatchCallbackApc *DispatchCallbackApcParam::GetApc()
- {
- return apc;
- }
|