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.
 
 
 
 
 
 

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;
}