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.

522 lines
15 KiB

  1. #define __DEBUG_MODULE_IN_USE__ CIC_CONTROLITEMCOLLECTION_CPP
  2. #include "stdhdrs.h"
  3. // @doc
  4. /**********************************************************************
  5. *
  6. * @module ControlItemCollection.cpp |
  7. *
  8. * Implementation of CControlItemCollection implementation functions
  9. *
  10. * History
  11. * ----------------------------------------------------------
  12. * Mitchell S. Dernis Original
  13. *
  14. * (c) 1986-1998 Microsoft Corporation. All right reserved.
  15. *
  16. * @topic ControlItemCollection |
  17. * This library encapsulates HID parsing and driver packet code. It is
  18. * used it both the driver and the control panel applet.
  19. *
  20. **********************************************************************/
  21. /***********************************************************************************
  22. **
  23. ** CControlItemCollectionImpl::Init
  24. **
  25. ** @mfunc Initialize collection by calling factory to get items
  26. **
  27. ** @rdesc S_OK on success, S_FALSE if factory failed to support one or
  28. ** more of the items, E_FAIL if device not supported or error from factory
  29. **
  30. *************************************************************************************/
  31. HRESULT CControlItemCollectionImpl::Init(
  32. ULONG ulVidPid, //@parm [in] Vid in the high word, Pid in the low word
  33. PFNGENERICFACTORY pfnFactory, //@parm [in] pointer to function which acts
  34. // on pFactoryHandle
  35. PFNGENERICDELETEFUNC pfnDeleteFunc //@parm [in] delete function to used for control items
  36. )
  37. {
  38. CIC_DBG_ENTRY_PRINT(("CControlItemCollectionImpl::Init(0x%0.8x, 0x%0.8x)\n", ulVidPid, pfnFactory));
  39. HRESULT hr = S_OK;
  40. //
  41. // Walk the table devices and find a matching VidPid
  42. //
  43. ULONG ulDeviceIndex=0;
  44. //
  45. // Endless loop, you get out by breaking, or returning from the function.
  46. //
  47. while(1)
  48. {
  49. //
  50. // If we have reached the end of the table
  51. //
  52. if(0 == DeviceControlsDescList[ulDeviceIndex].ulVidPid )
  53. {
  54. ASSERT(FALSE); //Should never get here.
  55. return E_FAIL; //BUGBUGBUG need more descriptive error code here
  56. }
  57. if(DeviceControlsDescList[ulDeviceIndex].ulVidPid == ulVidPid)
  58. {
  59. break;
  60. }
  61. ulDeviceIndex++;
  62. }
  63. m_ulDeviceIndex = ulDeviceIndex;
  64. //
  65. // Use the size argument to pre-allocate space for the list
  66. //
  67. hr = m_ObjectList.SetAllocSize(DeviceControlsDescList[m_ulDeviceIndex].ulControlItemCount, NonPagedPool);
  68. if( FAILED(hr) )
  69. {
  70. return hr;
  71. }
  72. //
  73. // Set the delete function for the class
  74. //
  75. m_ObjectList.SetDeleteFunc(pfnDeleteFunc);
  76. //
  77. // Walk through the control item list and call the factory for each one
  78. //
  79. CONTROL_ITEM_DESC *pControlItems = reinterpret_cast<CONTROL_ITEM_DESC *>(DeviceControlsDescList[m_ulDeviceIndex].pControlItems);
  80. PVOID pNewControlItem;
  81. HRESULT hrFactory;
  82. m_ulMaxXfers = 0;
  83. for(
  84. ULONG ulControlIndex = 0;
  85. ulControlIndex < DeviceControlsDescList[m_ulDeviceIndex].ulControlItemCount;
  86. ulControlIndex++
  87. )
  88. {
  89. //
  90. // Call factory to get new control item
  91. //
  92. hrFactory = pfnFactory(pControlItems[ulControlIndex].usType, &pControlItems[ulControlIndex], &pNewControlItem);
  93. //
  94. // If the factory fails mark an error
  95. //
  96. if( FAILED(hrFactory) )
  97. {
  98. hr = hrFactory;
  99. continue;
  100. }
  101. //
  102. // If the factory does not support that control add a null to the list
  103. // to hold the index as taken
  104. //
  105. if( S_FALSE == hrFactory )
  106. {
  107. pNewControlItem = NULL;
  108. }
  109. else
  110. //an Xfer would be needed to get the state.
  111. {
  112. m_ulMaxXfers++;
  113. }
  114. //
  115. // Add item (or NULL) to list of items in collection
  116. //
  117. hrFactory = m_ObjectList.Add(pNewControlItem);
  118. if( FAILED(hrFactory) )
  119. {
  120. hr = hrFactory;
  121. }
  122. }
  123. //
  124. // Return error code
  125. //
  126. return hr;
  127. }
  128. /***********************************************************************************
  129. **
  130. ** HRESULT CControlItemCollectionImpl::GetNext
  131. **
  132. ** @mfunc Gets the next item in list
  133. **
  134. ** @rdesc S_OK on success, S_FALSE if no more items
  135. **
  136. ************************************************************************************/
  137. HRESULT CControlItemCollectionImpl::GetNext
  138. (
  139. PVOID *ppControlItem, //@parm pointer to receive control item
  140. ULONG& rulCookie //@parm cookie to keep track of enumeration
  141. ) const
  142. {
  143. CIC_DBG_RT_ENTRY_PRINT(("CControlItemCollectionImpl::GetNext(0x%0.8x, 0x%0.8x)\n", ppControlItem, rulCookie));
  144. if( rulCookie >= m_ObjectList.GetItemCount() )
  145. {
  146. *ppControlItem = NULL;
  147. CIC_DBG_EXIT_PRINT(("Exit GetNext - no more items\n"));
  148. return S_FALSE;
  149. }
  150. else
  151. {
  152. *ppControlItem = m_ObjectList.Get( rulCookie );
  153. rulCookie += 1;
  154. if(!*ppControlItem)
  155. {
  156. CIC_DBG_EXIT_PRINT(("Calling GetNext recursively\n"));
  157. return GetNext(ppControlItem, rulCookie);
  158. }
  159. CIC_DBG_RT_EXIT_PRINT(("Exit GetNext - *ppControlItem = 0x%0.8x\n", *ppControlItem));
  160. return S_OK;
  161. }
  162. }
  163. /***********************************************************************************
  164. **
  165. ** PVOID CControlItemCollectionImpl::GetFromControlItemXfer
  166. **
  167. ** @mfunc Returns item given CONTROL_ITEM_XFER
  168. **
  169. ** @rdesc Pointer to item on success, NULL if not
  170. **
  171. ************************************************************************************/
  172. PVOID CControlItemCollectionImpl::GetFromControlItemXfer(
  173. const CONTROL_ITEM_XFER& crControlItemXfer //@parm [in] report selector to get object for
  174. )
  175. {
  176. CIC_DBG_RT_ENTRY_PRINT(("CControlItemCollectionImpl::GetFromControlItemXfer\n"));
  177. ULONG ulListIndex = crControlItemXfer.ulItemIndex - 1;
  178. ASSERT( m_ObjectList.GetItemCount() > ulListIndex);
  179. if( m_ObjectList.GetItemCount() <= ulListIndex)
  180. {
  181. return NULL;
  182. }
  183. CIC_DBG_RT_EXIT_PRINT(("Exiting CControlItemCollectionImpl::GetFromControlItemXfer\n"));
  184. return m_ObjectList.Get(ulListIndex);
  185. }
  186. /***********************************************************************************
  187. **
  188. ** NTSTATUS CControlItemCollectionImpl::ReadFromReport
  189. **
  190. ** @mfunc Recurses collection and asks each item to read its state.
  191. **
  192. ** @rdesc Use NT_SUCCESS, NT_ERROR, SUCCEEDED, FAILED macros to parse.
  193. **
  194. ************************************************************************************/
  195. NTSTATUS CControlItemCollectionImpl::ReadFromReport
  196. (
  197. PHIDP_PREPARSED_DATA pHidPPreparsedData, //@parm hid preparsed data
  198. PCHAR pcReport, //@parm report buffer
  199. LONG lReportLength, //@parm length of report buffer
  200. PFNGETCONTROLITEM GetControlFromPtr //@parm pointer to function to get CControlItem *
  201. )
  202. {
  203. NTSTATUS NtStatus;
  204. NtStatus = ControlItemsFuncs::ReadModifiersFromReport(
  205. DeviceControlsDescList[m_ulDeviceIndex].pModifierDescTable,
  206. m_ulModifiers,
  207. pHidPPreparsedData,
  208. pcReport,
  209. lReportLength
  210. );
  211. if( NT_ERROR(NtStatus) )
  212. {
  213. CIC_DBG_ERROR_PRINT(("ReadModifiersFromReport returned 0x%0.8x\n", NtStatus));
  214. //
  215. // Instead of returning, let's go on, the modifiers are important, but
  216. // not important enough to cripple everything else.
  217. NtStatus = S_OK;
  218. }
  219. //
  220. // Loop over all items and read them
  221. //
  222. ULONG ulCookie = 0;
  223. PVOID pvControlItem = NULL;
  224. CControlItem *pControlItem;
  225. HRESULT hr;
  226. hr = GetNext(&pvControlItem, ulCookie);
  227. while(S_OK == hr)
  228. {
  229. pControlItem = GetControlFromPtr(pvControlItem);
  230. NtStatus= pControlItem->ReadFromReport(
  231. pHidPPreparsedData,
  232. pcReport,
  233. lReportLength
  234. );
  235. if( NT_ERROR(NtStatus) )
  236. {
  237. CIC_DBG_ERROR_PRINT(("pControlItem->ReadFromReport returned 0x%0.8x, ulCookie = 0x%0.8x\n", NtStatus, ulCookie));
  238. return NtStatus;
  239. }
  240. pControlItem->SetModifiers(m_ulModifiers);
  241. hr = GetNext(&pvControlItem, ulCookie);
  242. }
  243. return NtStatus;
  244. }
  245. /***********************************************************************************
  246. **
  247. ** NTSTATUS CControlItemCollectionImpl::WriteToReport
  248. **
  249. ** @mfunc Recurses collection and asks each item to write its state to the report.
  250. **
  251. ** @rdesc Use NT_SUCCESS, NT_ERROR, SUCCEEDED, FAILED macros to parse.
  252. **
  253. ************************************************************************************/
  254. NTSTATUS CControlItemCollectionImpl::WriteToReport
  255. (
  256. PHIDP_PREPARSED_DATA pHidPPreparsedData, //@parm hid preparsed data
  257. PCHAR pcReport, //@parm report buffer
  258. LONG lReportLength, //@parm length of report buffer
  259. PFNGETCONTROLITEM GetControlFromPtr //@parm pointer to function to get CControlItem *
  260. ) const
  261. {
  262. //
  263. // Loop over all items and write to them
  264. //
  265. NTSTATUS NtStatus;
  266. ULONG ulCookie = 0;
  267. PVOID pvControlItem = NULL;
  268. CControlItem *pControlItem;
  269. HRESULT hr;
  270. hr = GetNext(&pvControlItem, ulCookie);
  271. while(S_OK == hr)
  272. {
  273. pControlItem = GetControlFromPtr(pvControlItem);
  274. NtStatus= pControlItem->WriteToReport(
  275. pHidPPreparsedData,
  276. pcReport,
  277. lReportLength
  278. );
  279. if( NT_ERROR(NtStatus) )
  280. {
  281. CIC_DBG_ERROR_PRINT(("pControlItem->WriteToReport returned 0x%0.8x, ulCookie = 0x%0.8x\n", NtStatus, ulCookie));
  282. return NtStatus;
  283. }
  284. hr = GetNext(&pvControlItem, ulCookie);
  285. }
  286. if( FAILED(hr) )
  287. {
  288. ASSERT(SUCCEEDED(hr));
  289. return hr;
  290. }
  291. NtStatus = ControlItemsFuncs::WriteModifiersToReport(
  292. DeviceControlsDescList[m_ulDeviceIndex].pModifierDescTable,
  293. m_ulModifiers,
  294. pHidPPreparsedData,
  295. pcReport,
  296. lReportLength
  297. );
  298. return NtStatus;
  299. }
  300. /***********************************************************************************
  301. **
  302. ** NTSTATUS CControlItemCollectionImpl::WriteToReport
  303. **
  304. ** @mfunc Recurses collection and asks each item to set its self to its default state.
  305. **
  306. ** @rdesc Use NT_SUCCESS, NT_ERROR, SUCCEEDED, FAILED macros to parse.
  307. **
  308. ************************************************************************************/
  309. void CControlItemCollectionImpl::SetDefaultState
  310. (
  311. PFNGETCONTROLITEM GetControlFromPtr //@parm pointer to function to get CControlItem *
  312. )
  313. {
  314. ULONG ulCookie = 0;
  315. PVOID pvControlItem = NULL;
  316. CControlItem *pControlItem;
  317. HRESULT hr;
  318. hr = GetNext(&pvControlItem, ulCookie);
  319. while(S_OK == hr)
  320. {
  321. pControlItem = GetControlFromPtr(pvControlItem);
  322. pControlItem->SetDefaultState();
  323. hr = GetNext(&pvControlItem, ulCookie);
  324. }
  325. m_ulModifiers=0;
  326. }
  327. /***********************************************************************************
  328. **
  329. ** HRESULT CControlItemCollectionImpl::GetState
  330. **
  331. ** @mfunc Gets the state of each item in the collection and return it in the caller
  332. **
  333. ** @rdesc S_OK on success, E_OUTOFMEMORY if buffer is not large enough
  334. **
  335. *************************************************************************************/
  336. HRESULT CControlItemCollectionImpl::GetState
  337. (
  338. ULONG& ulXferCount, // @parm [in\out] specifies length of array on entry
  339. // and items used on exit
  340. PCONTROL_ITEM_XFER pControlItemXfers, // @parm [out] caller allocated buffer to hold packets
  341. PFNGETCONTROLITEM GetControlFromPtr // @parm [in] function to get CControlItem *
  342. )
  343. {
  344. HRESULT hr = S_OK;
  345. ULONG ulCookie = 0;
  346. ULONG ulXferMax = ulXferCount;
  347. PVOID pvControlItem = NULL;
  348. CControlItem *pControlItem;
  349. ulXferCount = 0;
  350. hr = GetNext(&pvControlItem, ulCookie);
  351. while(S_OK == hr)
  352. {
  353. pControlItem = GetControlFromPtr(pvControlItem);
  354. if( !pControlItem->IsDefaultState() )
  355. {
  356. if(ulXferCount >= ulXferMax)
  357. {
  358. hr = E_OUTOFMEMORY;
  359. }
  360. else
  361. {
  362. pControlItem->GetItemState(pControlItemXfers[ulXferCount]);
  363. pControlItemXfers[ulXferCount++].ulModifiers = m_ulModifiers;
  364. }
  365. }
  366. hr = GetNext(&pvControlItem, ulCookie);
  367. }
  368. return hr;
  369. }
  370. HRESULT CControlItemCollectionImpl::SetState
  371. (
  372. ULONG ulXferCount, // @parm [in\out] specifies length of array on entry
  373. // and items used on exit
  374. PCONTROL_ITEM_XFER pControlItemXfers, // @parm [out] caller allocated buffer to hold packets
  375. PFNGETCONTROLITEM GetControlFromPtr // @parm [in] function to get CControlItem *
  376. )
  377. {
  378. PVOID pvControlItem = NULL;
  379. CControlItem *pControlItem;
  380. while(ulXferCount--)
  381. {
  382. //
  383. // It is legit, that someone may have a keyboard Xfer mixed up in the
  384. // array, in which case we need to dismiss it. If someone further down
  385. // gets it, they will ASSERT.
  386. //
  387. if( NonGameDeviceXfer::IsKeyboardXfer(pControlItemXfers[ulXferCount]) )
  388. {
  389. continue;
  390. }
  391. pvControlItem = GetFromControlItemXfer( pControlItemXfers[ulXferCount]);
  392. if(NULL == pvControlItem) continue;
  393. m_ulModifiers |= pControlItemXfers[ulXferCount].ulModifiers;
  394. pControlItem = GetControlFromPtr(pvControlItem);
  395. pControlItem->SetModifiers(pControlItemXfers[ulXferCount].ulModifiers);
  396. pControlItem->SetItemState( pControlItemXfers[ulXferCount]);
  397. }
  398. return S_OK;
  399. }
  400. void CControlItemCollectionImpl::SetStateOverlayMode(
  401. PFNGETCONTROLITEM GetControlFromPtr,
  402. BOOLEAN fEnable
  403. )
  404. {
  405. ULONG ulCookie = 0;
  406. PVOID pvControlItem = NULL;
  407. CControlItem *pControlItem;
  408. HRESULT hr;
  409. hr = GetNext(&pvControlItem, ulCookie);
  410. while(S_OK == hr)
  411. {
  412. pControlItem = GetControlFromPtr(pvControlItem);
  413. pControlItem->SetStateOverlayMode(fEnable);
  414. hr = GetNext(&pvControlItem, ulCookie);
  415. }
  416. }
  417. /***********************************************************************************
  418. **
  419. ** HRESULT ControlItemDefaultFactory
  420. **
  421. ** @func Factory for a default collection
  422. **
  423. ** @rdesc S_OK if successful, S_FALSE if not supported, E_FAIL for any failure.
  424. **
  425. ************************************************************************************/
  426. HRESULT ControlItemDefaultFactory
  427. (
  428. USHORT usType, //@parm [in] Type of object to create
  429. const CONTROL_ITEM_DESC* cpControlItemDesc, //@parm [in] Item descriptor data
  430. CControlItem **ppControlItem //@parm [out] CControlItem we created
  431. )
  432. {
  433. HRESULT hr = S_OK;
  434. switch(usType)
  435. {
  436. case ControlItemConst::usAxes:
  437. *ppControlItem = new WDM_NON_PAGED_POOL CAxesItem(cpControlItemDesc);
  438. break;
  439. case ControlItemConst::usDPAD:
  440. *ppControlItem = new WDM_NON_PAGED_POOL CDPADItem(cpControlItemDesc);
  441. break;
  442. case ControlItemConst::usPropDPAD:
  443. *ppControlItem = new WDM_NON_PAGED_POOL CPropDPADItem(cpControlItemDesc);
  444. break;
  445. case ControlItemConst::usWheel:
  446. *ppControlItem= new WDM_NON_PAGED_POOL CWheelItem(cpControlItemDesc);
  447. break;
  448. case ControlItemConst::usPOV:
  449. *ppControlItem = new WDM_NON_PAGED_POOL CPOVItem(cpControlItemDesc);
  450. break;
  451. case ControlItemConst::usThrottle:
  452. *ppControlItem = new WDM_NON_PAGED_POOL CThrottleItem(cpControlItemDesc);
  453. break;
  454. case ControlItemConst::usRudder:
  455. *ppControlItem = new WDM_NON_PAGED_POOL CRudderItem(cpControlItemDesc);
  456. break;
  457. case ControlItemConst::usPedal:
  458. *ppControlItem = new WDM_NON_PAGED_POOL CPedalItem(cpControlItemDesc);
  459. break;
  460. case ControlItemConst::usButton:
  461. *ppControlItem = new WDM_NON_PAGED_POOL CButtonsItem(cpControlItemDesc);
  462. break;
  463. case ControlItemConst::usZoneIndicator:
  464. *ppControlItem = new WDM_NON_PAGED_POOL CZoneIndicatorItem(cpControlItemDesc);
  465. break;
  466. case ControlItemConst::usForceMap:
  467. *ppControlItem = new WDM_NON_PAGED_POOL CForceMapItem(cpControlItemDesc);
  468. break;
  469. case ControlItemConst::usDualZoneIndicator:
  470. *ppControlItem = new WDM_NON_PAGED_POOL CDualZoneIndicatorItem(cpControlItemDesc);
  471. break;
  472. default:
  473. *ppControlItem = NULL;
  474. return S_FALSE;
  475. }
  476. if(!*ppControlItem)
  477. {
  478. return E_FAIL;
  479. }
  480. return S_OK;
  481. }