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.
380 lines
14 KiB
380 lines
14 KiB
/*****************************************************************************
|
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 2002
|
|
*
|
|
* AUTHOR: ByronC
|
|
*
|
|
* DATE: 4/14/2002
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @module StiEventHandlerLookup.cpp - Implementation for <c StiEventHandlerLookup> |
|
|
*
|
|
* This file contains the implementation of the <c StiEventHandlerLookup> class.
|
|
*
|
|
*****************************************************************************/
|
|
#include "precomp.h"
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc | StiEventHandlerLookup | StiEventHandlerLookup |
|
|
*
|
|
* We initialize all member variables. In general, this sets the values to 0,
|
|
* except:
|
|
* <nl><md StiEventHandlerLookup::m_ulSig> is set to be StiEventHandlerLookup_INIT_SIG.
|
|
* <nl><md StiEventHandlerLookup::m_cRef> is set to be 1.
|
|
*
|
|
*****************************************************************************/
|
|
StiEventHandlerLookup::StiEventHandlerLookup() :
|
|
m_ulSig(StiEventHandlerLookup_INIT_SIG),
|
|
m_cRef(1)
|
|
{
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc | StiEventHandlerLookup | ~StiEventHandlerLookup |
|
|
*
|
|
* Do any cleanup that is not already done. We:
|
|
* <nl> - Call <mf StiEventHandlerLookup::ClearListOfHandlers>
|
|
*
|
|
* Also:
|
|
* <nl><md StiEventHandlerLookup::m_ulSig> is set to be StiEventHandlerLookup_DEL_SIG.
|
|
*
|
|
*****************************************************************************/
|
|
StiEventHandlerLookup::~StiEventHandlerLookup()
|
|
{
|
|
m_ulSig = StiEventHandlerLookup_DEL_SIG;
|
|
m_cRef = 0;
|
|
|
|
ClearListOfHandlers();
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc ULONG | StiEventHandlerLookup | 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 StiEventHandlerLookup::AddRef()
|
|
{
|
|
InterlockedIncrement((long*) &m_cRef);
|
|
return m_cRef;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc ULONG | StiEventHandlerLookup | 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 StiEventHandlerLookup::Release()
|
|
{
|
|
ULONG ulRefCount = m_cRef - 1;
|
|
|
|
if (InterlockedDecrement((long*) &m_cRef) == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return ulRefCount;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc bool | StiEventHandlerLookup | getHandlerFromName |
|
|
*
|
|
* This method is used to create a <c StiEventHandlerInfo> object describing
|
|
* the handler named <p cswHandlerName>.
|
|
*
|
|
* @parm const CSimpleStringWide & | cswHandlerName |
|
|
* The STI handler name registered under the StillImage software key.
|
|
*
|
|
* @rvalue NULL |
|
|
* The handler was not found, therefore no information was returned.
|
|
* @rvalue non-NULL |
|
|
* A pointer to a new <c StiEventHandlerInfo>. Caller must release.
|
|
*****************************************************************************/
|
|
StiEventHandlerInfo* StiEventHandlerLookup::getHandlerFromName(
|
|
const CSimpleStringWide &cswHandlerName)
|
|
{
|
|
StiEventHandlerInfo *pStiEventHandlerInfo = NULL;
|
|
|
|
CSimpleReg csrGlobalHandlers(HKEY_LOCAL_MACHINE, STI_GLOBAL_EVENT_HANDLER_PATH, false, KEY_READ);
|
|
CSimpleStringWide cswCommandline = csrGlobalHandlers.Query(cswHandlerName, L"");
|
|
|
|
if (cswCommandline.Length() > 0)
|
|
{
|
|
pStiEventHandlerInfo = new StiEventHandlerInfo(cswHandlerName,
|
|
cswCommandline);
|
|
}
|
|
|
|
return pStiEventHandlerInfo;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc VOID | StiEventHandlerLookup | ClearListOfHandlers |
|
|
*
|
|
* Frees resources associated with our list of handlers
|
|
*
|
|
*****************************************************************************/
|
|
VOID StiEventHandlerLookup::ClearListOfHandlers()
|
|
{
|
|
CSimpleLinkedList<StiEventHandlerInfo*>::Iterator iter;
|
|
for (iter = m_ListOfHandlers.Begin(); iter != m_ListOfHandlers.End(); ++iter)
|
|
{
|
|
StiEventHandlerInfo *pStiEventHandlerInfo = *iter;
|
|
|
|
if (pStiEventHandlerInfo)
|
|
{
|
|
pStiEventHandlerInfo->Release();
|
|
}
|
|
}
|
|
m_ListOfHandlers.Destroy();
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc VOID | StiEventHandlerLookup | FillListOfHandlers |
|
|
*
|
|
* This method fills the <md StiEventHandlerLookup::m_ListOfHandlers> with
|
|
* the appropriate Sti registered handlers.
|
|
*
|
|
* The hueristic used is:
|
|
* <nl>1. Get the "LaunchApplications" value for the event.
|
|
* <nl>2. For each App specified in the LauncApplications value,
|
|
* create a <c StiEventHandlerInfo> and insert it into
|
|
* <md StiEventHandlerLookup::m_ListOfHandlers>.
|
|
* Note: If the "LaunchApplications" value == "*", then
|
|
* we get all STI registered apps.
|
|
*
|
|
* Note that this method will destroy the existing list of handlers by calling
|
|
* <mf ClearListOfHandlers::FillListOfHandlers> as it's first operation.
|
|
*
|
|
* @parm const CSimpleStringWide & | cswDeviceID |
|
|
* The Device on which the event occured
|
|
* @parm const GUID & | guidEvent |
|
|
* The Event generated by the device
|
|
*****************************************************************************/
|
|
VOID StiEventHandlerLookup::FillListOfHandlers(
|
|
const CSimpleStringWide &cswDeviceID,
|
|
const GUID &guidEvent)
|
|
{
|
|
WiaDeviceKey wiaDeviceKey(cswDeviceID);
|
|
CSimpleStringWide cswEventKeyPath = wiaDeviceKey.getDeviceEventKeyPath(guidEvent);
|
|
|
|
ClearListOfHandlers();
|
|
|
|
//
|
|
// If we can find the device event key, then
|
|
// read the LaunchApplications value for this key.
|
|
// If it was not found, then we assume this is a bogus event for
|
|
// this device, so we do nothing.
|
|
//
|
|
if (cswEventKeyPath.Length() > 0)
|
|
{
|
|
CSimpleReg csrEventKey(HKEY_LOCAL_MACHINE, cswEventKeyPath, false, KEY_READ);
|
|
CSimpleStringWide cswLaunchApplicationsValue = csrEventKey.Query(STI_LAUNCH_APPPLICATIONS_VALUE,
|
|
STI_LAUNCH_WILDCARD);
|
|
//
|
|
// Check whether the value is a wildcard or not. If it is, we need to process all globally
|
|
// registered STI Apps.
|
|
// If it isn't, only add the ones that are specified in the value (it is a
|
|
// comma separated list of Handler names).
|
|
//
|
|
if (cswLaunchApplicationsValue.CompareNoCase(STI_LAUNCH_WILDCARD) == 0)
|
|
{
|
|
CSimpleReg csrRegisteredAppsKey(HKEY_LOCAL_MACHINE, STI_GLOBAL_EVENT_HANDLER_PATH, false, KEY_READ);
|
|
|
|
//
|
|
// Enumerate through all the handler values in the globally registered and add them to the list
|
|
//
|
|
bool bReturnIgnored = csrRegisteredAppsKey.EnumValues(StiEventHandlerLookup::ProcessHandlers,
|
|
(LPARAM)this);
|
|
}
|
|
else
|
|
{
|
|
StiEventHandlerInfo *pStiEventHandlerInfo = NULL;
|
|
//
|
|
// Walk through each element of the comma separated list and add it as a new handler
|
|
//
|
|
StiEventHandlerLookup::SimpleStringTokenizer simpleStringTokenizer(cswLaunchApplicationsValue,
|
|
STI_LAUNCH_SEPARATOR);
|
|
for (CSimpleStringWide cswAppName = simpleStringTokenizer.getNextToken();
|
|
cswAppName.Length() > 0;
|
|
cswAppName = simpleStringTokenizer.getNextToken())
|
|
{
|
|
pStiEventHandlerInfo = getHandlerFromName(cswAppName);
|
|
if (pStiEventHandlerInfo)
|
|
{
|
|
//
|
|
// Handler was found, so add it to the list
|
|
//
|
|
m_ListOfHandlers.Append(pStiEventHandlerInfo);
|
|
pStiEventHandlerInfo = NULL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Handler not found, so don't add it to the list. This could happen
|
|
// if user chose to list a specific set of apps to choose from, but one
|
|
// of the apps in the list has subsequently been unregistered.
|
|
//
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc bool | StiEventHandlerLookup | ProcessHandlers |
|
|
*
|
|
* This method is called on each value of the registered handlers key.
|
|
* Our current behavior is to create a new <c StiEventHandlerInfo> describing
|
|
* the registered handler, and add it to <md StiEventHandlerLookup::m_ListOfHandlers>.
|
|
*
|
|
* @parm CValueEnumInfo& | enumInfo |
|
|
* Indicates the current value we're on.
|
|
*
|
|
* @rvalue true |
|
|
* This method always returns true. (Returning false would cause a
|
|
* enumeration to stop, but we want to enumerate all values)
|
|
*****************************************************************************/
|
|
bool StiEventHandlerLookup::ProcessHandlers(
|
|
CSimpleReg::CValueEnumInfo &enumInfo)
|
|
{
|
|
//
|
|
// Check that we have a This pointer
|
|
//
|
|
StiEventHandlerLookup *This = (StiEventHandlerLookup*)enumInfo.lParam;
|
|
if (This)
|
|
{
|
|
//
|
|
// Create a new StiEventHandlerInfo describing this handler
|
|
//
|
|
StiEventHandlerInfo *pStiEventHandlerInfo = NULL;
|
|
|
|
pStiEventHandlerInfo = This->getHandlerFromName(enumInfo.strName);
|
|
if (pStiEventHandlerInfo)
|
|
{
|
|
//
|
|
// Handler was found, so add it to the list
|
|
//
|
|
This->m_ListOfHandlers.Append(pStiEventHandlerInfo);
|
|
pStiEventHandlerInfo = NULL;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* @doc INTERNAL
|
|
*
|
|
* @mfunc BSTR | StiEventHandlerLookup | getStiAppListForDeviceEvent |
|
|
*
|
|
* This method returns a double NULL-terminated BSTR containing multiple
|
|
* strings. The format of the string is:
|
|
* <nl>App1Name[NULL]
|
|
* <nl>App1CommandLine[NULL]
|
|
* <nl>App2Name[NULL]
|
|
* <nl>App2CommandLine[NULL]
|
|
* <nl>......
|
|
* <nl>[NULL]
|
|
*
|
|
* Caller must free.
|
|
*
|
|
* @parm const CSimpleStringWide & | cswDeviceID |
|
|
* The STI device ID indicating which device generated the event
|
|
* @parm const GUID & | guidEvent |
|
|
* The event guid indicating the device event
|
|
*
|
|
* @rvalue NULL |
|
|
* We could not create a list of registered STI handlers. This is normal
|
|
* if there are no applications registered for StillImage events.
|
|
* @rvalue non-NULL |
|
|
* This contains a double NULL terminated string list. Caller must free.
|
|
*
|
|
*****************************************************************************/
|
|
BSTR StiEventHandlerLookup::getStiAppListForDeviceEvent(
|
|
const CSimpleStringWide &cswDeviceID,
|
|
const GUID &guidEvent)
|
|
{
|
|
BSTR bstrAppList = NULL;
|
|
|
|
//
|
|
// First, fill the list of event handlers.
|
|
//
|
|
FillListOfHandlers(cswDeviceID, guidEvent);
|
|
|
|
//
|
|
// m_ListOfHandlers now contains the handlers we need to put into a double NULL terminated list.
|
|
// First, we need to calculate the number of bytes needed to store the app list.
|
|
// For every StiEventHandlerInfo in the ListOfHandlers, add space for:
|
|
// <nl> App name plus terminating NULL.
|
|
// <nl> Prepared commandline plus terminating NULL.
|
|
// <nl>Lastly, add space for terminating NULL (ensuring that the list is double NULL terminated)
|
|
// Lastly, add space for terminating NULL (ensuring that the list is double NULL terminated)
|
|
//
|
|
int iNumHandlers = m_ListOfHandlers.Count();
|
|
int iSizeInBytes = 0;
|
|
CSimpleLinkedList<StiEventHandlerInfo*>::Iterator iter;
|
|
for (iter = m_ListOfHandlers.Begin(); iter != m_ListOfHandlers.End(); ++iter)
|
|
{
|
|
StiEventHandlerInfo *pStiEventHandlerInfo = *iter;
|
|
|
|
if (pStiEventHandlerInfo)
|
|
{
|
|
iSizeInBytes += (pStiEventHandlerInfo->getAppName().Length() * sizeof(WCHAR)) + sizeof(L'\0');
|
|
iSizeInBytes += (pStiEventHandlerInfo->getPreparedCommandline(cswDeviceID, guidEvent).Length() * sizeof(WCHAR)) + sizeof(L'\0');
|
|
}
|
|
}
|
|
|
|
//
|
|
// We now have the size, so allocate the space needed
|
|
//
|
|
bstrAppList = SysAllocStringByteLen(NULL, iSizeInBytes);
|
|
if (bstrAppList)
|
|
{
|
|
//
|
|
// Copy each null terminated string into the BSTR (including the terminating null),
|
|
// and make sure the end is double terminated.
|
|
//
|
|
WCHAR *wszDest = bstrAppList;
|
|
for (iter = m_ListOfHandlers.Begin(); iter != m_ListOfHandlers.End(); ++iter)
|
|
{
|
|
StiEventHandlerInfo *pStiEventHandlerInfo = *iter;
|
|
|
|
if (pStiEventHandlerInfo)
|
|
{
|
|
int iLengthAppName = pStiEventHandlerInfo->getAppName().Length() + 1;
|
|
int iLengthCommandline = pStiEventHandlerInfo->getPreparedCommandline(cswDeviceID, guidEvent).Length() + 1;
|
|
|
|
CSimpleString::GenericCopyLength(wszDest, pStiEventHandlerInfo->getAppName(), iLengthAppName);
|
|
wszDest += iLengthAppName;
|
|
CSimpleString::GenericCopyLength(wszDest, pStiEventHandlerInfo->getPreparedCommandline(cswDeviceID, guidEvent), iLengthCommandline);
|
|
wszDest += iLengthCommandline;
|
|
}
|
|
}
|
|
wszDest[0] = L'\0';
|
|
}
|
|
return bstrAppList;
|
|
}
|
|
|