123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- #include "main.h"
- #include "./deviceActivity.h"
- #include <strsafe.h>
- typedef struct DeviceActivityThreadParam
- {
- DeviceActivity *activity;
- unsigned int duration;
- unsigned int interval;
- HANDLE readyEvent;
- }DeviceActivityThreadParam;
- DeviceActivity::DeviceActivity(DeviceActivityFlags flags,
- DeviceActivityCallback startCb, DeviceActivityCallback finishCb,
- DeviceActivityProgressCallback progressCb, void *user)
- : ref(1), displayName(NULL), status(NULL), activityThread(FALSE), cancelEvent(NULL), progress(0)
- {
- InitializeCriticalSection(&lock);
- this->flags = flags;
- callbackStart = startCb;
- callbackFinish = finishCb;
- callbackProgress = progressCb;
- this->user = user;
- }
- DeviceActivity::~DeviceActivity()
- {
- Stop();
- String_Free(displayName);
- String_Free(status);
- DeleteCriticalSection(&lock);
- }
- HRESULT DeviceActivity::CreateInstance(DeviceActivityFlags flags,
- DeviceActivityCallback startCb, DeviceActivityCallback finishCb,
- DeviceActivityProgressCallback progressCb, void *user,
- DeviceActivity **instance)
- {
- DeviceActivity *self;
- if (NULL == instance)
- return E_POINTER;
- *instance = NULL;
-
- self = new DeviceActivity(flags, startCb, finishCb, progressCb, user);
- if (NULL == self)
- return E_OUTOFMEMORY;
-
- *instance = self;
- return S_OK;
- }
- size_t DeviceActivity::AddRef()
- {
- return InterlockedIncrement((LONG*)&ref);
- }
- size_t DeviceActivity::Release()
- {
- if (0 == ref)
- return ref;
-
- LONG r = InterlockedDecrement((LONG*)&ref);
- if (0 == r)
- delete(this);
-
- return r;
- }
- int DeviceActivity::QueryInterface(GUID interface_guid, void **object)
- {
- if (NULL == object)
- return E_POINTER;
-
- if (IsEqualIID(interface_guid, IFC_DeviceActivity))
- *object = static_cast<ifc_deviceactivity*>(this);
- else
- {
- *object = NULL;
- return E_NOINTERFACE;
- }
- if (NULL == *object)
- return E_UNEXPECTED;
- AddRef();
- return S_OK;
- }
- void DeviceActivity::Lock()
- {
- EnterCriticalSection(&lock);
- }
- void DeviceActivity::Unlock()
- {
- LeaveCriticalSection(&lock);
- }
- BOOL DeviceActivity::GetActive()
- {
- BOOL running;
- Lock();
- running = (NULL != activityThread);
- Unlock();
- return running;
- }
- BOOL DeviceActivity::GetCancelable()
- {
- BOOL cancelable;
- Lock();
- cancelable = (0 != (DeviceActivityFlag_Cancelable & flags));
- Unlock();
- return cancelable;
- }
- HRESULT DeviceActivity::GetProgress(unsigned int *percentCompleted)
- {
- if (NULL == percentCompleted)
- return E_POINTER;
- Lock();
- *percentCompleted = progress;
- Unlock();
- return S_OK;
- }
- HRESULT DeviceActivity::GetDisplayName(wchar_t *buffer, size_t bufferMax)
- {
- HRESULT hr;
- if (NULL == buffer)
- return E_POINTER;
- Lock();
- if (0 == String_CopyTo(buffer, displayName, bufferMax) &&
- FALSE == IS_STRING_EMPTY(displayName))
- {
- hr = E_FAIL;
- }
- else
- hr = S_OK;
-
- Unlock();
- return hr;
- }
- HRESULT DeviceActivity::GetStatus(wchar_t *buffer, size_t bufferMax)
- {
- HRESULT hr;
- if (NULL == buffer)
- return E_POINTER;
- Lock();
- if (0 == String_CopyTo(buffer, status, bufferMax) &&
- FALSE == IS_STRING_EMPTY(status))
- {
- hr = E_FAIL;
- }
- else
- hr = S_OK;
-
- Unlock();
- return hr;
- }
- HRESULT DeviceActivity::Cancel(HWND hostWindow)
- {
- HRESULT hr;
- Lock();
-
- if (0 == (DeviceActivityFlag_Cancelable & flags))
- hr = E_NOTIMPL;
- else
- hr = E_FAIL;
-
- Unlock();
- return hr;
- }
- HRESULT DeviceActivity::Start(unsigned int duration, unsigned int interval)
- {
- HRESULT hr;
- Lock();
- if (NULL != activityThread)
- hr = E_PENDING;
- else
- {
- hr = S_OK;
- if (NULL == cancelEvent)
- {
- cancelEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (NULL == cancelEvent)
- hr = E_FAIL;
- }
- if (SUCCEEDED(hr))
- {
- DeviceActivityThreadParam param;
-
- param.activity = this;
- param.duration = duration;
- param.interval = interval;
- param.readyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (NULL == param.readyEvent)
- hr = E_FAIL;
- else
- {
- DWORD threadId;
-
- activityThread = CreateThread(NULL, 0, DeviceActivity_ActivityThreadStarter,
- ¶m, 0, &threadId);
- if (NULL == activityThread)
- hr = E_FAIL;
- else
- WaitForSingleObject(param.readyEvent, INFINITE);
-
- CloseHandle(param.readyEvent);
- }
- }
- if (FAILED(hr))
- Stop();
- }
- Unlock();
- return hr;
- }
- HRESULT DeviceActivity::Stop()
- {
- HRESULT hr;
- HANDLE threadHandle, eventHandle;
- Lock();
- threadHandle = activityThread;
- eventHandle = cancelEvent;
- activityThread = NULL;
- cancelEvent = NULL;
- Unlock();
- if (NULL != threadHandle)
- {
- if (NULL != eventHandle)
- SetEvent(eventHandle);
- WaitForSingleObject(threadHandle, INFINITE);
- CloseHandle(threadHandle);
- hr = S_OK;
- }
- else
- hr = S_FALSE;
-
- if (NULL != eventHandle)
- CloseHandle(eventHandle);
- return hr;
- }
-
- HRESULT DeviceActivity::SetDisplayName(const wchar_t *name)
- {
- HRESULT hr;
- Lock();
- if (NULL == name && NULL == displayName)
- hr = S_FALSE;
- else
- {
- if (NULL != displayName &&
- CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, name, -1, displayName, -1))
- {
- hr = S_FALSE;
- }
- else
- {
- wchar_t *string;
- string = String_Duplicate(name);
- if (NULL == string && NULL != name)
- hr = E_FAIL;
- else
- {
- String_Free(displayName);
- displayName = string;
- hr = S_OK;
- }
- }
- }
- Unlock();
- return hr;
- }
- HRESULT DeviceActivity::SetStatus(const wchar_t *newStatus)
- {
- HRESULT hr;
- if (NULL == newStatus && NULL == status)
- return S_FALSE;
- Lock();
- if (NULL != status &&
- CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, newStatus, -1, status, -1))
- {
- hr = S_FALSE;
- }
- else
- {
- wchar_t *string;
- string = String_Duplicate(newStatus);
- if (NULL == string && NULL != newStatus)
- hr = E_FAIL;
- else
- {
- String_Free(status);
- status = string;
- hr = S_OK;
- }
- }
- Unlock();
- return hr;
- }
- HRESULT DeviceActivity::SetUser(void *data)
- {
- Lock();
- user = data;
- Unlock();
- return S_OK;
-
- }
- HRESULT DeviceActivity::GetUser(void **data)
- {
- if (NULL == data)
- return E_POINTER;
- Lock();
- *data = user;
- Unlock();
- return S_OK;
- }
- DWORD DeviceActivity::ActivityThread(unsigned int duration, unsigned int interval)
- {
- DWORD waitResult, waitTime;
- HANDLE cancelEventCopy;
- unsigned int position;
- if (interval > duration)
- interval = duration;
- position = 0;
-
- Lock();
-
- progress = 0;
- if (NULL == cancelEvent ||
- 0 == DuplicateHandle(GetCurrentProcess(), cancelEvent, GetCurrentProcess(),
- &cancelEventCopy, 0, FALSE, DUPLICATE_SAME_ACCESS))
- {
- cancelEventCopy = NULL;
- }
- Unlock();
- if(NULL == cancelEventCopy)
- return -3;
- Lock();
- if (NULL != callbackStart)
- callbackStart(this);
- if (NULL != callbackProgress)
- callbackProgress(this, position, duration);
- Unlock();
- for(;;)
- {
- waitTime = interval;
- if ((position + waitTime) > duration)
- waitTime = duration - position;
- waitResult = WaitForSingleObject(cancelEventCopy, waitTime);
- if (WAIT_TIMEOUT == waitResult)
- {
- position += waitTime;
-
- Lock();
- if (duration != 0)
- {
- progress = 100 * position / duration;
- if (progress > 100)
- progress = 100;
- }
- else
- progress = 100;
-
- if (NULL != callbackProgress)
- callbackProgress(this, position, duration);
- Unlock();
- if (position >= duration)
- break;
- }
- else
- break;
- }
- AddRef();
- Lock();
-
- if (NULL != activityThread)
- {
- CloseHandle(activityThread);
- activityThread = NULL;
- }
- if (NULL != cancelEvent)
- {
- CloseHandle(cancelEvent);
- cancelEvent = NULL;
- }
-
- if (NULL != callbackFinish)
- callbackFinish(this);
- Unlock();
- Release();
- return 0;
- }
- static DWORD CALLBACK
- DeviceActivity_ActivityThreadStarter(void *user)
- {
- DeviceActivityThreadParam *param;
- DeviceActivity *activity;
- unsigned int duration, interval;
- DWORD result;
-
- param = (DeviceActivityThreadParam*)user;
- activity = param->activity;
- duration = param->duration;
- interval = param->interval;
-
- if (NULL != param->readyEvent)
- SetEvent(param->readyEvent);
-
- if (NULL != activity)
- result = activity->ActivityThread(duration, interval);
- else
- result = -2;
-
- return result;
- }
- #define CBCLASS DeviceActivity
- START_DISPATCH;
- CB(ADDREF, AddRef)
- CB(RELEASE, Release)
- CB(QUERYINTERFACE, QueryInterface)
- CB(API_GETACTIVE, GetActive)
- CB(API_GETCANCELABLE, GetCancelable)
- CB(API_GETPROGRESS, GetProgress)
- CB(API_GETDISPLAYNAME, GetDisplayName)
- CB(API_GETSTATUS, GetStatus)
- CB(API_CANCEL, Cancel)
- END_DISPATCH;
- #undef CBCLASS
|