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.
699 lines
27 KiB
699 lines
27 KiB
/*****************************************************************************
|
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 2002
|
|
*
|
|
* AUTHOR: ByronC
|
|
*
|
|
* DATE: 3/30/2002
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @module WiaEventReceiver.cpp - Declarations for <c WiaEventReceiver> |
|
|
*
|
|
* This file contains the implementation for the <c WiaEventReceiver> class.
|
|
*
|
|
*****************************************************************************/
|
|
#include "cplusinc.h"
|
|
#include "coredbg.h"
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc | WiaEventReceiver | WiaEventReceiver |
|
|
*
|
|
* We initialize all member variables. In general, this sets the values to 0,
|
|
* except:
|
|
* <nl><md WiaEventReceiver::m_ulSig> is set to be WiaEventReceiver_UNINIT_SIG.
|
|
* <nl><md WiaEventReceiver::m_cRef> is set to be 1.
|
|
* <nl><md WiaEventReceiver::m_pClientEventTransport> is set to be <p pClientEventTransport>.
|
|
*
|
|
* @parm ClientEventTransport* | pClientEventTransport |
|
|
* The transport class used to communicate with the WIA Service.
|
|
*
|
|
*****************************************************************************/
|
|
WiaEventReceiver::WiaEventReceiver(
|
|
ClientEventTransport *pClientEventTransport) :
|
|
m_ulSig(WiaEventReceiver_UNINIT_SIG),
|
|
m_cRef(1),
|
|
m_pClientEventTransport(pClientEventTransport),
|
|
m_hEventThread(NULL),
|
|
m_bIsRunning(FALSE),
|
|
m_dwEventThreadID(0)
|
|
{
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc | WiaEventReceiver | ~WiaEventReceiver |
|
|
*
|
|
* Do any cleanup that is not already done.
|
|
* <nl>- Call <mf WiaEventReceiver::Stop>
|
|
* <nl>- Delete <mf WiaEventReceiver::m_pClientEventTransport>
|
|
* <nl>- Call <mf WiaEventReceiver::DestroyRegistrationList>
|
|
*
|
|
* Also:
|
|
* <nl><md WiaEventReceiver::m_ulSig> is set to be WiaEventReceiver_DEL_SIG.
|
|
*
|
|
*****************************************************************************/
|
|
WiaEventReceiver::~WiaEventReceiver()
|
|
{
|
|
m_ulSig = WiaEventReceiver_DEL_SIG;
|
|
m_cRef = 0;
|
|
|
|
Stop();
|
|
if (m_pClientEventTransport)
|
|
{
|
|
delete m_pClientEventTransport;
|
|
m_pClientEventTransport = NULL;
|
|
}
|
|
|
|
DestroyRegistrationList();
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc HRESULT | WiaEventReceiver | Start |
|
|
*
|
|
* This method does any initialization steps needed to start receiving
|
|
* notifications from the WIA Service. We:
|
|
* <nl>- Open our connection to the server
|
|
* <nl>- Open our notification channel
|
|
* <nl>- Create our event thread
|
|
*
|
|
* This method is idempotent i.e. you can call <mf WiaEventReceiver::Start> multiple times safely
|
|
* before calling <mf WiaEventReceiver::Stop>. Subsequent calls to <mf WiaEventReceiver::Start>
|
|
* have no effect until <mf WiaEventReceiver::Stop> has been called.
|
|
*
|
|
* @rvalue S_OK |
|
|
* This object initialized correctly.
|
|
* @rvalue E_XXXXXXXXX |
|
|
* This object could not be initialized correctly. It should be released
|
|
* immediately.
|
|
*****************************************************************************/
|
|
HRESULT WiaEventReceiver::Start()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_csReceiverSync.IsInitialized())
|
|
{
|
|
TAKE_CRIT_SECT t(m_csReceiverSync);
|
|
//
|
|
// We put an exception handler around our code to ensure that the
|
|
// crtitical section is exited properly.
|
|
//
|
|
_try
|
|
{
|
|
if (!m_bIsRunning)
|
|
{
|
|
if (m_pClientEventTransport)
|
|
{
|
|
hr = m_pClientEventTransport->Initialize();
|
|
if (hr == S_OK)
|
|
{
|
|
hr = m_pClientEventTransport->OpenConnectionToServer();
|
|
if (hr == S_OK)
|
|
{
|
|
hr = m_pClientEventTransport->OpenNotificationChannel();
|
|
if (hr == S_OK)
|
|
{
|
|
//
|
|
// Create our event thread with will wait for
|
|
// notifications from the transport layer.
|
|
//
|
|
m_hEventThread = CreateThread(NULL,
|
|
0,
|
|
WiaEventReceiver::EventThreadProc,
|
|
this,
|
|
0,
|
|
&m_dwEventThreadID);
|
|
if (m_hEventThread)
|
|
{
|
|
DBG_TRC(("WiaEventReceiver Started..."));
|
|
m_bIsRunning = TRUE;
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
DBG_ERR(("Runtime event Error: Could not initialize the transport for the WiaEventReceiver"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ERR(("Runtime event Error: The transport for the WiaEventReceiver is NULL"));
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DBG_ERR(("Runtime event Error: We caught exception 0x%08X trying to sart receiving notifications", GetExceptionCode()));
|
|
hr = E_UNEXPECTED;
|
|
// TBD: Rethrow the exception?
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ERR(("Runtime event Error: The critical section for the WiaEventReceiver could not be initialized"));
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DBG_ERR(("Runtime event Error: Could not Start...calling Stop"));
|
|
Stop();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc HRESULT | WiaEventReceiver | NotifyCallbacksOfEvent |
|
|
*
|
|
* Walks down the list of event registrations. For every event
|
|
* registration that matches <p pWiaEventInfo>, we make the callback.
|
|
* (See <mf EventRegistrationInfo::MatchesDeviceEvent> for information on what consitutes
|
|
* a match). This is done synchronously.
|
|
*
|
|
* The callbacks are done in two steps:
|
|
* <nl>1) Walk the list to find matching registrations. For each matching registration,
|
|
* add it to a ListOfCallbacks (This is done holding the critical section)
|
|
* <nl>2) Walk the ListOfCallbacks and make the callback (This is done without holding the critical
|
|
* section to avoid deadlock)
|
|
*
|
|
* @parm WiaEventInfo* | pWiaEventInfo |
|
|
* The actual event that occured.
|
|
*
|
|
* @rvalue S_OK |
|
|
* The method succeeded.
|
|
*****************************************************************************/
|
|
HRESULT WiaEventReceiver::NotifyCallbacksOfEvent(
|
|
WiaEventInfo *pWiaEventInfo)
|
|
{
|
|
CSimpleLinkedList<ClientEventRegistrationInfo*> ListOfCallbacksToNotify;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pWiaEventInfo)
|
|
{
|
|
TAKE_CRIT_SECT t(m_csReceiverSync);
|
|
//
|
|
// 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
|
|
//
|
|
ClientEventRegistrationInfo *pEventRegistrationInfo = NULL;
|
|
CSimpleLinkedList<ClientEventRegistrationInfo*>::Iterator iter;
|
|
for (iter = m_ListOfEventRegistrations.Begin(); iter != m_ListOfEventRegistrations.End(); ++iter)
|
|
{
|
|
pEventRegistrationInfo = *iter;
|
|
if (pEventRegistrationInfo)
|
|
{
|
|
//
|
|
// Check whether a given registration matches the event. If it does, it means
|
|
// we have to ad it to the list of callbacks to notify.
|
|
//
|
|
if (pEventRegistrationInfo->MatchesDeviceEvent(pWiaEventInfo->getDeviceID(),
|
|
pWiaEventInfo->getEventGuid()))
|
|
{
|
|
//
|
|
// AddRef the EventRegistrationInfo because we're keeping it in another list.
|
|
// It will be released once the callback is made.
|
|
//
|
|
ListOfCallbacksToNotify.Append(pEventRegistrationInfo);
|
|
pEventRegistrationInfo->AddRef();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Log Error
|
|
// pEventRegistrationInfo should never be NULL
|
|
DBG_ERR(("Runtime event Error: While searching for a matching registration, we hit a NULL pEventRegistrationInfo!"));
|
|
}
|
|
}
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DBG_ERR(("Runtime event Error: We caught exception 0x%08X trying to notify callbacks of event", GetExceptionCode()));
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ERR(("Runtime event Error: Cannot process NULL event info"));
|
|
hr = E_POINTER;
|
|
}
|
|
|
|
//
|
|
// We now have a list of callbacks we need to notify of the event. We do this here
|
|
// now that we are not holding the Critical Section (m_csReceiver) anymore.
|
|
//
|
|
if (SUCCEEDED(hr) && pWiaEventInfo)
|
|
{
|
|
//
|
|
// Walk the ListOfCallbacksToNotify and make the callbacks
|
|
//
|
|
ClientEventRegistrationInfo *pEventRegistrationInfo = NULL;
|
|
CSimpleLinkedList<ClientEventRegistrationInfo*>::Iterator iter;
|
|
for (iter = ListOfCallbacksToNotify.Begin(); iter != ListOfCallbacksToNotify.End(); ++iter)
|
|
{
|
|
pEventRegistrationInfo = *iter;
|
|
if (pEventRegistrationInfo)
|
|
{
|
|
//
|
|
// Put an exception handler around the actual callback attempt
|
|
//
|
|
_try
|
|
{
|
|
GUID guidEvent = pWiaEventInfo->getEventGuid();
|
|
ULONG ulEventType = pWiaEventInfo->getEventType();
|
|
IWiaEventCallback *pIWiaEventCallback = pEventRegistrationInfo->getCallbackInterface();
|
|
|
|
if (pIWiaEventCallback)
|
|
{
|
|
HRESULT hres = pIWiaEventCallback->ImageEventCallback(
|
|
&guidEvent,
|
|
pWiaEventInfo->getEventDescription(),
|
|
pWiaEventInfo->getDeviceID(),
|
|
pWiaEventInfo->getDeviceDescription(),
|
|
pWiaEventInfo->getDeviceType(),
|
|
pWiaEventInfo->getFullItemName(),
|
|
&ulEventType,
|
|
0);
|
|
pIWiaEventCallback->Release();
|
|
}
|
|
else
|
|
{
|
|
DBG_WRN(("Cannot notify a NULL IWiaEventCallback"));
|
|
}
|
|
}
|
|
_finally
|
|
{
|
|
//
|
|
// Always release the pEventRegistrationInfo since we AddRef'd it putting it in the list
|
|
//
|
|
pEventRegistrationInfo->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc HRESULT | WiaEventReceiver | SendRegisterUnregisterInfo |
|
|
*
|
|
* This method will add/remove the relevant event registration, then send
|
|
* the info off to the WIA Service.
|
|
*
|
|
* To insert into our list, we grab the <md WiaEventReceiver::m_csReceiverSync>,
|
|
* then create a new <c ClientEventRegistrationInfo> class (if this is a registration),
|
|
* or we find the registration in the list and remove it (if this is an
|
|
* unregister). The sync is released after this.
|
|
*
|
|
* Only once this is done, do we notify the service.
|
|
*
|
|
* This method will automatically ensure we are started by calling <mf WiaEventReceiver::Start>.
|
|
* If at the end of this method, there are no registrations, it will call
|
|
* <mf WiaEventReceiver::Stop>. (Because, if the client
|
|
* is not registered for anything, we do not need our event thread or an active channel
|
|
* to the server).
|
|
*
|
|
* @parm ClientEventRegistrationInfo* | pEventRegistrationInfo |
|
|
* Pointer to a class containing the registration data to add/remove.
|
|
*
|
|
* @rvalue S_OK |
|
|
* The method succeeded.
|
|
* @rvalue E_XXXXXXX |
|
|
* We could not send the register/unregister info.
|
|
*****************************************************************************/
|
|
HRESULT WiaEventReceiver::SendRegisterUnregisterInfo(
|
|
ClientEventRegistrationInfo *pEventRegistrationInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pEventRegistrationInfo)
|
|
{
|
|
//
|
|
// Ensure we have a channel open to the server and then send the registration info.
|
|
//
|
|
Start();
|
|
hr = m_pClientEventTransport->SendRegisterUnregisterInfo(pEventRegistrationInfo);
|
|
}
|
|
else
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
//
|
|
// Ensure we take the sync for the rest of this function
|
|
//
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
TAKE_CRIT_SECT t(m_csReceiverSync);
|
|
//
|
|
// We put an exception handler around our code to ensure that the
|
|
// crtitical section is exited properly.
|
|
//
|
|
_try
|
|
{
|
|
//
|
|
// 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)
|
|
{
|
|
ClientEventRegistrationInfo *pExistingReg = FindEqualEventRegistration(pEventRegistrationInfo);
|
|
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;
|
|
}
|
|
//
|
|
// We need to release pExistingReg due to the AddRef from the lookup.
|
|
//
|
|
if (pExistingReg)
|
|
{
|
|
pExistingReg->Release();
|
|
pExistingReg = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// 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();
|
|
}
|
|
|
|
//
|
|
// If no registrations exit in the list, then we should stop.
|
|
// If we have at least one registration in the list, then we should start.
|
|
//
|
|
if (m_ListOfEventRegistrations.Empty())
|
|
{
|
|
Stop();
|
|
}
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DBG_ERR(("Runtime event Error: We caught exception 0x%08X trying to register/unregister for event", GetExceptionCode()));
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
//*/
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc VOID | WiaEventReceiver | Stop |
|
|
*
|
|
* Calls transport object to:
|
|
* <nl>- Close our notification channel. See <mf ClientEventTransport::CloseNotificationChannel>
|
|
* <nl>- Close our connection to the server. See <mf ClientEventTransport::CloseConnectionToServer>
|
|
* <nl>- Close our event thread handle.
|
|
* <nl>- Set <md WiaEventReceiver::m_bIsRunning> to FALSE.
|
|
*
|
|
*****************************************************************************/
|
|
VOID WiaEventReceiver::Stop()
|
|
{
|
|
if (m_csReceiverSync.IsInitialized())
|
|
{
|
|
TAKE_CRIT_SECT t(m_csReceiverSync);
|
|
//
|
|
// We put an exception handler around our code to ensure that the
|
|
// crtitical section is exited properly.
|
|
//
|
|
_try
|
|
{
|
|
if (m_bIsRunning)
|
|
{
|
|
DBG_TRC(("...WiaEventReceiver is Stopping..."));
|
|
m_bIsRunning = FALSE;
|
|
m_dwEventThreadID = 0;
|
|
if (m_pClientEventTransport)
|
|
{
|
|
m_pClientEventTransport->CloseNotificationChannel();
|
|
m_pClientEventTransport->CloseConnectionToServer();
|
|
}
|
|
if (m_hEventThread)
|
|
{
|
|
CloseHandle(m_hEventThread);
|
|
m_hEventThread = NULL;
|
|
}
|
|
}
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DBG_ERR(("Runtime event Error: We caught exception 0x%08X trying to Stop", GetExceptionCode()));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc VOID | WiaEventReceiver | DestroyRegistrationList |
|
|
*
|
|
* Removes any remaining event registration objects and destroys the list.
|
|
*
|
|
*****************************************************************************/
|
|
VOID WiaEventReceiver::DestroyRegistrationList()
|
|
{
|
|
TAKE_CRIT_SECT t(m_csReceiverSync);
|
|
//
|
|
// 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.
|
|
//
|
|
ClientEventRegistrationInfo *pElem = NULL;
|
|
CSimpleLinkedList<ClientEventRegistrationInfo*>::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: We caught exception 0x%08X trying to destroy the registration list", GetExceptionCode()));
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc ClientEventRegistrationInfo* | WiaEventReceiver | FindEqualEventRegistration |
|
|
*
|
|
* Checks whether a semantically equal <c ClientEventRegistrationInfo> is in the list.
|
|
* If it is, we retrieve it. Note that caller must Release it.
|
|
*
|
|
* @parm ClientEventRegistrationInfo | pEventRegistrationInfo |
|
|
* Specifies a <c ClientEventRegistrationInfo> we're looking for in our list.
|
|
*
|
|
* @rvalue NULL |
|
|
* We could not find it.
|
|
* @rvalue non-NULL |
|
|
* The equivalent <c ClientEventRegistrationInfo> exists. Caller must Release.
|
|
*****************************************************************************/
|
|
ClientEventRegistrationInfo* WiaEventReceiver::FindEqualEventRegistration(
|
|
ClientEventRegistrationInfo *pEventRegistrationInfo)
|
|
{
|
|
ClientEventRegistrationInfo *pRet = NULL;
|
|
|
|
if (pEventRegistrationInfo)
|
|
{
|
|
TAKE_CRIT_SECT t(m_csReceiverSync);
|
|
//
|
|
// 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
|
|
//
|
|
ClientEventRegistrationInfo *pElem = NULL;
|
|
CSimpleLinkedList<ClientEventRegistrationInfo*>::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 WiaEventReceiver caught an exception (0x%08X) trying to find an equal event registration", GetExceptionCode()));
|
|
}
|
|
}
|
|
|
|
return pRet;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc DWORD WINAPI | WiaEventReceiver | EventThreadProc |
|
|
*
|
|
* This method waits on the handle returned by <mf ClientEventTransport::getNotificationHandle>.
|
|
* When this event is signalled, it means we either have a notification, or we are
|
|
* being asked to exit.
|
|
*
|
|
* Before processing the event, we check whether we are being asked to exit by
|
|
* checking the <md WiaEventReceiver::m_dwEventThreadID> member. If it is not
|
|
* equal to our thread ID, then we must exit this thread.
|
|
*
|
|
* @parm LPVOID | lpParameter |
|
|
* This is actually a pointer to the instance of <c WiaEventReceiver>.
|
|
*
|
|
* @rvalue S_OK |
|
|
* The method succeeded.
|
|
*****************************************************************************/
|
|
DWORD WINAPI WiaEventReceiver::EventThreadProc(
|
|
LPVOID lpParameter)
|
|
{
|
|
WiaEventReceiver *pThis = (WiaEventReceiver*)lpParameter;
|
|
BOOL bRunning = TRUE;
|
|
if (pThis)
|
|
{
|
|
//
|
|
// Call CoInitializeEx here. We prefer multithreaded but we will
|
|
// work with any aprtment model.
|
|
//
|
|
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
if (pThis->m_pClientEventTransport)
|
|
{
|
|
HANDLE hEvent = pThis->m_pClientEventTransport->getNotificationHandle();
|
|
RPC_STATUS rpcStatus = RPC_S_OK;
|
|
|
|
while (bRunning)
|
|
{
|
|
DWORD dwWait = WaitForSingleObject(hEvent, INFINITE);
|
|
if (dwWait == WAIT_OBJECT_0)
|
|
{
|
|
//
|
|
// Check whether we are still supposed to be running.
|
|
// We are supposed to be running if our thread id matches the
|
|
// one in the event receiver. If not, then we must exit.
|
|
//
|
|
if (pThis->m_dwEventThreadID == GetCurrentThreadId())
|
|
{
|
|
DBG_TRC(("...We got the event. Retriving data"));
|
|
WiaEventInfo wEventInfo;
|
|
rpcStatus = pThis->m_pClientEventTransport->FillEventData(&wEventInfo);
|
|
if (rpcStatus == RPC_S_OK)
|
|
{
|
|
HRESULT hrRes = pThis->NotifyCallbacksOfEvent(&wEventInfo);
|
|
}
|
|
else
|
|
{
|
|
DBG_WRN(("We got an error 0x%08X trying to fill the event data.", rpcStatus));
|
|
//
|
|
// TBD: Should we reset our connection to the server?
|
|
// Let's try to reconnect... If that fails, then just stop.
|
|
//
|
|
DBG_WRN(("Resetting connection to server"));
|
|
pThis->Stop();
|
|
rpcStatus = pThis->Start();
|
|
if (rpcStatus != RPC_S_OK)
|
|
{
|
|
DBG_WRN(("Resetting connection to server failed with 0x%08X, closing our connection", rpcStatus));
|
|
pThis->Stop();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_TRC(("!Received notification to Shutdown event thread!"));
|
|
bRunning = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ERR(("Cannot work with a NULL event transport"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ERR(("Cannot work with a NULL WiaEventReceiver"));
|
|
}
|
|
CoUninitialize();
|
|
DBG_TRC(("\nEvent Thread 0x%08X is now shutdown\n", GetCurrentThreadId()));
|
|
return 0;
|
|
}
|
|
|