/***************************************************************************** * (C) COPYRIGHT MICROSOFT CORPORATION, 2002 * * AUTHOR: ByronC * * DATE: 4/14/2002 * * @doc INTERNAL * * @module StiEventHandlerLookup.cpp - Implementation for | * * This file contains the implementation of the class. * *****************************************************************************/ #include "precomp.h" /***************************************************************************** * @doc INTERNAL * * @mfunc | StiEventHandlerLookup | StiEventHandlerLookup | * * We initialize all member variables. In general, this sets the values to 0, * except: * is set to be StiEventHandlerLookup_INIT_SIG. * 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: * - Call * * Also: * 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 object describing * the handler named

. * * @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 . 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::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 with * the appropriate Sti registered handlers. * * The hueristic used is: * 1. Get the "LaunchApplications" value for the event. * 2. For each App specified in the LauncApplications value, * create a and insert it into * . * 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 * 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 describing * the registered handler, and add it to . * * @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: * App1Name[NULL] * App1CommandLine[NULL] * App2Name[NULL] * App2CommandLine[NULL] * ...... * [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: // App name plus terminating NULL. // Prepared commandline plus terminating NULL. // 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::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; }