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.

1463 lines
40 KiB

  1. /*****************************************************************************
  2. *
  3. * DIGenM.c
  4. *
  5. * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * Practice generic IDirectInputDevice callback for mouse.
  10. *
  11. * Contents:
  12. *
  13. * CMouse_New
  14. *
  15. *****************************************************************************/
  16. #include "dinputpr.h"
  17. /*****************************************************************************
  18. *
  19. * The sqiffle for this file.
  20. *
  21. *****************************************************************************/
  22. #define sqfl sqflMouse
  23. /*****************************************************************************
  24. *
  25. * Declare the interfaces we will be providing.
  26. *
  27. *****************************************************************************/
  28. Primary_Interface(CMouse, IDirectInputDeviceCallback);
  29. Interface_Template_Begin(CMouse)
  30. Primary_Interface_Template(CMouse, IDirectInputDeviceCallback)
  31. Interface_Template_End(CMouse)
  32. /*****************************************************************************
  33. *
  34. * @doc INTERNAL
  35. *
  36. * @global DIOBJECTDATAFORMAT | c_rgodfMouse[] |
  37. *
  38. * Device object data formats for the generic mouse device.
  39. * The axes come first, then the buttons.
  40. *
  41. *****************************************************************************/
  42. #pragma BEGIN_CONST_DATA
  43. #define MAKEODF(guid, f, type, inst, aspect) \
  44. { &GUID_##guid, \
  45. FIELD_OFFSET(DIMOUSESTATE_INT, f), \
  46. DIDFT_##type | DIDFT_MAKEINSTANCE(inst), \
  47. DIDOI_ASPECT##aspect, \
  48. } \
  49. /*
  50. * Warning! If you change this table, you must adjust the IDS_MOUSEOBJECT
  51. * table in dinput.rc to match!
  52. */
  53. DIOBJECTDATAFORMAT c_rgodfMouse[] = {
  54. MAKEODF( XAxis, lX, RELAXIS, 0, POSITION),
  55. MAKEODF( YAxis, lY, RELAXIS, 1, POSITION),
  56. MAKEODF( ZAxis, lZ, RELAXIS, 2, POSITION),
  57. MAKEODF(Button, rgbButtons[0], PSHBUTTON, 3, UNKNOWN),
  58. MAKEODF(Button, rgbButtons[1], PSHBUTTON, 4, UNKNOWN),
  59. MAKEODF(Button, rgbButtons[2], PSHBUTTON, 5, UNKNOWN),
  60. MAKEODF(Button, rgbButtons[3], PSHBUTTON, 6, UNKNOWN),
  61. MAKEODF(Button, rgbButtons[4], PSHBUTTON, 7, UNKNOWN),
  62. MAKEODF(Button, rgbButtons[5], PSHBUTTON, 8, UNKNOWN),
  63. MAKEODF(Button, rgbButtons[6], PSHBUTTON, 9, UNKNOWN),
  64. MAKEODF(Button, rgbButtons[7], PSHBUTTON,10, UNKNOWN),
  65. };
  66. #define c_podfMouseAxes (&c_rgodfMouse[0])
  67. #define c_podfMouseButtons (&c_rgodfMouse[3])
  68. #pragma END_CONST_DATA
  69. /*****************************************************************************
  70. *
  71. * @doc INTERNAL
  72. *
  73. * @struct CMouse |
  74. *
  75. * The <i IDirectInputDeviceCallback> object for the generic mouse.
  76. *
  77. * @field IDirectInputDeviceCalllback | didc |
  78. *
  79. * The object (containing vtbl).
  80. *
  81. * @field LPDIMOUSESTATE_INT | pdmsPhys |
  82. *
  83. * Pointer to physical mouse status information kept down in the
  84. * VxD.
  85. *
  86. * @field POINT | ptPrev |
  87. *
  88. * Location of the mouse at the time we stole it exclusively.
  89. *
  90. * @field HWND | hwndCaptured |
  91. *
  92. * The window that captured the mouse.
  93. *
  94. * @field VXDINSTANCE * | pvi |
  95. *
  96. * The DirectInput instance handle. Even though we manipulate
  97. * the flags field, we do not need to mark it volatile because
  98. * we modify the flags only when unacquired, whereas the device
  99. * driver modifies the flags only when acquired.
  100. *
  101. * @field UINT | dwAxes |
  102. *
  103. * Number of axes on the mouse.
  104. *
  105. * @field UINT | dwButtons |
  106. *
  107. * Number of buttons on the mouse.
  108. *
  109. * @field DWORD | flEmulation |
  110. *
  111. * The emulation flags forced by the application. If any of
  112. * these flags is set (actually, at most one will be set), then
  113. * we are an alias device.
  114. *
  115. * @field DIDATAFORMAT | df |
  116. *
  117. * The dynamically-generated data format based on the
  118. * mouse type.
  119. *
  120. * @field DIOBJECTDATAFORMAT | rgodf[] |
  121. *
  122. * Object data format table generated as part of the
  123. * <e CMouse.df>.
  124. *
  125. * @comm
  126. *
  127. * It is the caller's responsibility to serialize access as
  128. * necessary.
  129. *
  130. *****************************************************************************/
  131. typedef struct CMouse {
  132. /* Supported interfaces */
  133. IDirectInputDeviceCallback dcb;
  134. LPDIMOUSESTATE_INT pdmsPhys; /* Physical mouse state */
  135. POINT ptPrev;
  136. HWND hwndCapture;
  137. VXDINSTANCE *pvi;
  138. UINT dwAxes;
  139. UINT dwButtons;
  140. DWORD flEmulation;
  141. DIDATAFORMAT df;
  142. DIOBJECTDATAFORMAT rgodf[cA(c_rgodfMouse)];
  143. } CMouse, DM, *PDM;
  144. #define ThisClass CMouse
  145. #define ThisInterface IDirectInputDeviceCallback
  146. #define riidExpected &IID_IDirectInputDeviceCallback
  147. /*****************************************************************************
  148. *
  149. * CMouse::QueryInterface (from IUnknown)
  150. * CMouse::AddRef (from IUnknown)
  151. * CMouse::Release (from IUnknown)
  152. *
  153. *****************************************************************************/
  154. /*****************************************************************************
  155. *
  156. * @doc INTERNAL
  157. *
  158. * @method HRESULT | CMouse | QueryInterface |
  159. *
  160. * Gives a client access to other interfaces on an object.
  161. *
  162. * @cwrap LPDIRECTINPUT | lpDirectInput
  163. *
  164. * @parm IN REFIID | riid |
  165. *
  166. * The requested interface's IID.
  167. *
  168. * @parm OUT LPVOID * | ppvObj |
  169. *
  170. * Receives a pointer to the obtained interface.
  171. *
  172. * @returns
  173. *
  174. * Returns a COM error code.
  175. *
  176. * @xref OLE documentation for <mf IUnknown::QueryInterface>.
  177. *
  178. *****************************************************************************
  179. *
  180. * @doc INTERNAL
  181. *
  182. * @method HRESULT | CMouse | AddRef |
  183. *
  184. * Increments the reference count for the interface.
  185. *
  186. * @cwrap LPDIRECTINPUT | lpDirectInput
  187. *
  188. * @returns
  189. *
  190. * Returns the object reference count.
  191. *
  192. * @xref OLE documentation for <mf IUnknown::AddRef>.
  193. *
  194. *****************************************************************************
  195. *
  196. * @doc INTERNAL
  197. *
  198. * @method HRESULT | CMouse | Release |
  199. *
  200. * Decrements the reference count for the interface.
  201. * If the reference count on the object falls to zero,
  202. * the object is freed from memory.
  203. *
  204. * @cwrap LPDIRECTINPUT | lpDirectInput
  205. *
  206. * @returns
  207. *
  208. * Returns the object reference count.
  209. *
  210. * @xref OLE documentation for <mf IUnknown::Release>.
  211. *
  212. *****************************************************************************
  213. *
  214. * @doc INTERNAL
  215. *
  216. * @method HRESULT | CMouse | QIHelper |
  217. *
  218. * We don't have any dynamic interfaces and simply forward
  219. * to <f Common_QIHelper>.
  220. *
  221. * @parm IN REFIID | riid |
  222. *
  223. * The requested interface's IID.
  224. *
  225. * @parm OUT LPVOID * | ppvObj |
  226. *
  227. * Receives a pointer to the obtained interface.
  228. *
  229. *****************************************************************************
  230. *
  231. * @doc INTERNAL
  232. *
  233. * @method HRESULT | CMouse | AppFinalize |
  234. *
  235. * We don't have any weak pointers, so we can just
  236. * forward to <f Common_Finalize>.
  237. *
  238. * @parm PV | pvObj |
  239. *
  240. * Object being released from the application's perspective.
  241. *
  242. *****************************************************************************/
  243. #ifdef DEBUG
  244. Default_QueryInterface(CMouse)
  245. Default_AddRef(CMouse)
  246. Default_Release(CMouse)
  247. #else
  248. #define CMouse_QueryInterface Common_QueryInterface
  249. #define CMouse_AddRef Common_AddRef
  250. #define CMouse_Release Common_Release
  251. #endif
  252. #define CMouse_QIHelper Common_QIHelper
  253. #define CMouse_AppFinalize Common_AppFinalize
  254. /*****************************************************************************
  255. *
  256. * @doc INTERNAL
  257. *
  258. * @func void | CMouse_Finalize |
  259. *
  260. * Releases the resources of the device.
  261. *
  262. * @parm PV | pvObj |
  263. *
  264. * Object being released. Note that it may not have been
  265. * completely initialized, so everything should be done
  266. * carefully.
  267. *
  268. *****************************************************************************/
  269. void INTERNAL
  270. CMouse_Finalize(PV pvObj)
  271. {
  272. PDM this = pvObj;
  273. if (this->pvi) {
  274. HRESULT hres;
  275. hres = Hel_DestroyInstance(this->pvi);
  276. AssertF(SUCCEEDED(hres));
  277. }
  278. }
  279. /*****************************************************************************
  280. *
  281. * @doc INTERNAL
  282. *
  283. * @method void | CMouse | GetPhysicalPosition |
  284. *
  285. * Read the physical mouse position into <p pmstOut>.
  286. *
  287. * Note that it doesn't matter if this is not atomic.
  288. * If a mouse motion occurs while we are reading it,
  289. * we will get a mix of old and new data. No big deal.
  290. *
  291. * @parm PDM | this |
  292. *
  293. * The object in question.
  294. *
  295. * @parm LPDIMOUSESTATE_INT | pdmsOut |
  296. *
  297. * Where to put the mouse position.
  298. * @returns
  299. * None.
  300. *
  301. *****************************************************************************/
  302. void INLINE
  303. CMouse_GetPhysicalPosition(PDM this, LPDIMOUSESTATE_INT pdmsOut)
  304. {
  305. AssertF(this->pdmsPhys);
  306. *pdmsOut = *this->pdmsPhys;
  307. }
  308. /*****************************************************************************
  309. *
  310. * @doc INTERNAL
  311. *
  312. * @method HRESULT | CMouse | Acquire |
  313. *
  314. * Tell the device driver to begin data acquisition.
  315. * Give the device driver the current mouse button states
  316. * in case it needs them.
  317. *
  318. * It is the caller's responsibility to have set the
  319. * data format before obtaining acquisition.
  320. *
  321. * @returns
  322. *
  323. * Returns a COM error code. The following error codes are
  324. * intended to be illustrative and not necessarily comprehensive.
  325. *
  326. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  327. *
  328. * <c S_FALSE>: The operation was begun and should be completed
  329. * by the caller by communicating with the <t VXDINSTANCE>.
  330. *
  331. *****************************************************************************/
  332. STDMETHODIMP
  333. CMouse_Acquire(PDICB pdcb)
  334. {
  335. HRESULT hres;
  336. PDM this;
  337. VXDDWORDDATA vdd;
  338. DWORD mef;
  339. EnterProcI(IDirectInputDeviceCallback::Mouse::Acquire,
  340. (_ "p", pdcb));
  341. /*
  342. * This is an internal interface, so we can skimp on validation.
  343. */
  344. this = _thisPvNm(pdcb, dcb);
  345. AssertF(this->pvi);
  346. vdd.pvi = this->pvi;
  347. vdd.dw = 0;
  348. /*
  349. * Collect information about which buttons are down.
  350. */
  351. mef = 0;
  352. if (GetAsyncKeyState(VK_LBUTTON) < 0) {
  353. mef |= MOUSEEVENTF_LEFTUP;
  354. vdd.dw |= 0x80;
  355. }
  356. if (GetAsyncKeyState(VK_RBUTTON) < 0) {
  357. mef |= MOUSEEVENTF_RIGHTUP;
  358. vdd.dw |= 0x8000;
  359. }
  360. if (GetAsyncKeyState(VK_MBUTTON) < 0) {
  361. mef |= MOUSEEVENTF_MIDDLEUP;
  362. vdd.dw |= 0x800000;
  363. }
  364. /*
  365. * HACKHACK - This, strictly speaking, belongs in dihel.c,
  366. * but we need to maintain some state, and it's easier to
  367. * put the state in our own object.
  368. */
  369. /*
  370. * A bit of work needs to be done at ring 3 now.
  371. */
  372. if (this->pvi->fl & VIFL_CAPTURED) {
  373. RECT rc;
  374. /*
  375. * Hide the mouse cursor (for compatibility with NT emulation)
  376. */
  377. GetCursorPos(&this->ptPrev);
  378. GetWindowRect(this->hwndCapture, &rc);
  379. SetCursorPos((rc.left + rc.right) >> 1,
  380. (rc.top + rc.bottom) >> 1);
  381. ShowCursor(0);
  382. if (!(this->pvi->fl & VIFL_EMULATED)) {
  383. /*
  384. * Force all mouse buttons up from USER's point of view
  385. * to avoid "stuck mouse button" problems. However, don't
  386. * force a button up unless it is actually down.
  387. */
  388. if (mef) {
  389. mouse_event(mef, 0, 0, 0, 0);
  390. }
  391. }
  392. }
  393. if (!(this->pvi->fl & VIFL_EMULATED)) {
  394. hres = IoctlHw(IOCTL_MOUSE_INITBUTTONS, &vdd.dw, cbX(vdd.dw), 0, 0);
  395. } else {
  396. #ifdef USE_WM_INPUT
  397. if( g_fRawInput ) {
  398. hres = CDIRaw_Mouse_InitButtons();
  399. }
  400. #endif
  401. hres = CEm_Mouse_InitButtons(&vdd);
  402. }
  403. AssertF(SUCCEEDED(hres));
  404. hres = S_FALSE; /* Please finish for me */
  405. ExitOleProcR();
  406. return hres;
  407. }
  408. /*****************************************************************************
  409. *
  410. * @doc INTERNAL
  411. *
  412. * @method HRESULT | CMouse | Unacquire |
  413. *
  414. * Tell the device driver to stop data acquisition.
  415. *
  416. * It is the caller's responsibility to call this only
  417. * when the device has been acquired.
  418. *
  419. * @returns
  420. *
  421. * Returns a COM error code. The following error codes are
  422. * intended to be illustrative and not necessarily comprehensive.
  423. *
  424. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  425. *
  426. * <c S_FALSE>: The operation was begun and should be completed
  427. * by the caller by communicating with the <t VXDINSTANCE>.
  428. *
  429. *****************************************************************************/
  430. STDMETHODIMP
  431. CMouse_Unacquire(PDICB pdcb)
  432. {
  433. HRESULT hres;
  434. PDM this;
  435. #ifdef WANT_TO_FIX_MANBUG43879
  436. DWORD mef;
  437. #endif
  438. EnterProcI(IDirectInputDeviceCallback::Mouse::Unacquire,
  439. (_ "p", pdcb));
  440. /*
  441. * This is an internal interface, so we can skimp on validation.
  442. */
  443. this = _thisPvNm(pdcb, dcb);
  444. AssertF(this->pvi);
  445. #ifdef WANT_TO_FIX_MANBUG43879
  446. /*
  447. * Collect information about which buttons are down.
  448. */
  449. mef = 0;
  450. if (GetAsyncKeyState(VK_LBUTTON) < 0) {
  451. mef |= MOUSEEVENTF_LEFTUP;
  452. }
  453. if (GetAsyncKeyState(VK_RBUTTON) < 0) {
  454. mef |= MOUSEEVENTF_RIGHTUP;
  455. }
  456. if (GetAsyncKeyState(VK_MBUTTON) < 0) {
  457. mef |= MOUSEEVENTF_MIDDLEUP;
  458. }
  459. if (this->pvi->fl & VIFL_FOREGROUND) {
  460. /*
  461. * Force all mouse buttons up from USER's point of view
  462. * to avoid "stuck mouse button" problems. However, don't
  463. * force a button up unless it is actually down.
  464. * This could happen if DInput loses UP events due to slow
  465. * low-level hook. See bug: 43879.
  466. */
  467. if (mef) {
  468. mouse_event(mef, 0, 0, 0, 0);
  469. }
  470. }
  471. #endif
  472. /*
  473. * HACKHACK - This is the corresponding half of the HACKHACK
  474. * in CMouse_Acquire.
  475. */
  476. /*
  477. * A bit of work needs to be done at ring 3 now.
  478. */
  479. if (this->pvi->fl & VIFL_CAPTURED) {
  480. RECT rcDesk;
  481. RECT rcApp;
  482. /*
  483. * Reposition and restore the mouse cursor
  484. * (for compatibility with NT emulation)
  485. *
  486. * Do not reposition the mouse cursor if we lost to a
  487. * window that covers the screen. Otherwise, our
  488. * repositioning will nuke the screen saver.
  489. */
  490. GetWindowRect(GetDesktopWindow(), &rcDesk);
  491. GetWindowRect(GetForegroundWindow(), &rcApp);
  492. SubtractRect(&rcDesk, &rcDesk, &rcApp);
  493. if (!IsRectEmpty(&rcDesk)) {
  494. SetCursorPos(this->ptPrev.x, this->ptPrev.y);
  495. }
  496. ShowCursor(1);
  497. }
  498. hres = S_FALSE;
  499. ExitOleProcR();
  500. return hres;
  501. }
  502. /*****************************************************************************
  503. *
  504. * @doc INTERNAL
  505. *
  506. * @method HRESULT | CMouse | GetInstance |
  507. *
  508. * Obtains the DirectInput instance handle.
  509. *
  510. * @parm OUT PPV | ppvi |
  511. *
  512. * Receives the instance handle.
  513. *
  514. *****************************************************************************/
  515. STDMETHODIMP
  516. CMouse_GetInstance(PDICB pdcb, PPV ppvi)
  517. {
  518. HRESULT hres;
  519. PDM this;
  520. EnterProcI(IDirectInputDeviceCallback::Mouse::GetInstance, (_ "p", pdcb));
  521. /*
  522. * This is an internal interface, so we can skimp on validation.
  523. */
  524. this = _thisPvNm(pdcb, dcb);
  525. AssertF(this->pvi);
  526. *ppvi = (PV)this->pvi;
  527. hres = S_OK;
  528. ExitOleProcPpvR(ppvi);
  529. return hres;
  530. }
  531. /*****************************************************************************
  532. *
  533. * @doc INTERNAL
  534. *
  535. * @method HRESULT | CMouse | GetDataFormat |
  536. *
  537. * Obtains the device's preferred data format.
  538. *
  539. * @parm OUT LPDIDEVICEFORMAT * | ppdf |
  540. *
  541. * <t LPDIDEVICEFORMAT> to receive pointer to device format.
  542. *
  543. * @returns
  544. *
  545. * Returns a COM error code. The following error codes are
  546. * intended to be illustrative and not necessarily comprehensive.
  547. *
  548. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  549. *
  550. * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
  551. * <p lpmdr> parameter is not a valid pointer.
  552. *
  553. *****************************************************************************/
  554. STDMETHODIMP
  555. CMouse_GetDataFormat(PDICB pdcb, LPDIDATAFORMAT *ppdf)
  556. {
  557. HRESULT hres;
  558. PDM this;
  559. EnterProcI(IDirectInputDeviceCallback::Mouse::GetDataFormat,
  560. (_ "p", pdcb));
  561. /*
  562. * This is an internal interface, so we can skimp on validation.
  563. */
  564. this = _thisPvNm(pdcb, dcb);
  565. *ppdf = &this->df;
  566. hres = S_OK;
  567. ExitOleProcPpvR(ppdf);
  568. return hres;
  569. }
  570. /*****************************************************************************
  571. *
  572. * @doc INTERNAL
  573. *
  574. * @method HRESULT | CMouse | GetDeviceInfo |
  575. *
  576. * Obtain general information about the device.
  577. *
  578. * @parm OUT LPDIDEVICEINSTANCEW | pdiW |
  579. *
  580. * <t DEVICEINSTANCE> to be filled in. The
  581. * <e DEVICEINSTANCE.dwSize> and <e DEVICEINSTANCE.guidInstance>
  582. * have already been filled in.
  583. *
  584. * Secret convenience: <e DEVICEINSTANCE.guidProduct> is equal
  585. * to <e DEVICEINSTANCE.guidInstance>.
  586. *
  587. *****************************************************************************/
  588. STDMETHODIMP
  589. CMouse_GetDeviceInfo(PDICB pdcb, LPDIDEVICEINSTANCEW pdiW)
  590. {
  591. HRESULT hres;
  592. PDM this;
  593. EnterProcI(IDirectInputDeviceCallback::Mouse::GetDeviceInfo,
  594. (_ "pp", pdcb, pdiW));
  595. /*
  596. * This is an internal interface, so we can skimp on validation.
  597. */
  598. this = _thisPvNm(pdcb, dcb);
  599. AssertF(IsValidSizeDIDEVICEINSTANCEW(pdiW->dwSize));
  600. AssertF(IsEqualGUID(&GUID_SysMouse , &pdiW->guidInstance) ||
  601. IsEqualGUID(&GUID_SysMouseEm , &pdiW->guidInstance) ||
  602. IsEqualGUID(&GUID_SysMouseEm2, &pdiW->guidInstance));
  603. pdiW->guidProduct = GUID_SysMouse;
  604. pdiW->dwDevType = MAKE_DIDEVICE_TYPE(DI8DEVTYPE_MOUSE,
  605. DI8DEVTYPEMOUSE_UNKNOWN);
  606. LoadStringW(g_hinst, IDS_STDMOUSE, pdiW->tszProductName, cA(pdiW->tszProductName));
  607. LoadStringW(g_hinst, IDS_STDMOUSE, pdiW->tszInstanceName, cA(pdiW->tszInstanceName));
  608. hres = S_OK;
  609. ExitOleProcR();
  610. return hres;
  611. }
  612. /*****************************************************************************
  613. *
  614. * @doc INTERNAL
  615. *
  616. * @method void | CMouse | GetProperty |
  617. *
  618. * Get a mouse device property.
  619. *
  620. * @parm IN LPCDIPROPINFO | ppropi |
  621. *
  622. * Information describing the property being retrieved.
  623. *
  624. * @parm LPDIPROPHEADER | pdiph |
  625. *
  626. * Structure to receive property value.
  627. *
  628. * @returns
  629. *
  630. * <c E_NOTIMPL> nothing happened. The caller will do
  631. * the default thing in response to <c E_NOTIMPL>.
  632. *
  633. *****************************************************************************/
  634. STDMETHODIMP
  635. CMouse_GetProperty(PDICB pdcb, LPCDIPROPINFO ppropi, LPDIPROPHEADER pdiph)
  636. {
  637. HRESULT hres;
  638. PDM this;
  639. EnterProcI(IDirectInputDeviceCallback::Mouse::GetProperty,
  640. (_ "pxxp", pdcb, ppropi->pguid, ppropi->iobj, pdiph));
  641. /*
  642. * This is an internal interface, so we can skimp on validation.
  643. */
  644. this = _thisPvNm(pdcb, dcb);
  645. /*
  646. * Granularity is only supported for wheels.
  647. */
  648. if (ppropi->pguid == DIPROP_GRANULARITY &&
  649. ppropi->dwDevType == (DIDFT_RELAXIS | DIDFT_MAKEINSTANCE(2)) )
  650. {
  651. LPDIPROPDWORD pdipdw = (PV)pdiph;
  652. pdipdw->dwData = g_lWheelGranularity? (DWORD)g_lWheelGranularity : 120;
  653. hres = S_OK;
  654. }
  655. else
  656. {
  657. hres = E_NOTIMPL;
  658. }
  659. ExitOleProcR();
  660. return hres;
  661. }
  662. /*****************************************************************************
  663. *
  664. * @doc INTERNAL
  665. *
  666. * @method void | CMouse | GetCapabilities |
  667. *
  668. * Get mouse device capabilities.
  669. *
  670. * @parm LPDIDEVCAPS | pdc |
  671. *
  672. * Device capabilities structure to receive result.
  673. *
  674. * @returns
  675. * <c S_OK> on success.
  676. *
  677. *****************************************************************************/
  678. STDMETHODIMP
  679. CMouse_GetCapabilities(PDICB pdcb, LPDIDEVCAPS pdc)
  680. {
  681. HRESULT hres;
  682. PDM this;
  683. EnterProcI(IDirectInputDeviceCallback::Mouse::GetCapabilities,
  684. (_ "pp", pdcb, pdc));
  685. /*
  686. * This is an internal interface, so we can skimp on validation.
  687. */
  688. this = _thisPvNm(pdcb, dcb);
  689. pdc->dwDevType = MAKE_DIDEVICE_TYPE(DI8DEVTYPE_MOUSE,
  690. DI8DEVTYPEMOUSE_UNKNOWN);
  691. pdc->dwFlags = DIDC_ATTACHED;
  692. if (this->flEmulation) {
  693. pdc->dwFlags |= DIDC_ALIAS;
  694. }
  695. pdc->dwAxes = this->dwAxes;
  696. pdc->dwButtons = this->dwButtons;
  697. AssertF(pdc->dwPOVs == 0);
  698. hres = S_OK;
  699. ExitOleProcR();
  700. return hres;
  701. }
  702. /*****************************************************************************
  703. *
  704. * @doc INTERNAL
  705. *
  706. * @method HRESULT | CMouse | GetDeviceState |
  707. *
  708. * Obtains the state of the mouse device.
  709. *
  710. * It is the caller's responsibility to have validated all the
  711. * parameters and ensure that the device has been acquired.
  712. *
  713. * @parm OUT LPVOID | lpvData |
  714. *
  715. * Mouse data in the preferred data format.
  716. *
  717. * @returns
  718. *
  719. * Returns a COM error code. The following error codes are
  720. * intended to be illustrative and not necessarily comprehensive.
  721. *
  722. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  723. *
  724. * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
  725. * <p lpmdr> parameter is not a valid pointer.
  726. *
  727. *****************************************************************************/
  728. STDMETHODIMP
  729. CMouse_GetDeviceState(PDICB pdcb, LPVOID pvData)
  730. {
  731. HRESULT hres;
  732. PDM this;
  733. EnterProcI(IDirectInputDeviceCallback::Mouse::GetDeviceState,
  734. (_ "pp", pdcb, pvData));
  735. /*
  736. * This is an internal interface, so we can skimp on validation.
  737. */
  738. this = _thisPvNm(pdcb, dcb);
  739. AssertF(this->pvi);
  740. AssertF(this->pdmsPhys);
  741. if (this->pvi->fl & VIFL_ACQUIRED) {
  742. CMouse_GetPhysicalPosition(this, pvData);
  743. hres = S_OK;
  744. } else {
  745. hres = DIERR_INPUTLOST;
  746. }
  747. ExitOleProcR();
  748. return hres;
  749. }
  750. /*****************************************************************************
  751. *
  752. * @doc INTERNAL
  753. *
  754. * @method HRESULT | CMouse | GetObjectInfo |
  755. *
  756. * Obtain the friendly name of an object, passwed by index
  757. * into the preferred data format.
  758. *
  759. * @parm IN LPCDIPROPINFO | ppropi |
  760. *
  761. * Information describing the object being accessed.
  762. *
  763. * @parm IN OUT LPDIDEVICEOBJECTINSTANCEW | pdidioiW |
  764. *
  765. * Structure to receive information. The
  766. * <e DIDEVICEOBJECTINSTANCE.guidType>,
  767. * <e DIDEVICEOBJECTINSTANCE.dwOfs>,
  768. * and
  769. * <e DIDEVICEOBJECTINSTANCE.dwType>
  770. * fields have already been filled in.
  771. *
  772. * @returns
  773. *
  774. * Returns a COM error code.
  775. *
  776. *****************************************************************************/
  777. STDMETHODIMP
  778. CMouse_GetObjectInfo(PDICB pdcb, LPCDIPROPINFO ppropi,
  779. LPDIDEVICEOBJECTINSTANCEW pdidoiW)
  780. {
  781. HRESULT hres;
  782. PDM this;
  783. EnterProcI(IDirectInputDeviceCallback::Mouse::GetObjectInfo,
  784. (_ "pxp", pdcb, ppropi->iobj, pdidoiW));
  785. /*
  786. * This is an internal interface, so we can skimp on validation.
  787. */
  788. this = _thisPvNm(pdcb, dcb);
  789. AssertF(IsValidSizeDIDEVICEOBJECTINSTANCEW(pdidoiW->dwSize));
  790. if (ppropi->iobj < this->df.dwNumObjs) {
  791. AssertF(this->rgodf == this->df.rgodf);
  792. AssertF(ppropi->dwDevType == this->rgodf[ppropi->iobj].dwType);
  793. AssertF(DIDFT_GETTYPE(ppropi->dwDevType) == DIDFT_RELAXIS ||
  794. DIDFT_GETTYPE(ppropi->dwDevType) == DIDFT_PSHBUTTON);
  795. LoadStringW(g_hinst, IDS_MOUSEOBJECT +
  796. DIDFT_GETINSTANCE(ppropi->dwDevType),
  797. pdidoiW->tszName, cA(pdidoiW->tszName));
  798. /*
  799. * We do not support force feedback on mice, so
  800. * there are no FF flags to report.
  801. */
  802. hres = S_OK;
  803. } else {
  804. hres = E_INVALIDARG;
  805. }
  806. ExitOleProcR();
  807. return hres;
  808. }
  809. /*****************************************************************************
  810. *
  811. * @doc INTERNAL
  812. *
  813. * @method HRESULT | CMouse | SetCooperativeLevel |
  814. *
  815. * Notify the device of the cooperative level.
  816. *
  817. * @parm IN HWND | hwnd |
  818. *
  819. * The window handle.
  820. *
  821. * @parm IN DWORD | dwFlags |
  822. *
  823. * The cooperativity level.
  824. *
  825. * @returns
  826. *
  827. * Returns a COM error code.
  828. *
  829. *****************************************************************************/
  830. STDMETHODIMP
  831. CMouse_SetCooperativeLevel(PDICB pdcb, HWND hwnd, DWORD dwFlags)
  832. {
  833. HRESULT hres;
  834. PDM this;
  835. EnterProcI(IDirectInputDeviceCallback::Mouse::SetCooperativityLevel,
  836. (_ "pxx", pdcb, hwnd, dwFlags));
  837. /*
  838. * This is an internal interface, so we can skimp on validation.
  839. */
  840. this = _thisPvNm(pdcb, dcb);
  841. AssertF(this->pvi);
  842. #ifdef USE_SLOW_LL_HOOKS
  843. AssertF(DIGETEMFL(this->pvi->fl) == 0 ||
  844. DIGETEMFL(this->pvi->fl) == DIEMFL_MOUSE ||
  845. DIGETEMFL(this->pvi->fl) == DIEMFL_MOUSE2);
  846. #else
  847. AssertF(DIGETEMFL(this->pvi->fl) == 0 ||
  848. DIGETEMFL(this->pvi->fl) == DIEMFL_MOUSE2);
  849. #endif
  850. /*
  851. * Even though we can do it, we don't let the app
  852. * get background exclusive access. As with the keyboard,
  853. * there is nothing that technically prevents us from
  854. * supporting it; we just don't feel like it because it's
  855. * too dangerous.
  856. */
  857. /*
  858. * VxD and LL (emulation 1) behave the same, so we check
  859. * if it's "not emulation 2".
  860. */
  861. if (!(this->pvi->fl & DIMAKEEMFL(DIEMFL_MOUSE2))) {
  862. if (dwFlags & DISCL_EXCLUSIVE) {
  863. if (dwFlags & DISCL_FOREGROUND) {
  864. #ifdef WANT_TO_FIX_MANBUG43879
  865. this->pvi->fl |= VIFL_FOREGROUND;
  866. #endif
  867. this->pvi->fl |= VIFL_CAPTURED;
  868. hres = S_OK;
  869. } else { /* Disallow exclusive background */
  870. SquirtSqflPtszV(sqfl | sqflError,
  871. TEXT("Exclusive background mouse access disallowed"));
  872. hres = E_NOTIMPL;
  873. }
  874. } else {
  875. #ifdef WANT_TO_FIX_MANBUG43879
  876. if (dwFlags & DISCL_FOREGROUND) {
  877. this->pvi->fl |= VIFL_FOREGROUND;
  878. }
  879. #endif
  880. this->pvi->fl &= ~VIFL_CAPTURED;
  881. hres = S_OK;
  882. }
  883. } else {
  884. /*
  885. * Emulation 2 supports only exclusive foreground.
  886. */
  887. if ((dwFlags & (DISCL_EXCLUSIVE | DISCL_FOREGROUND)) ==
  888. (DISCL_EXCLUSIVE | DISCL_FOREGROUND)) {
  889. #ifdef WANT_TO_FIX_MANBUG43879
  890. this->pvi->fl |= VIFL_FOREGROUND;
  891. #endif
  892. this->pvi->fl |= VIFL_CAPTURED;
  893. hres = S_OK;
  894. } else {
  895. SquirtSqflPtszV(sqfl | sqflError,
  896. TEXT("Mouse access must be exclusive foreground in Emulation 2."));
  897. hres = E_NOTIMPL;
  898. }
  899. }
  900. if (SUCCEEDED(hres)) {
  901. this->hwndCapture = hwnd;
  902. }
  903. ExitOleProcR();
  904. return hres;
  905. }
  906. /*****************************************************************************
  907. *
  908. * @doc INTERNAL
  909. *
  910. * @method HRESULT | CMouse | RunControlPanel |
  911. *
  912. * Run the mouse control panel.
  913. *
  914. * @parm IN HWND | hwndOwner |
  915. *
  916. * The owner window.
  917. *
  918. * @parm DWORD | dwFlags |
  919. *
  920. * Flags.
  921. *
  922. *****************************************************************************/
  923. #pragma BEGIN_CONST_DATA
  924. TCHAR c_tszMouse[] = TEXT("mouse");
  925. #pragma END_CONST_DATA
  926. STDMETHODIMP
  927. CMouse_RunControlPanel(PDICB pdcb, HWND hwnd, DWORD dwFlags)
  928. {
  929. HRESULT hres;
  930. EnterProcI(IDirectInputDeviceCallback::Mouse::RunControlPanel,
  931. (_ "pxx", pdcb, hwnd, dwFlags));
  932. hres = hresRunControlPanel(c_tszMouse);
  933. ExitOleProcR();
  934. return hres;
  935. }
  936. /*****************************************************************************
  937. *
  938. * @doc INTERNAL
  939. *
  940. * @method HRESULT | CMouse | BuildDefaultActionMap |
  941. *
  942. * Validate the passed action map, blanking out invalid ones.
  943. *
  944. * @parm LPDIACTIONFORMATW | pActionFormat |
  945. *
  946. * Actions to map.
  947. *
  948. * @parm DWORD | dwFlags |
  949. *
  950. * Flags used to indicate mapping preferences.
  951. *
  952. * @parm REFGUID | guidInst |
  953. *
  954. * Device instance GUID.
  955. *
  956. * @returns
  957. *
  958. * <c E_NOTIMPL>
  959. *
  960. *****************************************************************************/
  961. STDMETHODIMP
  962. CMouse_BuildDefaultActionMap
  963. (
  964. PDICB pdcb,
  965. LPDIACTIONFORMATW paf,
  966. DWORD dwFlags,
  967. REFGUID guidInst
  968. )
  969. {
  970. HRESULT hres;
  971. PDM this;
  972. /*
  973. * This is an internal interface, so we can skimp on validation.
  974. */
  975. EnterProcI(IDirectInputDeviceCallback::Mouse::BuildDefaultActionMap,
  976. (_ "ppxG", pdcb, paf, dwFlags, guidInst));
  977. this = _thisPvNm(pdcb, dcb);
  978. hres = CMap_BuildDefaultSysActionMap ( paf, dwFlags, DIPHYSICAL_MOUSE,
  979. guidInst, &this->df, 3 /* Generic mice buttons start at instnace 3 */ );
  980. ExitOleProcR();
  981. return hres;
  982. }
  983. /*****************************************************************************
  984. *
  985. * @doc INTERNAL
  986. *
  987. * @method UINT | CMouse | NumAxes |
  988. *
  989. * Determine the number of mouse axes.
  990. *
  991. * On Windows NT, we can use the new <c SM_MOUSEWHEELPRESENT>
  992. * system metric. On Windows 95, we have to hunt for the
  993. * Magellan window (using the mechanism documented in the
  994. * Magellan SDK).
  995. *
  996. *****************************************************************************/
  997. #pragma BEGIN_CONST_DATA
  998. TCHAR c_tszMouseZClass[] = TEXT("MouseZ");
  999. TCHAR c_tszMouseZTitle[] = TEXT("Magellan MSWHEEL");
  1000. TCHAR c_tszMouseZActive[] = TEXT("MSH_WHEELSUPPORT_MSG");
  1001. #pragma END_CONST_DATA
  1002. #ifdef WINNT
  1003. #define CMouse_IsMagellanWheel() FALSE
  1004. #else
  1005. BOOL INLINE
  1006. CMouse_IsMagellanWheel(void)
  1007. {
  1008. HWND hwnd = FindWindow(c_tszMouseZClass, c_tszMouseZTitle);
  1009. return hwnd && SendMessage(hwnd, RegisterWindowMessage(c_tszMouseZActive), 0, 0);
  1010. }
  1011. #endif
  1012. #ifndef SM_MOUSEWHEELPRESENT
  1013. #define SM_MOUSEWHEELPRESENT 75
  1014. #endif
  1015. UINT INLINE
  1016. CMouse_NumAxes(void)
  1017. {
  1018. UINT dwAxes;
  1019. if (GetSystemMetrics(SM_MOUSEWHEELPRESENT) || CMouse_IsMagellanWheel()) {
  1020. dwAxes = 3;
  1021. } else {
  1022. dwAxes = 2;
  1023. }
  1024. if (dwAxes == 2) {
  1025. //Should avoid rebuilding too frequently.
  1026. DIHid_BuildHidList(FALSE);
  1027. DllEnterCrit();
  1028. if (g_phdl) {
  1029. int ihdi;
  1030. for (ihdi = 0; ihdi < g_phdl->chdi; ihdi++) {
  1031. if (dwAxes < g_phdl->rghdi[ihdi].osd.uiAxes) {
  1032. dwAxes = g_phdl->rghdi[ihdi].osd.uiAxes;
  1033. }
  1034. }
  1035. }
  1036. DllLeaveCrit();
  1037. }
  1038. return dwAxes;
  1039. }
  1040. UINT INLINE
  1041. CMouse_NumButtons(DWORD dwAxes)
  1042. {
  1043. UINT dwButtons;
  1044. dwButtons = GetSystemMetrics(SM_CMOUSEBUTTONS);
  1045. #ifndef WINNT
  1046. #ifdef HID_SUPPORT
  1047. {
  1048. /*
  1049. * ISSUE-2001/03/29-timgill Should try to avoid rebuilding Hid List too frequently.
  1050. */
  1051. DIHid_BuildHidList(FALSE);
  1052. DllEnterCrit();
  1053. if (g_phdl) {
  1054. int ihdi;
  1055. for (ihdi = 0; ihdi < g_phdl->chdi; ihdi++) {
  1056. if (dwButtons < g_phdl->rghdi[ihdi].osd.uiButtons) {
  1057. dwButtons = g_phdl->rghdi[ihdi].osd.uiButtons;
  1058. }
  1059. }
  1060. }
  1061. DllLeaveCrit();
  1062. }
  1063. #endif
  1064. #endif
  1065. if( dwButtons >= 8 ) {
  1066. dwButtons = 8;
  1067. }
  1068. else if (dwAxes == 3 && dwButtons < 3) {
  1069. /*
  1070. * HACK FOR MAGELLAN!
  1071. *
  1072. * They return 2 from GetSystemMetrics(SM_CMOUSEBUTTONS).
  1073. * So if we see a Z-axis, then assume that
  1074. * there is also a third button.
  1075. */
  1076. dwButtons = 3;
  1077. }
  1078. return dwButtons;
  1079. }
  1080. /*****************************************************************************
  1081. *
  1082. * @doc INTERNAL
  1083. *
  1084. * @method void | CMouse | AddObjects |
  1085. *
  1086. * Add a number of objects to the device format.
  1087. *
  1088. * @parm LPCDIOBJECTDATAFORMAT | rgodf |
  1089. *
  1090. * Array of objects to be added.
  1091. *
  1092. * @parm UINT | cObj |
  1093. *
  1094. * Number of objects to add.
  1095. *
  1096. *****************************************************************************/
  1097. void INTERNAL
  1098. CMouse_AddObjects(PDM this, LPCDIOBJECTDATAFORMAT rgodf, UINT cObj)
  1099. {
  1100. UINT iodf;
  1101. EnterProc(CMouse_AddObjects, (_ "pxx", this, rgodf, cObj));
  1102. for (iodf = 0; iodf < cObj; iodf++) {
  1103. this->rgodf[this->df.dwNumObjs++] = rgodf[iodf];
  1104. }
  1105. AssertF(this->df.dwNumObjs <= cA(this->rgodf));
  1106. }
  1107. /*****************************************************************************
  1108. *
  1109. * @doc INTERNAL
  1110. *
  1111. * @method void | CMouse | Init |
  1112. *
  1113. * Initialize the object by establishing the data format
  1114. * based on the mouse type.
  1115. *
  1116. * Code for detecting the IntelliMouse (formerly known as
  1117. * Magellan) pointing device is swiped from zmouse.h.
  1118. *
  1119. * @parm REFGUID | rguid |
  1120. *
  1121. * The instance GUID we are being asked to create.
  1122. *
  1123. *****************************************************************************/
  1124. HRESULT INTERNAL
  1125. CMouse_Init(PDM this, REFGUID rguid)
  1126. {
  1127. HRESULT hres;
  1128. VXDDEVICEFORMAT devf;
  1129. EnterProc(CMouse_Init, (_ "pG", this, rguid));
  1130. this->df.dwSize = cbX(DIDATAFORMAT);
  1131. this->df.dwObjSize = cbX(DIOBJECTDATAFORMAT);
  1132. this->df.dwDataSize = cbX(DIMOUSESTATE_INT);
  1133. this->df.rgodf = this->rgodf;
  1134. AssertF(this->df.dwFlags == 0);
  1135. AssertF(this->df.dwNumObjs == 0);
  1136. /*
  1137. * Need to know early if we have a Z-axis, so we can disable
  1138. * the Z-wheel if it doesn't exist.
  1139. *
  1140. * Note that this disabling needs to be done only on Win95.
  1141. * Win98 and NT4 have native Z-axis support, so there is
  1142. * nothing bogus that needs to be hacked.
  1143. */
  1144. this->dwAxes = CMouse_NumAxes();
  1145. devf.dwExtra = this->dwAxes;
  1146. if (this->dwAxes < 3) {
  1147. DWORD dwVer = GetVersion();
  1148. if ((LONG)dwVer >= 0 ||
  1149. MAKEWORD(HIBYTE(LOWORD(dwVer)), LOBYTE(dwVer)) >= 0x040A) {
  1150. devf.dwExtra = 3;
  1151. }
  1152. }
  1153. CMouse_AddObjects(this, c_podfMouseAxes, this->dwAxes);
  1154. /*
  1155. * Create the object with the most optimistic data format.
  1156. * This is important, because DINPUT.VXD builds the
  1157. * data format only once, and we need to protect ourselves against
  1158. * the user going into Control Panel and enabling the Z-Wheel
  1159. * after DINPUT.VXD has already initialized.
  1160. */
  1161. devf.cbData = cbX(DIMOUSESTATE_INT);
  1162. devf.cObj = cA(c_rgodfMouse);
  1163. devf.rgodf = c_rgodfMouse;
  1164. /*
  1165. * But first a word from our other sponsor: Figure out the
  1166. * emulation flags based on the GUID.
  1167. */
  1168. AssertF(GUID_SysMouse .Data1 == 0x6F1D2B60);
  1169. AssertF(GUID_SysMouseEm .Data1 == 0x6F1D2B80);
  1170. AssertF(GUID_SysMouseEm2.Data1 == 0x6F1D2B81);
  1171. switch (rguid->Data1) {
  1172. default:
  1173. case 0x6F1D2B60:
  1174. AssertF(IsEqualGUID(rguid, &GUID_SysMouse));
  1175. AssertF(this->flEmulation == 0);
  1176. break;
  1177. case 0x6F1D2B80:
  1178. AssertF(IsEqualGUID(rguid, &GUID_SysMouseEm));
  1179. this->flEmulation = DIEMFL_MOUSE;
  1180. break;
  1181. case 0x6F1D2B81:
  1182. AssertF(IsEqualGUID(rguid, &GUID_SysMouseEm2));
  1183. this->flEmulation = DIEMFL_MOUSE2;
  1184. break;
  1185. }
  1186. devf.dwEmulation = this->flEmulation;
  1187. hres = Hel_Mouse_CreateInstance(&devf, &this->pvi);
  1188. if (SUCCEEDED(hres)) {
  1189. AssertF(this->pvi);
  1190. this->pdmsPhys = this->pvi->pState;
  1191. this->dwButtons = CMouse_NumButtons( this->dwAxes );
  1192. CMouse_AddObjects(this, c_podfMouseButtons, this->dwButtons);
  1193. hres = S_OK;
  1194. } else {
  1195. SquirtSqflPtszV(sqfl | sqflError,
  1196. TEXT("Mismatched version of dinput.vxd"));
  1197. hres = E_FAIL;
  1198. }
  1199. ExitOleProc();
  1200. return hres;
  1201. }
  1202. /*****************************************************************************
  1203. *
  1204. * CMouse_New (constructor)
  1205. *
  1206. * Fail the create if the machine has no mouse.
  1207. *
  1208. *****************************************************************************/
  1209. STDMETHODIMP
  1210. CMouse_New(PUNK punkOuter, REFGUID rguid, RIID riid, PPV ppvObj)
  1211. {
  1212. HRESULT hres;
  1213. EnterProcI(IDirectInputDeviceCallback::Mouse::<constructor>,
  1214. (_ "Gp", riid, ppvObj));
  1215. AssertF(IsEqualGUID(rguid, &GUID_SysMouse) ||
  1216. IsEqualGUID(rguid, &GUID_SysMouseEm) ||
  1217. IsEqualGUID(rguid, &GUID_SysMouseEm2));
  1218. if (GetSystemMetrics(SM_MOUSEPRESENT)) {
  1219. hres = Common_NewRiid(CMouse, punkOuter, riid, ppvObj);
  1220. if (SUCCEEDED(hres)) {
  1221. /* Must use _thisPv in case of aggregation */
  1222. PDM this = _thisPv(*ppvObj);
  1223. if (SUCCEEDED(hres = CMouse_Init(this, rguid))) {
  1224. } else {
  1225. Invoke_Release(ppvObj);
  1226. }
  1227. }
  1228. } else {
  1229. RPF("Warning: System does not have a mouse");
  1230. /*
  1231. * Since we by-passed the parameter checks and we failed to create
  1232. * the new interface, try to zero the pointer now.
  1233. */
  1234. if (!IsBadWritePtr(ppvObj, sizeof(UINT_PTR) ))
  1235. {
  1236. *(PUINT_PTR)ppvObj = 0;
  1237. }
  1238. hres = DIERR_DEVICENOTREG;
  1239. }
  1240. ExitOleProcPpvR(ppvObj);
  1241. return hres;
  1242. }
  1243. /*****************************************************************************
  1244. *
  1245. * The long-awaited vtbls and templates
  1246. *
  1247. *****************************************************************************/
  1248. #pragma BEGIN_CONST_DATA
  1249. #define CMouse_Signature 0x53554F4D /* "MOUS" */
  1250. Primary_Interface_Begin(CMouse, IDirectInputDeviceCallback)
  1251. CMouse_GetInstance,
  1252. CDefDcb_GetVersions,
  1253. CMouse_GetDataFormat,
  1254. CMouse_GetObjectInfo,
  1255. CMouse_GetCapabilities,
  1256. CMouse_Acquire,
  1257. CMouse_Unacquire,
  1258. CMouse_GetDeviceState,
  1259. CMouse_GetDeviceInfo,
  1260. CMouse_GetProperty,
  1261. CDefDcb_SetProperty,
  1262. CDefDcb_SetEventNotification,
  1263. CMouse_SetCooperativeLevel,
  1264. CMouse_RunControlPanel,
  1265. CDefDcb_CookDeviceData,
  1266. CDefDcb_CreateEffect,
  1267. CDefDcb_GetFFConfigKey,
  1268. CDefDcb_SendDeviceData,
  1269. CDefDcb_Poll,
  1270. CDefDcb_GetUsage,
  1271. CDefDcb_MapUsage,
  1272. CDefDcb_SetDIData,
  1273. CMouse_BuildDefaultActionMap,
  1274. Primary_Interface_End(CMouse, IDirectInputDeviceCallback)