Leaked source code of windows server 2003
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

/*****************************************************************************
* (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;
}