You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
546 lines
19 KiB
546 lines
19 KiB
/*****************************************************************************
|
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 2002
|
|
*
|
|
* AUTHOR: ByronC
|
|
*
|
|
* DATE: 3/24/2002
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @module WiaEventClient.cpp - Implementation of the <c WiaEventClient> class |
|
|
*
|
|
* This file contains the implementation for the <c WiaEventClient> base class.
|
|
*
|
|
*****************************************************************************/
|
|
#include "precomp.h"
|
|
#include "wia.h"
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc | WiaEventClient | WiaEventClient |
|
|
*
|
|
* We initialize all member variables. In general, this sets the values to 0,
|
|
* except:
|
|
* <nl><md WiaEventClient::m_ulSig> is set to be WiaEventClient_UNINIT_SIG.
|
|
* <nl><md WiaEventClient::m_cRef> is set to be 1.
|
|
* <nl><md WiaEventClient::m_ClientContext> is set to be ClientContext.
|
|
*
|
|
*****************************************************************************/
|
|
WiaEventClient::WiaEventClient(STI_CLIENT_CONTEXT ClientContext) :
|
|
m_ulSig(WiaEventClient_UNINIT_SIG),
|
|
m_cRef(1),
|
|
m_ClientContext(ClientContext),
|
|
m_bRemove(FALSE)
|
|
{
|
|
DBG_FN(WiaEventClient);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc | WiaEventClient | ~WiaEventClient |
|
|
*
|
|
* Do any cleanup that is not already done. We call:
|
|
* <nl><mf WiaEventClient::DestroyRegistrationList>
|
|
* <nl><mf WiaEventClient::DestroyPendingEventList>
|
|
*
|
|
* Also:
|
|
* <nl><md WiaEventClient::m_ulSig> is set to be WiaEventClient_DEL_SIG.
|
|
*
|
|
*****************************************************************************/
|
|
WiaEventClient::~WiaEventClient()
|
|
{
|
|
DBG_FN(~WiaEventClient destructor);
|
|
m_ulSig = WiaEventClient_DEL_SIG;
|
|
m_cRef = 0;
|
|
m_ClientContext = NULL;
|
|
|
|
DestroyRegistrationList();
|
|
DestroyPendingEventList();
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc ULONG | WiaEventClient | AddRef |
|
|
*
|
|
* Increments this object's ref count. We should always AddRef when handing
|
|
* out a pointer to this object.
|
|
*
|
|
* @rvalue Count |
|
|
* The reference count after the count has been incremented.
|
|
*****************************************************************************/
|
|
ULONG __stdcall WiaEventClient::AddRef()
|
|
{
|
|
InterlockedIncrement((long*) &m_cRef);
|
|
return m_cRef;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc ULONG | WiaEventClient | Release |
|
|
*
|
|
* Decrement this object's ref count. We should always Release when finished
|
|
* with a pointer to this object.
|
|
*
|
|
* @rvalue Count |
|
|
* The reference count after the count has been decremented.
|
|
*****************************************************************************/
|
|
ULONG __stdcall WiaEventClient::Release()
|
|
{
|
|
ULONG ulRefCount = m_cRef - 1;
|
|
|
|
if (InterlockedDecrement((long*) &m_cRef) == 0) {
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return ulRefCount;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc HRESULT | WiaEventClient | Initialize |
|
|
*
|
|
* Create and initialize any dependant objects/resources. Specifically:
|
|
* <nl>- Check that <md WiaEventClient::m_csClientSync> is initialized
|
|
* correctly.
|
|
*
|
|
* If this method fails, the object should not be used - it should be
|
|
* destroyed immediately.
|
|
*
|
|
* @rvalue S_OK |
|
|
* The method succeeded.
|
|
* @rvalue E_UNEXPECTED |
|
|
* The object could not be intialized sucessfully.
|
|
*****************************************************************************/
|
|
HRESULT WiaEventClient::Initialize()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_csClientSync.IsInitialized())
|
|
{
|
|
DBG_ERR(("Runtime event Error: WiaEventClient's sync primitive could not be created"));
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_ulSig = WiaEventNotifier_INIT_SIG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc BOOL | WiaEventClient | IsRegisteredForEvent |
|
|
*
|
|
* Checks whether the client has at least one event registration that matches
|
|
* this event.
|
|
*
|
|
* @parm WiaEventInfo* | pWiaEventInfo |
|
|
* Indicates WIA Device event
|
|
*
|
|
* @rvalue TRUE |
|
|
* The client is registered to receive this event.
|
|
* @rvalue FALSE |
|
|
* The client is not registered.
|
|
*****************************************************************************/
|
|
BOOL WiaEventClient::IsRegisteredForEvent(
|
|
WiaEventInfo *pWiaEventInfo)
|
|
{
|
|
BOOL bRegistered = FALSE;
|
|
|
|
if (pWiaEventInfo)
|
|
{
|
|
BSTR bstrDeviceID = pWiaEventInfo->getDeviceID();
|
|
GUID guidEvent = pWiaEventInfo->getEventGuid();
|
|
|
|
TAKE_CRIT_SECT t(m_csClientSync);
|
|
//
|
|
// We put an exception handler around our code to ensure that the
|
|
// crtitical section is exited properly.
|
|
//
|
|
_try
|
|
{
|
|
//
|
|
// Walk the list and see if we can find it
|
|
//
|
|
EventRegistrationInfo *pEventRegistrationInfo = NULL;
|
|
CSimpleLinkedList<EventRegistrationInfo*>::Iterator iter;
|
|
for (iter = m_ListOfEventRegistrations.Begin(); iter != m_ListOfEventRegistrations.End(); ++iter)
|
|
{
|
|
pEventRegistrationInfo = *iter;
|
|
if (pEventRegistrationInfo)
|
|
{
|
|
if (pEventRegistrationInfo->MatchesDeviceEvent(bstrDeviceID, guidEvent))
|
|
{
|
|
//
|
|
// We found a registration matching this event, set the return and break from the loop
|
|
//
|
|
bRegistered = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Log Error
|
|
// pEventRegistrationInfo should never be NULL
|
|
DBG_ERR(("Runtime event Error: While searching for an equal registration, we hit a NULL pEventRegistrationInfo!"));
|
|
}
|
|
}
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DBG_ERR(("Runtime event Error: The WiaEventClient caught an exception (0x%08X) trying to check for an event registration", GetExceptionCode()));
|
|
// TBD: Should we re-throw the exception?
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ERR(("Runtime event Error: The WiaEventClient cannot check whether the client is registered for a NULL WIA Event"));
|
|
}
|
|
|
|
return bRegistered;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc HRESULT | WiaEventClient | RegisterUnregisterForEventNotification |
|
|
*
|
|
* Description goes here
|
|
*
|
|
* @parm EventRegistrationInfo | pEventRegistrationInfo |
|
|
* Pointer to a class containing the registration data to add.
|
|
* This method will make a copy of the structure and insert it into the
|
|
* relevant list.
|
|
*
|
|
* @rvalue S_OK |
|
|
* The method succeeded.
|
|
* @rvalue S_FALSE |
|
|
* We are already registered for this.
|
|
* @rvalue E_XXXXXXXX |
|
|
* Could not update event registration.
|
|
*****************************************************************************/
|
|
HRESULT WiaEventClient::RegisterUnregisterForEventNotification(
|
|
EventRegistrationInfo *pEventRegistrationInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pEventRegistrationInfo)
|
|
{
|
|
//
|
|
// We always have to walk through the list. This is because when we add, we need
|
|
// to check whether it already exists. When we remove, we need to find the
|
|
// element to remove.
|
|
// So, try and find the element here.
|
|
//
|
|
EventRegistrationInfo *pExistingReg = FindEqualEventRegistration(pEventRegistrationInfo);
|
|
|
|
//
|
|
// Check whether this is registration or unregistration.
|
|
// NOTE: Since unregistration is typically done via the RegistrationCookie,
|
|
// our hueristic for this is that if it is not specifically an UnRegistration,
|
|
// then it is considered a registration.
|
|
//
|
|
if (pEventRegistrationInfo->getFlags() & WIA_UNREGISTER_EVENT_CALLBACK)
|
|
{
|
|
if (pExistingReg != NULL)
|
|
{
|
|
//
|
|
// Release it and remove it from our list.
|
|
//
|
|
m_ListOfEventRegistrations.Remove(pExistingReg);
|
|
pExistingReg->Release();
|
|
DBG_TRC(("Removed registration:"));
|
|
pExistingReg->Dump();
|
|
}
|
|
else
|
|
{
|
|
DBG_ERR(("Runtime event Error: Attempting to unregister when you have not first registered"));
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else // This is considered a registration
|
|
{
|
|
if (pExistingReg == NULL)
|
|
{
|
|
//
|
|
// Add it to our list. We AddRef it here since we're keeping a reference to it.
|
|
//
|
|
m_ListOfEventRegistrations.Prepend(pEventRegistrationInfo);
|
|
pEventRegistrationInfo->AddRef();
|
|
DBG_TRC(("Added new registration:"));
|
|
pEventRegistrationInfo->Dump();
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
DBG_WRN(("Runtime event client Error: Registration already exists in the list"));
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We need to release pExistingReg due to the AddRef from the lookup.
|
|
//
|
|
if (pExistingReg)
|
|
{
|
|
pExistingReg->Release();
|
|
pExistingReg = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ERR(("Runtime event Error: Cannot handle a NULL registration"));
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc HRESULT | WiaEventClient | AddPendingEventNotification |
|
|
*
|
|
* Description goes here
|
|
*
|
|
* @parm WiaEventInfo* | pWiaEventInfo |
|
|
* Pointer to a <c WiaEventInfo> object which contains event info that
|
|
* must be sent to the client. This class is AddRef'd when added to the
|
|
* list.
|
|
*
|
|
* @rvalue S_OK |
|
|
* The method succeeded.
|
|
* @rvalue E_UNEXPECTED |
|
|
* The object could not be added sucessfully.
|
|
*****************************************************************************/
|
|
HRESULT WiaEventClient::AddPendingEventNotification(
|
|
WiaEventInfo *pWiaEventInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
TAKE_CRIT_SECT t(m_csClientSync);
|
|
//
|
|
// We put an exception handler around our code to ensure that the
|
|
// crtitical section is exited properly.
|
|
//
|
|
_try
|
|
{
|
|
DBG_TRC(("Added another pending event to %p", m_ClientContext));
|
|
m_ListOfEventsPending.Enqueue(pWiaEventInfo);
|
|
pWiaEventInfo->AddRef();
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DBG_ERR(("Runtime event Error: The WiaEventClient caught an exception (0x%08X) trying to add a pending event", GetExceptionCode()));
|
|
// TBD: Should we re-throw the exception?
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc STI_CLIENT_CONTEXT | WiaEventClient | getClientContext |
|
|
*
|
|
* Returns the context which uniquely identifies the client.
|
|
*
|
|
* @rvalue STI_CLIENT_CONTEXT |
|
|
* The context identifyin this client.
|
|
*****************************************************************************/
|
|
STI_CLIENT_CONTEXT WiaEventClient::getClientContext()
|
|
{
|
|
return m_ClientContext;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc EventRegistrationInfo* | WiaEventClient | FindEqualEventRegistration |
|
|
*
|
|
* Checks whether a semantically equal <c EventRegistrationInfo> is in the list.
|
|
* If it is, we retrieve it. Note that caller must Release it.
|
|
*
|
|
* @parm EventRegistrationInfo | pEventRegistrationInfo |
|
|
* Specifies a <c EventRegistrationInfo> we're looking for in our list.
|
|
*
|
|
* @rvalue NULL |
|
|
* We could not find it.
|
|
* @rvalue non-NULL |
|
|
* The equivalent <c EventRegistrationInfo> exists. Caller must Release.
|
|
*****************************************************************************/
|
|
EventRegistrationInfo* WiaEventClient::FindEqualEventRegistration(
|
|
EventRegistrationInfo *pEventRegistrationInfo)
|
|
{
|
|
EventRegistrationInfo *pRet = NULL;
|
|
|
|
if (pEventRegistrationInfo)
|
|
{
|
|
TAKE_CRIT_SECT t(m_csClientSync);
|
|
//
|
|
// We put an exception handler around our code to ensure that the
|
|
// crtitical section is exited properly.
|
|
//
|
|
_try
|
|
{
|
|
//
|
|
// Walk the list and see if we can find it
|
|
//
|
|
EventRegistrationInfo *pElem = NULL;
|
|
CSimpleLinkedList<EventRegistrationInfo*>::Iterator iter;
|
|
for (iter = m_ListOfEventRegistrations.Begin(); iter != m_ListOfEventRegistrations.End(); ++iter)
|
|
{
|
|
pElem = *iter;
|
|
if (pElem)
|
|
{
|
|
if (pElem->Equals(pEventRegistrationInfo))
|
|
{
|
|
//
|
|
// We found it, so AddRef it and set the return
|
|
//
|
|
pElem->AddRef();
|
|
pRet = pElem;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Log Error
|
|
// pEventRegistrationInfo should never be NULL
|
|
DBG_ERR(("Runtime event Error: While searching for an equal registration, we hit a NULL pEventRegistrationInfo!"));
|
|
}
|
|
}
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DBG_ERR(("Runtime event Error: The WiaEventClient caught an exception (0x%08X) trying to find an equal event registration", GetExceptionCode()));
|
|
// TBD: Should we re-throw the exception?
|
|
}
|
|
}
|
|
|
|
return pRet;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc VOID | WiaEventClient | DestroyRegistrationList |
|
|
*
|
|
* Frees all resources associated with the registration list by releasing all elements
|
|
* in it, and then destroying the links in the list.
|
|
*****************************************************************************/
|
|
VOID WiaEventClient::DestroyRegistrationList()
|
|
{
|
|
TAKE_CRIT_SECT t(m_csClientSync);
|
|
//
|
|
// We put an exception handler around our code to ensure that the
|
|
// crtitical section is exited properly.
|
|
//
|
|
_try
|
|
{
|
|
//
|
|
// Walk the list of registrations release all elements. Then destroy the list.
|
|
//
|
|
EventRegistrationInfo *pElem = NULL;
|
|
CSimpleLinkedList<EventRegistrationInfo*>::Iterator iter;
|
|
for (iter = m_ListOfEventRegistrations.Begin(); iter != m_ListOfEventRegistrations.End(); ++iter)
|
|
{
|
|
pElem = *iter;
|
|
if (pElem)
|
|
{
|
|
pElem->Release();
|
|
}
|
|
}
|
|
m_ListOfEventRegistrations.Destroy();
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DBG_ERR(("Runtime event Error: The WiaEventClient caught an exception (0x%08X) trying to destroy the registration list", GetExceptionCode()));
|
|
// TBD: Should we re-throw the exception?
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc VOID | WiaEventClient | DestroyPendingEventList |
|
|
*
|
|
* Frees all resources associated with the pending event list by releasing all elements
|
|
* in it, and then destroying the links in the list.
|
|
*****************************************************************************/
|
|
VOID WiaEventClient::DestroyPendingEventList()
|
|
{
|
|
TAKE_CRIT_SECT t(m_csClientSync);
|
|
//
|
|
// We put an exception handler around our code to ensure that the
|
|
// crtitical section is exited properly.
|
|
//
|
|
_try
|
|
{
|
|
//
|
|
// Walk the list of registrations release all elements. Then destroy the list.
|
|
//
|
|
WiaEventInfo *pElem = NULL;
|
|
CSimpleLinkedList<WiaEventInfo*>::Iterator iter;
|
|
for (iter = m_ListOfEventsPending.Begin(); iter != m_ListOfEventsPending.End(); ++iter)
|
|
{
|
|
pElem = *iter;
|
|
if (pElem)
|
|
{
|
|
pElem->Release();
|
|
}
|
|
}
|
|
m_ListOfEventsPending.Destroy();
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DBG_ERR(("Runtime event Error: The WiaEventClient caught an exception (0x%08X) trying to destroy the registration list", GetExceptionCode()));
|
|
// TBD: Should we re-throw the exception?
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc VOID | WiaEventClient | MarkForRemoval |
|
|
*
|
|
* Sets the mark to indicate that this object should be removed at the next
|
|
* possible convenience (i.e. we use lazy deletion).
|
|
*
|
|
*****************************************************************************/
|
|
VOID WiaEventClient::MarkForRemoval()
|
|
{
|
|
DBG_TRC(("Client %p marked for removal", m_ClientContext));
|
|
m_bRemove = TRUE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc BOOL | WiaEventClient | isMarkedForRemoval |
|
|
*
|
|
* Check the mark to indicate whether this object should be removed.
|
|
*
|
|
* @rvalue TRUE |
|
|
* This object can/should be removed.
|
|
* @rvalue FALSE |
|
|
* This object is not marked for removal.
|
|
*****************************************************************************/
|
|
BOOL WiaEventClient::isMarkedForRemoval()
|
|
{
|
|
return m_bRemove;
|
|
}
|
|
|