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

  1. /*****************************************************************************
  2. * (C) COPYRIGHT MICROSOFT CORPORATION, 2002
  3. *
  4. * AUTHOR: ByronC
  5. *
  6. * DATE: 4/14/2002
  7. *
  8. * @doc INTERNAL
  9. *
  10. * @module StiEventHandlerLookup.cpp - Implementation for <c StiEventHandlerLookup> |
  11. *
  12. * This file contains the implementation of the <c StiEventHandlerLookup> class.
  13. *
  14. *****************************************************************************/
  15. #include "precomp.h"
  16. /*****************************************************************************
  17. * @doc INTERNAL
  18. *
  19. * @mfunc | StiEventHandlerLookup | StiEventHandlerLookup |
  20. *
  21. * We initialize all member variables. In general, this sets the values to 0,
  22. * except:
  23. * <nl><md StiEventHandlerLookup::m_ulSig> is set to be StiEventHandlerLookup_INIT_SIG.
  24. * <nl><md StiEventHandlerLookup::m_cRef> is set to be 1.
  25. *
  26. *****************************************************************************/
  27. StiEventHandlerLookup::StiEventHandlerLookup() :
  28. m_ulSig(StiEventHandlerLookup_INIT_SIG),
  29. m_cRef(1)
  30. {
  31. }
  32. /*****************************************************************************
  33. * @doc INTERNAL
  34. *
  35. * @mfunc | StiEventHandlerLookup | ~StiEventHandlerLookup |
  36. *
  37. * Do any cleanup that is not already done. We:
  38. * <nl> - Call <mf StiEventHandlerLookup::ClearListOfHandlers>
  39. *
  40. * Also:
  41. * <nl><md StiEventHandlerLookup::m_ulSig> is set to be StiEventHandlerLookup_DEL_SIG.
  42. *
  43. *****************************************************************************/
  44. StiEventHandlerLookup::~StiEventHandlerLookup()
  45. {
  46. m_ulSig = StiEventHandlerLookup_DEL_SIG;
  47. m_cRef = 0;
  48. ClearListOfHandlers();
  49. }
  50. /*****************************************************************************
  51. * @doc INTERNAL
  52. *
  53. * @mfunc ULONG | StiEventHandlerLookup | AddRef |
  54. *
  55. * Increments this object's ref count. We should always AddRef when handing
  56. * out a pointer to this object.
  57. *
  58. * @rvalue Count |
  59. * The reference count after the count has been incremented.
  60. *****************************************************************************/
  61. ULONG __stdcall StiEventHandlerLookup::AddRef()
  62. {
  63. InterlockedIncrement((long*) &m_cRef);
  64. return m_cRef;
  65. }
  66. /*****************************************************************************
  67. * @doc INTERNAL
  68. *
  69. * @mfunc ULONG | StiEventHandlerLookup | Release |
  70. *
  71. * Decrement this object's ref count. We should always Release when finished
  72. * with a pointer to this object.
  73. *
  74. * @rvalue Count |
  75. * The reference count after the count has been decremented.
  76. *****************************************************************************/
  77. ULONG __stdcall StiEventHandlerLookup::Release()
  78. {
  79. ULONG ulRefCount = m_cRef - 1;
  80. if (InterlockedDecrement((long*) &m_cRef) == 0)
  81. {
  82. delete this;
  83. return 0;
  84. }
  85. return ulRefCount;
  86. }
  87. /*****************************************************************************
  88. * @doc INTERNAL
  89. *
  90. * @mfunc bool | StiEventHandlerLookup | getHandlerFromName |
  91. *
  92. * This method is used to create a <c StiEventHandlerInfo> object describing
  93. * the handler named <p cswHandlerName>.
  94. *
  95. * @parm const CSimpleStringWide & | cswHandlerName |
  96. * The STI handler name registered under the StillImage software key.
  97. *
  98. * @rvalue NULL |
  99. * The handler was not found, therefore no information was returned.
  100. * @rvalue non-NULL |
  101. * A pointer to a new <c StiEventHandlerInfo>. Caller must release.
  102. *****************************************************************************/
  103. StiEventHandlerInfo* StiEventHandlerLookup::getHandlerFromName(
  104. const CSimpleStringWide &cswHandlerName)
  105. {
  106. StiEventHandlerInfo *pStiEventHandlerInfo = NULL;
  107. CSimpleReg csrGlobalHandlers(HKEY_LOCAL_MACHINE, STI_GLOBAL_EVENT_HANDLER_PATH, false, KEY_READ);
  108. CSimpleStringWide cswCommandline = csrGlobalHandlers.Query(cswHandlerName, L"");
  109. if (cswCommandline.Length() > 0)
  110. {
  111. pStiEventHandlerInfo = new StiEventHandlerInfo(cswHandlerName,
  112. cswCommandline);
  113. }
  114. return pStiEventHandlerInfo;
  115. }
  116. /*****************************************************************************
  117. * @doc INTERNAL
  118. *
  119. * @mfunc VOID | StiEventHandlerLookup | ClearListOfHandlers |
  120. *
  121. * Frees resources associated with our list of handlers
  122. *
  123. *****************************************************************************/
  124. VOID StiEventHandlerLookup::ClearListOfHandlers()
  125. {
  126. CSimpleLinkedList<StiEventHandlerInfo*>::Iterator iter;
  127. for (iter = m_ListOfHandlers.Begin(); iter != m_ListOfHandlers.End(); ++iter)
  128. {
  129. StiEventHandlerInfo *pStiEventHandlerInfo = *iter;
  130. if (pStiEventHandlerInfo)
  131. {
  132. pStiEventHandlerInfo->Release();
  133. }
  134. }
  135. m_ListOfHandlers.Destroy();
  136. }
  137. /*****************************************************************************
  138. * @doc INTERNAL
  139. *
  140. * @mfunc VOID | StiEventHandlerLookup | FillListOfHandlers |
  141. *
  142. * This method fills the <md StiEventHandlerLookup::m_ListOfHandlers> with
  143. * the appropriate Sti registered handlers.
  144. *
  145. * The hueristic used is:
  146. * <nl>1. Get the "LaunchApplications" value for the event.
  147. * <nl>2. For each App specified in the LauncApplications value,
  148. * create a <c StiEventHandlerInfo> and insert it into
  149. * <md StiEventHandlerLookup::m_ListOfHandlers>.
  150. * Note: If the "LaunchApplications" value == "*", then
  151. * we get all STI registered apps.
  152. *
  153. * Note that this method will destroy the existing list of handlers by calling
  154. * <mf ClearListOfHandlers::FillListOfHandlers> as it's first operation.
  155. *
  156. * @parm const CSimpleStringWide & | cswDeviceID |
  157. * The Device on which the event occured
  158. * @parm const GUID & | guidEvent |
  159. * The Event generated by the device
  160. *****************************************************************************/
  161. VOID StiEventHandlerLookup::FillListOfHandlers(
  162. const CSimpleStringWide &cswDeviceID,
  163. const GUID &guidEvent)
  164. {
  165. WiaDeviceKey wiaDeviceKey(cswDeviceID);
  166. CSimpleStringWide cswEventKeyPath = wiaDeviceKey.getDeviceEventKeyPath(guidEvent);
  167. ClearListOfHandlers();
  168. //
  169. // If we can find the device event key, then
  170. // read the LaunchApplications value for this key.
  171. // If it was not found, then we assume this is a bogus event for
  172. // this device, so we do nothing.
  173. //
  174. if (cswEventKeyPath.Length() > 0)
  175. {
  176. CSimpleReg csrEventKey(HKEY_LOCAL_MACHINE, cswEventKeyPath, false, KEY_READ);
  177. CSimpleStringWide cswLaunchApplicationsValue = csrEventKey.Query(STI_LAUNCH_APPPLICATIONS_VALUE,
  178. STI_LAUNCH_WILDCARD);
  179. //
  180. // Check whether the value is a wildcard or not. If it is, we need to process all globally
  181. // registered STI Apps.
  182. // If it isn't, only add the ones that are specified in the value (it is a
  183. // comma separated list of Handler names).
  184. //
  185. if (cswLaunchApplicationsValue.CompareNoCase(STI_LAUNCH_WILDCARD) == 0)
  186. {
  187. CSimpleReg csrRegisteredAppsKey(HKEY_LOCAL_MACHINE, STI_GLOBAL_EVENT_HANDLER_PATH, false, KEY_READ);
  188. //
  189. // Enumerate through all the handler values in the globally registered and add them to the list
  190. //
  191. bool bReturnIgnored = csrRegisteredAppsKey.EnumValues(StiEventHandlerLookup::ProcessHandlers,
  192. (LPARAM)this);
  193. }
  194. else
  195. {
  196. StiEventHandlerInfo *pStiEventHandlerInfo = NULL;
  197. //
  198. // Walk through each element of the comma separated list and add it as a new handler
  199. //
  200. StiEventHandlerLookup::SimpleStringTokenizer simpleStringTokenizer(cswLaunchApplicationsValue,
  201. STI_LAUNCH_SEPARATOR);
  202. for (CSimpleStringWide cswAppName = simpleStringTokenizer.getNextToken();
  203. cswAppName.Length() > 0;
  204. cswAppName = simpleStringTokenizer.getNextToken())
  205. {
  206. pStiEventHandlerInfo = getHandlerFromName(cswAppName);
  207. if (pStiEventHandlerInfo)
  208. {
  209. //
  210. // Handler was found, so add it to the list
  211. //
  212. m_ListOfHandlers.Append(pStiEventHandlerInfo);
  213. pStiEventHandlerInfo = NULL;
  214. }
  215. else
  216. {
  217. //
  218. // Handler not found, so don't add it to the list. This could happen
  219. // if user chose to list a specific set of apps to choose from, but one
  220. // of the apps in the list has subsequently been unregistered.
  221. //
  222. }
  223. }
  224. }
  225. }
  226. }
  227. /*****************************************************************************
  228. * @doc INTERNAL
  229. *
  230. * @mfunc bool | StiEventHandlerLookup | ProcessHandlers |
  231. *
  232. * This method is called on each value of the registered handlers key.
  233. * Our current behavior is to create a new <c StiEventHandlerInfo> describing
  234. * the registered handler, and add it to <md StiEventHandlerLookup::m_ListOfHandlers>.
  235. *
  236. * @parm CValueEnumInfo& | enumInfo |
  237. * Indicates the current value we're on.
  238. *
  239. * @rvalue true |
  240. * This method always returns true. (Returning false would cause a
  241. * enumeration to stop, but we want to enumerate all values)
  242. *****************************************************************************/
  243. bool StiEventHandlerLookup::ProcessHandlers(
  244. CSimpleReg::CValueEnumInfo &enumInfo)
  245. {
  246. //
  247. // Check that we have a This pointer
  248. //
  249. StiEventHandlerLookup *This = (StiEventHandlerLookup*)enumInfo.lParam;
  250. if (This)
  251. {
  252. //
  253. // Create a new StiEventHandlerInfo describing this handler
  254. //
  255. StiEventHandlerInfo *pStiEventHandlerInfo = NULL;
  256. pStiEventHandlerInfo = This->getHandlerFromName(enumInfo.strName);
  257. if (pStiEventHandlerInfo)
  258. {
  259. //
  260. // Handler was found, so add it to the list
  261. //
  262. This->m_ListOfHandlers.Append(pStiEventHandlerInfo);
  263. pStiEventHandlerInfo = NULL;
  264. }
  265. }
  266. return true;
  267. }
  268. /*****************************************************************************
  269. * @doc INTERNAL
  270. *
  271. * @mfunc BSTR | StiEventHandlerLookup | getStiAppListForDeviceEvent |
  272. *
  273. * This method returns a double NULL-terminated BSTR containing multiple
  274. * strings. The format of the string is:
  275. * <nl>App1Name[NULL]
  276. * <nl>App1CommandLine[NULL]
  277. * <nl>App2Name[NULL]
  278. * <nl>App2CommandLine[NULL]
  279. * <nl>......
  280. * <nl>[NULL]
  281. *
  282. * Caller must free.
  283. *
  284. * @parm const CSimpleStringWide & | cswDeviceID |
  285. * The STI device ID indicating which device generated the event
  286. * @parm const GUID & | guidEvent |
  287. * The event guid indicating the device event
  288. *
  289. * @rvalue NULL |
  290. * We could not create a list of registered STI handlers. This is normal
  291. * if there are no applications registered for StillImage events.
  292. * @rvalue non-NULL |
  293. * This contains a double NULL terminated string list. Caller must free.
  294. *
  295. *****************************************************************************/
  296. BSTR StiEventHandlerLookup::getStiAppListForDeviceEvent(
  297. const CSimpleStringWide &cswDeviceID,
  298. const GUID &guidEvent)
  299. {
  300. BSTR bstrAppList = NULL;
  301. //
  302. // First, fill the list of event handlers.
  303. //
  304. FillListOfHandlers(cswDeviceID, guidEvent);
  305. //
  306. // m_ListOfHandlers now contains the handlers we need to put into a double NULL terminated list.
  307. // First, we need to calculate the number of bytes needed to store the app list.
  308. // For every StiEventHandlerInfo in the ListOfHandlers, add space for:
  309. // <nl> App name plus terminating NULL.
  310. // <nl> Prepared commandline plus terminating NULL.
  311. // <nl>Lastly, add space for terminating NULL (ensuring that the list is double NULL terminated)
  312. // Lastly, add space for terminating NULL (ensuring that the list is double NULL terminated)
  313. //
  314. int iNumHandlers = m_ListOfHandlers.Count();
  315. int iSizeInBytes = 0;
  316. CSimpleLinkedList<StiEventHandlerInfo*>::Iterator iter;
  317. for (iter = m_ListOfHandlers.Begin(); iter != m_ListOfHandlers.End(); ++iter)
  318. {
  319. StiEventHandlerInfo *pStiEventHandlerInfo = *iter;
  320. if (pStiEventHandlerInfo)
  321. {
  322. iSizeInBytes += (pStiEventHandlerInfo->getAppName().Length() * sizeof(WCHAR)) + sizeof(L'\0');
  323. iSizeInBytes += (pStiEventHandlerInfo->getPreparedCommandline(cswDeviceID, guidEvent).Length() * sizeof(WCHAR)) + sizeof(L'\0');
  324. }
  325. }
  326. //
  327. // We now have the size, so allocate the space needed
  328. //
  329. bstrAppList = SysAllocStringByteLen(NULL, iSizeInBytes);
  330. if (bstrAppList)
  331. {
  332. //
  333. // Copy each null terminated string into the BSTR (including the terminating null),
  334. // and make sure the end is double terminated.
  335. //
  336. WCHAR *wszDest = bstrAppList;
  337. for (iter = m_ListOfHandlers.Begin(); iter != m_ListOfHandlers.End(); ++iter)
  338. {
  339. StiEventHandlerInfo *pStiEventHandlerInfo = *iter;
  340. if (pStiEventHandlerInfo)
  341. {
  342. int iLengthAppName = pStiEventHandlerInfo->getAppName().Length() + 1;
  343. int iLengthCommandline = pStiEventHandlerInfo->getPreparedCommandline(cswDeviceID, guidEvent).Length() + 1;
  344. CSimpleString::GenericCopyLength(wszDest, pStiEventHandlerInfo->getAppName(), iLengthAppName);
  345. wszDest += iLengthAppName;
  346. CSimpleString::GenericCopyLength(wszDest, pStiEventHandlerInfo->getPreparedCommandline(cswDeviceID, guidEvent), iLengthCommandline);
  347. wszDest += iLengthCommandline;
  348. }
  349. }
  350. wszDest[0] = L'\0';
  351. }
  352. return bstrAppList;
  353. }