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.

1719 lines
58 KiB

  1. /*****************************************************************************
  2. *
  3. * DIGenK.c
  4. *
  5. * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * Generic IDirectInputDevice callback for keyboard.
  10. *
  11. * Contents:
  12. *
  13. * CKbd_CreateInstance
  14. *
  15. *****************************************************************************/
  16. #include "dinputpr.h"
  17. /*****************************************************************************
  18. *
  19. * Some holes in windows.h on NT platforms.
  20. *
  21. *****************************************************************************/
  22. #ifndef VK_KANA
  23. #define VK_KANA 0x15
  24. #endif
  25. /*****************************************************************************
  26. *
  27. * The sqiffle for this file.
  28. *
  29. *****************************************************************************/
  30. #define sqfl sqflKbd
  31. /*****************************************************************************
  32. *
  33. * Declare the interfaces we will be providing.
  34. *
  35. * WARNING! If you add a secondary interface, you must also change
  36. * CKbd_New!
  37. *
  38. *****************************************************************************/
  39. Primary_Interface(CKbd, IDirectInputDeviceCallback);
  40. /*****************************************************************************
  41. *
  42. * @doc INTERNAL
  43. *
  44. * @struct KBDSTAT |
  45. *
  46. * Internal instantaneous keyboard status information.
  47. *
  48. * @field BYTE | rgb[DIKBD_CKEYS] |
  49. *
  50. * Array of key states, one for each logical key.
  51. *
  52. *****************************************************************************/
  53. typedef struct KBDSTAT {
  54. BYTE rgb[DIKBD_CKEYS];
  55. } KBDSTAT, *PKBDSTAT;
  56. /*****************************************************************************
  57. *
  58. * @doc EXTERNAL
  59. *
  60. * @topic Special remarks on keyboard scan codes |
  61. *
  62. * There are several aspects of keyboards which applications should
  63. * be aware of. Applications are encouraged to allow users to
  64. * reconfigure keyboard action keys to suit the physical keyboard
  65. * layout.
  66. *
  67. * For the purposes of this discussion, the baseline keyboard
  68. * shall be the US PC Enhanced keyboard. When a key is described
  69. * as "missing", it means that the key is present on the US PC
  70. * Enhanced keyboard but not on the keyboard under discussion.
  71. * When a key is described as "added", it means that the key is
  72. * absent on the US PC Enhanced keyboard but present on the
  73. * keyboard under discussion.
  74. *
  75. * Not all PC Enhanced keyboards support the new Windows keys
  76. * (DIK_LWIN, DIK_RWIN, and DIK_APPS). There is no way to
  77. * determine whether the keys are physically available.
  78. *
  79. * Note that there is no DIK_PAUSE key code. The PC Enhanced
  80. * keyboard does not generate a separate DIK_PAUSE scan code;
  81. * rather, it synthesizes a "Pause" from the DIK_LCONTROL and
  82. * DIK_NUMLOCK scan codes.
  83. *
  84. * Keyboards for laptops or other reduced-footprint computers
  85. * frequently do not implement a full set of keys. Instead,
  86. * some keys (typically numeric keypad keys) are multiplexed
  87. * with other keys, selected by an auxiliary "mode" key which
  88. * does not generate a separate scan code.
  89. *
  90. * If the keyboard subtype indicates a PC XT or PC AT keyboard,
  91. * then the following keys are not available:
  92. * DIK_F11, DIK_F12, and all the extended keys (DIK_* values
  93. * greater than or equal to 0x80). Furthermore, the PC XT
  94. * keyboard lacks DIK_SYSRQ.
  95. *
  96. * Japanese keyboards contain a substantially different set of
  97. * keys from US keyboards. The following keyboard scan codes
  98. * are not available on Japanese keyboards:
  99. * DIK_EQUALS, DIK_APOSTROPHE, DIK_GRAVE, DIK_NUMPADENTER,
  100. * DIK_RCONTROL, DIK_RMENU. Furthermore, most Japanese
  101. * keyboards do not support DIK_RSHIFT. (It is customary
  102. * to use DIK_NUMPADEQUAL in place of DIK_RSHIFT.)
  103. *
  104. * Japanese keyboards contain the following additional keys:
  105. * DIK_F14, DIK_NUMPADEQUAL, DIK_CIRCUMFLEX, DIK_AT, DIK_COLON,
  106. * DIK_UNDERLINE, DIK_XFER, DIK_NFER, DIK_STOP, DIK_KANA, and
  107. * DIK_NUMPADCOMMA.
  108. *
  109. * Note that on Japanese keyboards, the DIK_CAPSLOCK and
  110. * DIK_KANA keys are toggle buttons and not push buttons.
  111. * They generate a down event
  112. * when first pressed, then generate an up event when pressed a
  113. * second time.
  114. * Note that on Windows 2000, the DIK_KANJI key is also treated as a
  115. * toggle.
  116. *
  117. *****************************************************************************/
  118. /*****************************************************************************
  119. *
  120. * @doc INTERNAL
  121. *
  122. * @global KBDTYPE | c_rgktWhich[] |
  123. *
  124. * Array that describes which keyboards support which keys.
  125. *
  126. * The list is optimistic. If any keyboard of the indicated
  127. * type supports the key, then we list it.
  128. *
  129. * Items marks "available for NEC" are keys which are extremely
  130. * unlikely to be used in future versions of the Enhanced
  131. * keyboard and therefore can be used as ersatz scan codes for
  132. * NEC-only keys.
  133. *
  134. * Note: Kana and CAPSLOCK are toggle buttons on NEC keyboards.
  135. * Note: Kana, Kanji and CAPSLOCK are toggle buttons on all NT JPN
  136. * keyboards.
  137. *
  138. *****************************************************************************/
  139. typedef BYTE KBDTYPE;
  140. #define KBDTYPE_XT 0x01 /* Key exists on XT class keyboard */
  141. #define KBDTYPE_AT 0x02 /* Key exists on AT class keyboard */
  142. #define KBDTYPE_ENH 0x04 /* Key exists on Enhanced keyboard */
  143. #define KBDTYPE_NEC 0x08 /* Key exists on NEC keyboard */
  144. #define KBDTYPE_ANYKBD 0x0F /* Key exists somewhere in the world */
  145. #define KBDTYPE_NECTGL 0x10 /* Is a toggle-key on NEC keyboard */
  146. #define KBDTYPE_NTTGL 0x20 /* Is a toggle-key on an NT FE keyboard */
  147. #pragma BEGIN_CONST_DATA
  148. #define XT KBDTYPE_XT |
  149. #define AT KBDTYPE_XT |
  150. #define ENH KBDTYPE_ENH |
  151. #define NEC KBDTYPE_NEC |
  152. #define NECTGL KBDTYPE_NECTGL |
  153. #define NTTGL KBDTYPE_NTTGL |
  154. KBDTYPE c_rgktWhich[] = {
  155. 0, /* 0x00 - <undef> */
  156. XT AT ENH NEC 0, /* 0x01 - Esc */
  157. XT AT ENH NEC 0, /* 0x02 - 1 */
  158. XT AT ENH NEC 0, /* 0x03 - 2 */
  159. XT AT ENH NEC 0, /* 0x04 - 3 */
  160. XT AT ENH NEC 0, /* 0x05 - 4 */
  161. XT AT ENH NEC 0, /* 0x06 - 5 */
  162. XT AT ENH NEC 0, /* 0x07 - 6 */
  163. XT AT ENH NEC 0, /* 0x08 - 7 */
  164. XT AT ENH NEC 0, /* 0x09 - 8 */
  165. XT AT ENH NEC 0, /* 0x0A - 9 */
  166. XT AT ENH NEC 0, /* 0x0B - 0 */
  167. XT AT ENH NEC 0, /* 0x0C - - */
  168. XT AT ENH 0, /* 0x0D - = */
  169. XT AT ENH NEC 0, /* 0x0E - BkSp */
  170. XT AT ENH NEC 0, /* 0x0F - Tab */
  171. XT AT ENH NEC 0, /* 0x10 - Q */
  172. XT AT ENH NEC 0, /* 0x11 - W */
  173. XT AT ENH NEC 0, /* 0x12 - E */
  174. XT AT ENH NEC 0, /* 0x13 - R */
  175. XT AT ENH NEC 0, /* 0x14 - T */
  176. XT AT ENH NEC 0, /* 0x15 - Y */
  177. XT AT ENH NEC 0, /* 0x16 - U */
  178. XT AT ENH NEC 0, /* 0x17 - I */
  179. XT AT ENH NEC 0, /* 0x18 - O */
  180. XT AT ENH NEC 0, /* 0x19 - P */
  181. XT AT ENH NEC 0, /* 0x1A - [ */
  182. XT AT ENH NEC 0, /* 0x1B - ] */
  183. XT AT ENH NEC 0, /* 0x1C - Enter */
  184. XT AT ENH NEC 0, /* 0x1D - LCtrl */
  185. XT AT ENH NEC 0, /* 0x1E - A */
  186. XT AT ENH NEC 0, /* 0x1F - S */
  187. XT AT ENH NEC 0, /* 0x20 - D */
  188. XT AT ENH NEC 0, /* 0x21 - F */
  189. XT AT ENH NEC 0, /* 0x22 - G */
  190. XT AT ENH NEC 0, /* 0x23 - H */
  191. XT AT ENH NEC 0, /* 0x24 - J */
  192. XT AT ENH NEC 0, /* 0x25 - K */
  193. XT AT ENH NEC 0, /* 0x26 - L */
  194. XT AT ENH NEC 0, /* 0x27 - ; */
  195. XT AT ENH 0, /* 0x28 - ' */
  196. XT AT ENH 0, /* 0x29 - ` */
  197. XT AT ENH NEC 0, /* 0x2A - LShift */
  198. XT AT ENH NEC 0, /* 0x2B - \ */
  199. XT AT ENH NEC 0, /* 0x2C - Z */
  200. XT AT ENH NEC 0, /* 0x2D - X */
  201. XT AT ENH NEC 0, /* 0x2E - C */
  202. XT AT ENH NEC 0, /* 0x2F - V */
  203. XT AT ENH NEC 0, /* 0x30 - B */
  204. XT AT ENH NEC 0, /* 0x31 - N */
  205. XT AT ENH NEC 0, /* 0x32 - M */
  206. XT AT ENH NEC 0, /* 0x33 - , */
  207. XT AT ENH NEC 0, /* 0x34 - . */
  208. XT AT ENH NEC 0, /* 0x35 - / */
  209. XT AT ENH NEC 0, /* 0x36 - RShift */
  210. XT AT ENH NEC 0, /* 0x37 - Num* */
  211. XT AT ENH NEC 0, /* 0x38 - LAlt */
  212. XT AT ENH NEC 0, /* 0x39 - Space */
  213. XT AT ENH NEC NECTGL NTTGL 0, /* 0x3A - CapsLock */
  214. XT AT ENH NEC 0, /* 0x3B - F1 */
  215. XT AT ENH NEC 0, /* 0x3C - F2 */
  216. XT AT ENH NEC 0, /* 0x3D - F3 */
  217. XT AT ENH NEC 0, /* 0x3E - F4 */
  218. XT AT ENH NEC 0, /* 0x3F - F5 */
  219. XT AT ENH NEC 0, /* 0x40 - F6 */
  220. XT AT ENH NEC 0, /* 0x41 - F7 */
  221. XT AT ENH NEC 0, /* 0x42 - F8 */
  222. XT AT ENH NEC 0, /* 0x43 - F9 */
  223. XT AT ENH NEC 0, /* 0x44 - F10 */
  224. XT AT ENH 0, /* 0x45 - NumLock */
  225. XT AT ENH 0, /* 0x46 - ScrLock */
  226. XT AT ENH NEC 0, /* 0x47 - Numpad7 */
  227. XT AT ENH NEC 0, /* 0x48 - Numpad8 */
  228. XT AT ENH NEC 0, /* 0x49 - Numpad9 */
  229. XT AT ENH NEC 0, /* 0x4A - Numpad- */
  230. XT AT ENH NEC 0, /* 0x4B - Numpad4 */
  231. XT AT ENH NEC 0, /* 0x4C - Numpad5 */
  232. XT AT ENH NEC 0, /* 0x4D - Numpad6 */
  233. XT AT ENH NEC 0, /* 0x4E - Numpad+ */
  234. XT AT ENH NEC 0, /* 0x4F - Numpad1 */
  235. XT AT ENH NEC 0, /* 0x50 - Numpad2 */
  236. XT AT ENH NEC 0, /* 0x51 - Numpad3 */
  237. XT AT ENH NEC 0, /* 0x52 - Numpad0 */
  238. XT AT ENH NEC 0, /* 0x53 - Numpad. */
  239. 0, /* 0x54 - <undef> */
  240. 0, /* 0x55 - <undef> */
  241. ENH 0, /* 0x56 - <undef>. On UK/Germany keyboards, it is <, > and |. */
  242. ENH NEC 0, /* 0x57 - F11 */
  243. ENH NEC 0, /* 0x58 - F12 */
  244. 0, /* 0x59 - <undef> */
  245. 0, /* 0x5A - <undef> */
  246. 0, /* 0x5B - <undef> */
  247. 0, /* 0x5C - <undef> */
  248. 0, /* 0x5D - <undef> */
  249. 0, /* 0x5E - <undef> */
  250. 0, /* 0x5F - <undef> */
  251. 0, /* 0x60 - <undef> */
  252. 0, /* 0x61 - <undef> */
  253. 0, /* 0x62 - <undef> */
  254. 0, /* 0x63 - <undef> */
  255. NEC 0, /* 0x64 - F13 */
  256. NEC 0, /* 0x65 - F14 */
  257. NEC 0, /* 0x66 - F15 */
  258. 0, /* 0x67 - <undef> */
  259. 0, /* 0x68 - <undef> */
  260. 0, /* 0x69 - <undef> */
  261. 0, /* 0x6A - <undef> */
  262. 0, /* 0x6B - <undef> */
  263. 0, /* 0x6C - <undef> */
  264. 0, /* 0x6D - <undef> */
  265. 0, /* 0x6E - <undef> */
  266. 0, /* 0x6F - <undef> */
  267. NEC NECTGL NTTGL 0, /* 0x70 - Kana */
  268. 0, /* 0x71 - <undef> */
  269. 0, /* 0x72 - <undef> */
  270. ENH 0, /* 0x73 - <undef>. On Portugese (Brazilian) keyboard, it is /, ? */
  271. 0, /* 0x74 - <undef> */
  272. 0, /* 0x75 - <undef> */
  273. 0, /* 0x76 - <undef> */
  274. 0, /* 0x77 - <undef> */
  275. 0, /* 0x78 - <undef> */
  276. NEC 0, /* 0x79 - Convert */
  277. 0, /* 0x7A - <undef> */
  278. NEC 0, /* 0x7B - Nfer */
  279. 0, /* 0x7C - <undef> */
  280. NEC 0, /* 0x7D - Yen */
  281. ENH 0, /* 0x7E - <undef>. On Portugese (Brazilian) keyboard, it is keypad . */
  282. 0, /* 0x7F - <undef> */
  283. /* Extended keycodes go here */
  284. 0, /* 0x80 - <undef> */
  285. 0, /* 0x81 - <undef> */
  286. 0, /* 0x82 - <undef> */
  287. 0, /* 0x83 - <undef> */
  288. 0, /* 0x84 - <undef> */
  289. 0, /* 0x85 - <undef> */
  290. 0, /* 0x86 - <undef> */
  291. 0, /* 0x87 - <undef> */
  292. 0, /* 0x88 - <undef> */
  293. 0, /* 0x89 - <undef> */
  294. 0, /* 0x8A - <undef> */
  295. 0, /* 0x8B - <undef> */
  296. 0, /* 0x8C - <undef> */
  297. NEC 0, /* 0x8D - Num= */
  298. 0, /* 0x8E - <undef> */
  299. 0, /* 0x8F - <undef> */
  300. ENH NEC 0, /* 0x90 - ^ */ ///Prev Track
  301. NEC 0, /* 0x91 - @ */
  302. NEC 0, /* 0x92 - : */
  303. NEC 0, /* 0x93 - _ */
  304. NEC NTTGL 0, /* 0x94 - Xfer - AKA Kanji */
  305. NEC 0, /* 0x95 - Stop */
  306. NEC 0, /* 0x96 - AX */
  307. NEC 0, /* 0x97 - Unlabel'd*/
  308. 0, /* 0x98 - <undef> */ /* available for NEC */
  309. ENH 0, /* 0x99 - <undef> */ /* available for NEC */ ///Next Track
  310. 0, /* 0x9A - <undef> */
  311. 0, /* 0x9B - <undef> */
  312. ENH 0, /* 0x9C - NumEnter */
  313. ENH 0, /* 0x9D - RCtrl */
  314. 0, /* 0x9E - <undef> */ /* available for NEC */
  315. 0, /* 0x9F - <undef> */ /* available for NEC */
  316. ENH 0, /* 0xA0 - <undef> */ /* available for NEC */ ///Mute
  317. ENH 0, /* 0xA1 - <undef> */ /* available for NEC */ ///Calculator
  318. ENH 0, /* 0xA2 - <undef> */ /* available for NEC */ ///Play/Pause
  319. 0, /* 0xA3 - <undef> */ /* available for NEC */
  320. ENH 0, /* 0xA4 - <undef> */ /* available for NEC */ ///Stop
  321. 0, /* 0xA5 - <undef> */ /* available for NEC */
  322. 0, /* 0xA6 - <undef> */ /* available for NEC */
  323. 0, /* 0xA7 - <undef> */
  324. 0, /* 0xA8 - <undef> */
  325. 0, /* 0xA9 - <undef> */
  326. 0, /* 0xAA - <undef> */
  327. 0, /* 0xAB - <undef> */
  328. 0, /* 0xAC - <undef> */ /* available for NEC */
  329. 0, /* 0xAD - <undef> */ /* available for NEC */
  330. ENH 0, /* 0xAE - <undef> */ /* available for NEC */ ///Volume -
  331. 0, /* 0xAF - <undef> */ /* available for NEC */
  332. ENH 0, /* 0xB0 - <undef> */ /* available for NEC */ ///Volume +
  333. 0, /* 0xB1 - <undef> */ /* available for NEC */
  334. ENH 0, /* 0xB2 - <undef> */ /* available for NEC */ ///Web/Home
  335. NEC 0, /* 0xB3 - Num, */
  336. 0, /* 0xB4 - <undef> */
  337. ENH NEC 0, /* 0xB5 - Num/ */
  338. 0, /* 0xB6 - <undef> */
  339. AT ENH NEC 0, /* 0xB7 - SysRq */
  340. ENH 0, /* 0xB8 - RAlt */
  341. 0, /* 0xB9 - <undef> */
  342. 0, /* 0xBA - <undef> */
  343. 0, /* 0xBB - <undef> */
  344. 0, /* 0xBC - <undef> */
  345. 0, /* 0xBD - <undef> */
  346. 0, /* 0xBE - <undef> */
  347. 0, /* 0xBF - <undef> */
  348. 0, /* 0xC0 - <undef> */
  349. 0, /* 0xC1 - <undef> */
  350. 0, /* 0xC2 - <undef> */
  351. 0, /* 0xC3 - <undef> */
  352. 0, /* 0xC4 - <undef> */
  353. ENH 0, /* 0xC5 - Pause */
  354. 0, /* 0xC6 - <undef> */
  355. ENH NEC 0, /* 0xC7 - Home */
  356. ENH NEC 0, /* 0xC8 - UpArrow */
  357. ENH NEC 0, /* 0xC9 - PgUp */
  358. 0, /* 0xCA - <undef> */
  359. ENH NEC 0, /* 0xCB - LtArrow */
  360. 0, /* 0xCC - <undef> */
  361. ENH NEC 0, /* 0xCD - RtArrow */
  362. 0, /* 0xCE - <undef> */
  363. ENH NEC 0, /* 0xCF - End */
  364. ENH NEC 0, /* 0xD0 - DnArrow */
  365. ENH NEC 0, /* 0xD1 - PgDn */
  366. ENH NEC 0, /* 0xD2 - Insert */
  367. ENH NEC 0, /* 0xD3 - Delete */
  368. 0, /* 0xD4 - <undef> */
  369. 0, /* 0xD5 - <undef> */
  370. 0, /* 0xD6 - <undef> */
  371. 0, /* 0xD7 - <undef> */
  372. 0, /* 0xD8 - <undef> */
  373. 0, /* 0xD9 - <undef> */
  374. 0, /* 0xDA - <undef> */
  375. ENH NEC 0, /* 0xDB - LWin */
  376. ENH NEC 0, /* 0xDC - RWin */
  377. ENH NEC 0, /* 0xDD - AppMenu */
  378. ENH 0, /* 0xDE - Power */
  379. ENH 0, /* 0xDF - Sleep */
  380. 0, /* 0xE0 - <undef> */
  381. 0, /* 0xE1 - <undef> */
  382. 0, /* 0xE2 - <undef> */
  383. ENH 0, /* 0xE3 - Wake */
  384. 0, /* 0xE4 - <undef> */
  385. ENH 0, /* 0xE5 - <undef> */ ///Search
  386. ENH 0, /* 0xE6 - <undef> */ ///Favorites
  387. ENH 0, /* 0xE7 - <undef> */ ///Refresh
  388. ENH 0, /* 0xE8 - <undef> */ ///Stop
  389. ENH 0, /* 0xE9 - <undef> */ ///Forward
  390. ENH 0, /* 0xEA - <undef> */ ///Back
  391. ENH 0, /* 0xEB - <undef> */ ///My Computer
  392. ENH 0, /* 0xEC - <undef> */ ///Mail
  393. ENH 0, /* 0xED - <undef> */ ///Media
  394. 0, /* 0xEE - <undef> */
  395. 0, /* 0xEF - <undef> */
  396. 0, /* 0xF0 - <undef> */
  397. 0, /* 0xF1 - <undef> */
  398. 0, /* 0xF2 - <undef> */
  399. 0, /* 0xF3 - <undef> */
  400. 0, /* 0xF4 - <undef> */
  401. 0, /* 0xF5 - <undef> */
  402. 0, /* 0xF6 - <undef> */
  403. 0, /* 0xF7 - <undef> */
  404. 0, /* 0xF8 - <undef> */
  405. 0, /* 0xF9 - <undef> */
  406. 0, /* 0xFA - <undef> */
  407. 0, /* 0xFB - <undef> */
  408. 0, /* 0xFC - <undef> */
  409. 0, /* 0xFD - <undef> */
  410. 0, /* 0xFE - <undef> */
  411. 0, /* 0xFF - <undef> */
  412. };
  413. #undef XT
  414. #undef AT
  415. #undef ENH
  416. #undef NEC
  417. /*****************************************************************************
  418. *
  419. * @doc INTERNAL
  420. *
  421. * @struct CKbd |
  422. *
  423. * The <i IDirectInputDeviceCallback> object for the
  424. * generic keyboard.
  425. *
  426. * @field IDirectInputDeviceCalllback | didc |
  427. *
  428. * The object (containing vtbl).
  429. *
  430. * @field PMKBDSTAT | pksPhys |
  431. *
  432. * Pointer to physical keyboard status information kept down in the
  433. * VxD.
  434. *
  435. * @field VXDINSTANCE * | pvi |
  436. *
  437. * The DirectInput instance handle.
  438. *
  439. * @field DWORD | dwKbdType |
  440. *
  441. * The device subtype for this keyboard.
  442. *
  443. * @field DWORD | flEmulation |
  444. *
  445. * The emulation flags forced by the application. If any of
  446. * these flags is set (actually, at most one will be set), then
  447. * we are an alias device.
  448. *
  449. * @field DIDATAFORMAT | df |
  450. *
  451. * The dynamically-generated data format based on the
  452. * keyboard type.
  453. *
  454. * @field DIOBJECTDATAFORMAT | rgodf[] |
  455. *
  456. * Object data format table generated as part of the
  457. * <e CKbd.df>.
  458. *
  459. * @comm
  460. *
  461. * It is the caller's responsibility to serialize access as
  462. * necessary.
  463. *
  464. *****************************************************************************/
  465. typedef struct CKbd {
  466. /* Supported interfaces */
  467. IDirectInputDeviceCallback dcb;
  468. PKBDSTAT pksPhys;
  469. VXDINSTANCE *pvi;
  470. DWORD dwKbdType;
  471. DWORD flEmulation;
  472. DIDATAFORMAT df;
  473. DIOBJECTDATAFORMAT rgodf[DIKBD_CKEYS];
  474. } CKbd, DK, *PDK;
  475. #define ThisClass CKbd
  476. #define ThisInterface IDirectInputDeviceCallback
  477. #define riidExpected &IID_IDirectInputDeviceCallback
  478. /*****************************************************************************
  479. *
  480. * CKbd::QueryInterface (from IUnknown)
  481. * CKbd::AddRef (from IUnknown)
  482. * CKbd::Release (from IUnknown)
  483. *
  484. *****************************************************************************/
  485. /*****************************************************************************
  486. *
  487. * @doc INTERNAL
  488. *
  489. * @method HRESULT | CKbd | QueryInterface |
  490. *
  491. * Gives a client access to other interfaces on an object.
  492. *
  493. * @parm IN REFIID | riid |
  494. *
  495. * The requested interface's IID.
  496. *
  497. * @parm OUT LPVOID * | ppvObj |
  498. *
  499. * Receives a pointer to the obtained interface.
  500. *
  501. * @returns
  502. *
  503. * Returns a COM error code.
  504. *
  505. * @xref OLE documentation for <mf IUnknown::QueryInterface>.
  506. *
  507. *****************************************************************************
  508. *
  509. * @doc INTERNAL
  510. *
  511. * @method HRESULT | CKbd | AddRef |
  512. *
  513. * Increments the reference count for the interface.
  514. *
  515. * @returns
  516. *
  517. * Returns the object reference count.
  518. *
  519. * @xref OLE documentation for <mf IUnknown::AddRef>.
  520. *
  521. *****************************************************************************
  522. *
  523. * @doc INTERNAL
  524. *
  525. * @method HRESULT | CKbd | Release |
  526. *
  527. * Decrements the reference count for the interface.
  528. * If the reference count on the object falls to zero,
  529. * the object is freed from memory.
  530. *
  531. * @returns
  532. *
  533. * Returns the object reference count.
  534. *
  535. * @xref OLE documentation for <mf IUnknown::Release>.
  536. *
  537. *****************************************************************************
  538. *
  539. * @doc INTERNAL
  540. *
  541. * @method HRESULT | CKbd | QIHelper |
  542. *
  543. * We don't have any dynamic interfaces and simply forward
  544. * to <f Common_QIHelper>.
  545. *
  546. * @parm IN REFIID | riid |
  547. *
  548. * The requested interface's IID.
  549. *
  550. * @parm OUT LPVOID * | ppvObj |
  551. *
  552. * Receives a pointer to the obtained interface.
  553. *
  554. *****************************************************************************
  555. *
  556. * @doc INTERNAL
  557. *
  558. * @method HRESULT | CKbd | AppFinalize |
  559. *
  560. * We don't have any weak pointers, so we can just
  561. * forward to <f Common_Finalize>.
  562. *
  563. * @parm PV | pvObj |
  564. *
  565. * Object being released from the application's perspective.
  566. *
  567. *****************************************************************************/
  568. #ifdef DEBUG
  569. Default_QueryInterface(CKbd)
  570. Default_AddRef(CKbd)
  571. Default_Release(CKbd)
  572. #else
  573. #define CKbd_QueryInterface Common_QueryInterface
  574. #define CKbd_AddRef Common_AddRef
  575. #define CKbd_Release Common_Release
  576. #endif
  577. #define CKbd_QIHelper Common_QIHelper
  578. #define CKbd_AppFinalize Common_AppFinalize
  579. /*****************************************************************************
  580. *
  581. * @doc INTERNAL
  582. *
  583. * @func void | CKbd_Finalize |
  584. *
  585. * Releases the resources of the device.
  586. *
  587. * @parm PV | pvObj |
  588. *
  589. * Object being released. Note that it may not have been
  590. * completely initialized, so everything should be done
  591. * carefully.
  592. *
  593. *****************************************************************************/
  594. void INTERNAL
  595. CKbd_Finalize(PV pvObj)
  596. {
  597. PDK this = pvObj;
  598. if (this->pvi) {
  599. HRESULT hres;
  600. hres = Hel_DestroyInstance(this->pvi);
  601. AssertF(SUCCEEDED(hres));
  602. }
  603. }
  604. /*****************************************************************************
  605. *
  606. * @doc INTERNAL
  607. *
  608. * @func int | WrappedGetKeyboardType |
  609. *
  610. * GetKeyboardType but wrapped in DEBUG for registry overrides.
  611. *
  612. * @parm int | nTypeFlag |
  613. *
  614. * Which data to return. Only 0, 1 and 2 are supported
  615. *
  616. * @returns
  617. *
  618. * int value requested
  619. *
  620. *****************************************************************************/
  621. #ifndef DEBUG
  622. #ifdef USE_WM_INPUT
  623. #define WrappedGetKeyboardType(x) DIRaw_GetKeyboardType(x)
  624. #else
  625. #define WrappedGetKeyboardType(x) GetKeyboardType(x)
  626. #endif
  627. #else
  628. int INTERNAL WrappedGetKeyboardType
  629. (
  630. int nTypeFlag
  631. )
  632. {
  633. TCHAR ValueName[2];
  634. int TypeRes;
  635. #ifdef USE_WM_INPUT
  636. TypeRes = DIRaw_GetKeyboardType( nTypeFlag );
  637. #else
  638. TypeRes = GetKeyboardType( nTypeFlag );
  639. #endif
  640. if( nTypeFlag < 10 )
  641. {
  642. ValueName[0] = TEXT( '0' ) + nTypeFlag;
  643. ValueName[1] = TEXT( '\0' );
  644. TypeRes = (int)RegQueryDIDword( REGSTR_KEY_KEYBTYPE, ValueName, (DWORD)TypeRes );
  645. SquirtSqflPtszV(sqfl | sqflTrace,
  646. TEXT( "DINPUT: GetKeyboardType(%d) returning 0x%08x" ),
  647. nTypeFlag, TypeRes );
  648. }
  649. else
  650. {
  651. RPF( "Somebody is passing %d to WrappedGetKeyboardType", nTypeFlag );
  652. }
  653. return TypeRes;
  654. }
  655. #endif
  656. /*****************************************************************************
  657. *
  658. * @doc INTERNAL
  659. *
  660. * @method HRESULT | CKbd | Acquire |
  661. *
  662. * Tell the device driver to begin data acquisition.
  663. *
  664. * It is the caller's responsibility to have set the
  665. * data format before obtaining acquisition.
  666. *
  667. * @returns
  668. *
  669. * Returns a COM error code. The following error codes are
  670. * intended to be illustrative and not necessarily comprehensive.
  671. *
  672. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  673. *
  674. * <c S_FALSE>: The operation was begun and should be completed
  675. * by the caller by communicating with the <t VXDINSTANCE>.
  676. *
  677. *****************************************************************************/
  678. STDMETHODIMP
  679. CKbd_Acquire(PDICB pdcb)
  680. {
  681. VXDDWORDDATA vdd;
  682. PDK this;
  683. HRESULT hres;
  684. /*
  685. * This is an internal interface, so we can skimp on validation.
  686. */
  687. this = _thisPvNm(pdcb, dcb);
  688. /*
  689. * Propagate the state of the potential toggle keys down to
  690. * the VxD. This also alerts the VxD that acquisition is coming,
  691. * so it can reset the state tables if necessary.
  692. */
  693. vdd.pvi = this->pvi;
  694. vdd.dw = 0;
  695. if( WrappedGetKeyboardType(0) == 7 )
  696. {
  697. /*
  698. * Let the keyboard driver know that this is an FE keyboard
  699. */
  700. vdd.dw |= 16;
  701. if (GetAsyncKeyState(VK_KANA) < 0) {
  702. vdd.dw |= 1;
  703. }
  704. if (GetAsyncKeyState(VK_CAPITAL) < 0) {
  705. vdd.dw |= 2;
  706. }
  707. if (GetAsyncKeyState(VK_KANJI) < 0) {
  708. vdd.dw |= 8;
  709. }
  710. }
  711. if( this->pvi->fl & VIFL_CAPTURED )
  712. {
  713. vdd.dw |= 4; // Tell the keyboard driver to pre-acquire hooks
  714. }
  715. hres = Hel_Kbd_InitKeys(&vdd);
  716. if( this->pvi->fl & VIFL_CAPTURED )
  717. {
  718. /*
  719. * A bit of work needs to be done at ring 3 now.
  720. * Try to clear any key that is set. Start with VK_BACK as mouse
  721. * buttons and undefined things go before.
  722. * This still covers a lot of undefined VKs but we're less likely
  723. * to do damage clearing something that was undefined than leaving
  724. * keys uncleared.
  725. */
  726. BYTE vk;
  727. for( vk=VK_BACK; vk<VK_OEM_CLEAR; vk++ )
  728. {
  729. if( ( vk == VK_KANA ) || ( vk == VK_KANJI ) || ( vk == VK_CAPITAL ) )
  730. {
  731. continue;
  732. }
  733. if(GetAsyncKeyState(vk) < 0)
  734. {
  735. keybd_event( vk, 0, KEYEVENTF_KEYUP, 0 );
  736. }
  737. }
  738. }
  739. return S_FALSE;
  740. }
  741. /*****************************************************************************
  742. *
  743. * @doc INTERNAL
  744. *
  745. * @method HRESULT | CKbd | GetInstance |
  746. *
  747. * Obtains the DirectInput instance handle.
  748. *
  749. * @parm OUT PPV | ppvi |
  750. *
  751. * Receives the instance handle.
  752. *
  753. *****************************************************************************/
  754. STDMETHODIMP
  755. CKbd_GetInstance(PDICB pdcb, PPV ppvi)
  756. {
  757. HRESULT hres;
  758. PDK this;
  759. EnterProcI(IDirectInputDeviceCallback::Kbd::GetInstance, (_ "p", pdcb));
  760. /*
  761. * This is an internal interface, so we can skimp on validation.
  762. */
  763. this = _thisPvNm(pdcb, dcb);
  764. AssertF(this->pvi);
  765. *ppvi = (PV)this->pvi;
  766. hres = S_OK;
  767. ExitOleProcPpvR(ppvi);
  768. return hres;
  769. }
  770. /*****************************************************************************
  771. *
  772. * @doc INTERNAL
  773. *
  774. * @method HRESULT | CKbd | GetDataFormat |
  775. *
  776. * Obtains the device's preferred data format.
  777. *
  778. * @parm OUT LPDIDEVICEFORMAT * | ppdf |
  779. *
  780. * <t LPDIDEVICEFORMAT> to receive pointer to device format.
  781. *
  782. * @returns
  783. *
  784. * Returns a COM error code. The following error codes are
  785. * intended to be illustrative and not necessarily comprehensive.
  786. *
  787. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  788. *
  789. * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
  790. * <p lpmdr> parameter is not a valid pointer.
  791. *
  792. *****************************************************************************/
  793. STDMETHODIMP
  794. CKbd_GetDataFormat(PDICB pdcb, LPDIDATAFORMAT *ppdf)
  795. {
  796. HRESULT hres;
  797. PDK this;
  798. EnterProcI(IDirectInputDeviceCallback::Kbd::GetDataFormat,
  799. (_ "p", pdcb));
  800. /*
  801. * This is an internal interface, so we can skimp on validation.
  802. */
  803. this = _thisPvNm(pdcb, dcb);
  804. *ppdf = &this->df;
  805. hres = S_OK;
  806. ExitOleProcPpvR(ppdf);
  807. return hres;
  808. }
  809. /*****************************************************************************
  810. *
  811. * @doc INTERNAL
  812. *
  813. * @method HRESULT | CKbd | GetDeviceInfo |
  814. *
  815. * Obtain general information about the device.
  816. *
  817. * @parm OUT LPDIDEVICEINSTANCEW | pdiW |
  818. *
  819. * <t DEVICEINSTANCE> to be filled in. The
  820. * <e DEVICEINSTANCE.dwSize> and <e DEVICEINSTANCE.guidInstance>
  821. * have already been filled in.
  822. *
  823. * Secret convenience: <e DEVICEINSTANCE.guidProduct> is equal
  824. * to <e DEVICEINSTANCE.guidInstance>.
  825. *
  826. *****************************************************************************/
  827. STDMETHODIMP
  828. CKbd_GetDeviceInfo(PDICB pdcb, LPDIDEVICEINSTANCEW pdiW)
  829. {
  830. HRESULT hres;
  831. PDK this;
  832. EnterProcI(IDirectInputDeviceCallback::Kbd::GetDeviceInfo,
  833. (_ "pp", pdcb, pdiW));
  834. /*
  835. * This is an internal interface, so we can skimp on validation.
  836. */
  837. this = _thisPvNm(pdcb, dcb);
  838. AssertF(IsValidSizeDIDEVICEINSTANCEW(pdiW->dwSize));
  839. AssertF(IsEqualGUID(&GUID_SysKeyboard , &pdiW->guidInstance) ||
  840. IsEqualGUID(&GUID_SysKeyboardEm , &pdiW->guidInstance) ||
  841. IsEqualGUID(&GUID_SysKeyboardEm2, &pdiW->guidInstance));
  842. pdiW->guidProduct = GUID_SysKeyboard;
  843. pdiW->dwDevType = MAKE_DIDEVICE_TYPE(DIDEVTYPE_KEYBOARD,
  844. this->dwKbdType);
  845. LoadStringW(g_hinst, IDS_STDKEYBOARD, pdiW->tszProductName, cA(pdiW->tszProductName));
  846. LoadStringW(g_hinst, IDS_STDKEYBOARD, pdiW->tszInstanceName, cA(pdiW->tszInstanceName));
  847. hres = S_OK;
  848. ExitOleProcR();
  849. return hres;
  850. }
  851. /*****************************************************************************
  852. *
  853. * @doc INTERNAL
  854. *
  855. * @method void | CKbd | GetCapabilities |
  856. *
  857. * Get keyboard device capabilities.
  858. *
  859. * @parm LPDIDEVCAPS | pdc |
  860. *
  861. * Device capabilities structure to receive result.
  862. *
  863. * @returns
  864. * <c S_OK> on success.
  865. *
  866. *****************************************************************************/
  867. STDMETHODIMP
  868. CKbd_GetCapabilities(PDICB pdcb, LPDIDEVCAPS pdc)
  869. {
  870. HRESULT hres;
  871. PDK this;
  872. EnterProcI(IDirectInputDeviceCallback::Kbd::GetCapabilities,
  873. (_ "pp", pdcb, pdc));
  874. /*
  875. * This is an internal interface, so we can skimp on validation.
  876. */
  877. this = _thisPvNm(pdcb, dcb);
  878. pdc->dwDevType = MAKE_DIDEVICE_TYPE(DIDEVTYPE_KEYBOARD,
  879. this->dwKbdType);
  880. pdc->dwFlags = DIDC_ATTACHED;
  881. if (this->flEmulation) {
  882. pdc->dwFlags |= DIDC_ALIAS;
  883. }
  884. // Remove these assertions for 32650
  885. // AssertF(pdc->dwAxes == 0);
  886. // AssertF(pdc->dwPOVs == 0);
  887. pdc->dwButtons = this->df.dwNumObjs;
  888. hres = S_OK;
  889. ExitOleProcR();
  890. return hres;
  891. }
  892. /*****************************************************************************
  893. *
  894. * @doc INTERNAL
  895. *
  896. * @method void | CKbd | GetPhysicalState |
  897. *
  898. * Read the physical keyboard state into <p pksOut>.
  899. *
  900. * Note that it doesn't matter if this is not atomic.
  901. * If a key goes down or up while we are reading it,
  902. * we will get a mix of old and new data. No big deal.
  903. *
  904. * @parm PDK | this |
  905. *
  906. * The object in question.
  907. *
  908. * @parm PKBDSTATE | pksOut |
  909. *
  910. * Where to put the keyboard state.
  911. * @returns
  912. * None.
  913. *
  914. *****************************************************************************/
  915. void INLINE
  916. CKbd_GetPhysicalState(PDK this, PKBDSTAT pksOut)
  917. {
  918. AssertF(this->pksPhys);
  919. *pksOut = *this->pksPhys;
  920. }
  921. /*****************************************************************************
  922. *
  923. * @doc INTERNAL
  924. *
  925. * @method HRESULT | CKbd | GetDeviceState |
  926. *
  927. * Obtains the state of the keyboard device.
  928. *
  929. * It is the caller's responsibility to have validated all the
  930. * parameters and ensure that the device has been acquired.
  931. *
  932. * @parm OUT LPVOID | lpvData |
  933. *
  934. * Keyboard data in the preferred data format.
  935. *
  936. * @returns
  937. *
  938. * Returns a COM error code. The following error codes are
  939. * intended to be illustrative and not necessarily comprehensive.
  940. *
  941. * <c DI_OK> = <c S_OK>: The operation completed successfully.
  942. *
  943. * <c DIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
  944. * <p lpmdr> parameter is not a valid pointer.
  945. *
  946. *****************************************************************************/
  947. STDMETHODIMP
  948. CKbd_GetDeviceState(PDICB pdcb, LPVOID pvData)
  949. {
  950. HRESULT hres;
  951. PDK this;
  952. PKBDSTAT pkstOut = pvData;
  953. EnterProcI(IDirectInputDeviceCallback::Kbd::GetDeviceState,
  954. (_ "pp", pdcb, pvData));
  955. /*
  956. * This is an internal interface, so we can skimp on validation.
  957. */
  958. this = _thisPvNm(pdcb, dcb);
  959. /*
  960. * ISSUE-2001/03/29-timgill older apps may need compat behaviour
  961. * We never used to check whether or not the device was still
  962. * acquired since without exclusive mode there would be no reason for
  963. * the device not to be.
  964. * To keep behavior the same for older apps it might be better to
  965. * only fail if VIFL_CAPTURED is not set but just checking VIFL_ACQUIRED
  966. * is good enough for now, maybe for ever.
  967. */
  968. // if( !(this->pvi->fl & VIFL_CAPTURED)
  969. // || (this->pvi->fl & VIFL_ACQUIRED) )
  970. if( this->pvi->fl & VIFL_ACQUIRED )
  971. {
  972. CKbd_GetPhysicalState(this, pkstOut);
  973. hres = S_OK;
  974. } else {
  975. RPF( "Keyboard VxD flags: 0x%08x", this->pvi->fl );
  976. hres = DIERR_INPUTLOST;
  977. }
  978. ExitOleProcR();
  979. return hres;
  980. }
  981. /*****************************************************************************
  982. *
  983. * @doc INTERNAL
  984. *
  985. * @method HRESULT | CKbd | GetObjectInfo |
  986. *
  987. * Obtain the friendly name of an object, passwed by index
  988. * into the preferred data format.
  989. *
  990. * @parm IN LPCDIPROPINFO | ppropi |
  991. *
  992. * Information describing the object being accessed.
  993. *
  994. * @parm IN OUT LPDIDEVICEOBJECTINSTANCEW | pdidioiW |
  995. *
  996. * Structure to receive information. The
  997. * <e DIDEVICEOBJECTINSTANCE.guidType>,
  998. * <e DIDEVICEOBJECTINSTANCE.dwOfs>,
  999. * and
  1000. * <e DIDEVICEOBJECTINSTANCE.dwType>
  1001. * fields have already been filled in.
  1002. *
  1003. * @returns
  1004. *
  1005. * Returns a COM error code.
  1006. *
  1007. *****************************************************************************/
  1008. STDMETHODIMP
  1009. CKbd_GetObjectInfo(PDICB pdcb, LPCDIPROPINFO ppropi,
  1010. LPDIDEVICEOBJECTINSTANCEW pdidoiW)
  1011. {
  1012. HRESULT hres;
  1013. PDK this;
  1014. EnterProcI(IDirectInputDeviceCallback::Kbd::GetObjectInfo,
  1015. (_ "pxp", pdcb, ppropi->iobj, pdidoiW));
  1016. /*
  1017. * This is an internal interface, so we can skimp on validation.
  1018. */
  1019. this = _thisPvNm(pdcb, dcb);
  1020. #ifdef HAVE_DIDEVICEOBJECTINSTANCE_DX5
  1021. AssertF(IsValidSizeDIDEVICEOBJECTINSTANCEW(pdidoiW->dwSize));
  1022. #endif
  1023. if (ppropi->iobj < this->df.dwNumObjs) {
  1024. AssertF(this->rgodf == this->df.rgodf);
  1025. AssertF(ppropi->dwDevType == this->rgodf[ppropi->iobj].dwType);
  1026. AssertF(ppropi->dwDevType & DIDFT_BUTTON);
  1027. LoadStringW(g_hinst,
  1028. IDS_KEYBOARDOBJECT +
  1029. DIDFT_GETINSTANCE(ppropi->dwDevType),
  1030. pdidoiW->tszName, cA(pdidoiW->tszName));
  1031. /*
  1032. * We do not support force feedback on keyboards, so
  1033. * there are no FF flags to report.
  1034. */
  1035. hres = S_OK;
  1036. } else {
  1037. hres = E_INVALIDARG;
  1038. }
  1039. ExitOleProcR();
  1040. return hres;
  1041. }
  1042. /*****************************************************************************
  1043. *
  1044. * @doc INTERNAL
  1045. *
  1046. * @method HRESULT | CKbd | SetCooperativeLevel |
  1047. *
  1048. * Notify the device of the cooperative level.
  1049. *
  1050. * @parm IN HWND | hwnd |
  1051. *
  1052. * The window handle.
  1053. *
  1054. * @parm IN DWORD | dwFlags |
  1055. *
  1056. * The cooperativity level. We do not support exclusive access.
  1057. *
  1058. * @returns
  1059. *
  1060. * Returns a COM error code.
  1061. *
  1062. *****************************************************************************/
  1063. STDMETHODIMP
  1064. CKbd_SetCooperativeLevel(PDICB pdcb, HWND hwnd, DWORD dwFlags)
  1065. {
  1066. HRESULT hres;
  1067. PDK this;
  1068. EnterProcI(IDirectInputDeviceCallback::Kbd::SetCooperativityLevel,
  1069. (_ "pxx", pdcb, hwnd, dwFlags));
  1070. /*
  1071. * This is an internal interface, so we can skimp on validation.
  1072. */
  1073. this = _thisPvNm(pdcb, dcb);
  1074. AssertF(this->pvi);
  1075. AssertF(DIGETEMFL(this->pvi->fl) == 0 ||
  1076. DIGETEMFL(this->pvi->fl) == DIEMFL_KBD ||
  1077. DIGETEMFL(this->pvi->fl) == DIEMFL_KBD2);
  1078. /*
  1079. * We don't allow background exclusive access.
  1080. * This is actually not a real problem to support; we just don't feel like it
  1081. * because it's too dangerous.
  1082. */
  1083. if (!(this->pvi->fl & DIMAKEEMFL(DIEMFL_KBD2))) {
  1084. if (dwFlags & DISCL_EXCLUSIVE) {
  1085. if (dwFlags & DISCL_FOREGROUND) {
  1086. this->pvi->fl |= VIFL_CAPTURED;
  1087. this->pvi->fl &= ~VIFL_NOWINKEY;
  1088. hres = S_OK;
  1089. } else { /* Disallow exclusive background */
  1090. hres = E_NOTIMPL;
  1091. }
  1092. } else {
  1093. this->pvi->fl &= ~VIFL_CAPTURED;
  1094. this->pvi->fl &= ~VIFL_NOWINKEY;
  1095. hres = S_OK;
  1096. if (dwFlags & DISCL_NOWINKEY) {
  1097. if (dwFlags & DISCL_FOREGROUND) {
  1098. this->pvi->fl |= VIFL_NOWINKEY;
  1099. } else {
  1100. RPF("Kbd::SetCooperativeLevel: NOWINKEY not supported in Backgroud mode.");
  1101. hres = E_NOTIMPL;
  1102. }
  1103. }
  1104. }
  1105. } else {
  1106. /*
  1107. * Emulation level 2 does not support background access.
  1108. */
  1109. if ((this->pvi->fl & DIMAKEEMFL(DIEMFL_KBD2)) &&
  1110. (dwFlags & DISCL_BACKGROUND)) {
  1111. hres = E_NOTIMPL;
  1112. } else {
  1113. this->pvi->fl &= ~VIFL_NOWINKEY;
  1114. hres = S_OK;
  1115. if (dwFlags & DISCL_NOWINKEY) {
  1116. if (dwFlags & DISCL_FOREGROUND) {
  1117. this->pvi->fl |= VIFL_NOWINKEY;
  1118. } else {
  1119. RPF("Kbd::SetCooperativeLevel: NOWINKEY not supported in Backgroud mode.");
  1120. hres = E_NOTIMPL;
  1121. }
  1122. }
  1123. }
  1124. }
  1125. ExitOleProcR();
  1126. return hres;
  1127. }
  1128. /*****************************************************************************
  1129. *
  1130. * @doc INTERNAL
  1131. *
  1132. * @method HRESULT | CKbd | RunControlPanel |
  1133. *
  1134. * Run the keyboard control panel.
  1135. *
  1136. * @parm IN HWND | hwndOwner |
  1137. *
  1138. * The owner window.
  1139. *
  1140. * @parm DWORD | dwFlags |
  1141. *
  1142. * Flags.
  1143. *
  1144. *****************************************************************************/
  1145. #pragma BEGIN_CONST_DATA
  1146. TCHAR c_tszKeyboard[] = TEXT("keyboard");
  1147. #pragma END_CONST_DATA
  1148. STDMETHODIMP
  1149. CKbd_RunControlPanel(PDICB pdcb, HWND hwnd, DWORD dwFlags)
  1150. {
  1151. HRESULT hres;
  1152. PDK this;
  1153. EnterProcI(IDirectInputDeviceCallback::Kbd::RunControlPanel,
  1154. (_ "pxx", pdcb, hwnd, dwFlags));
  1155. /*
  1156. * This is an internal interface, so we can skimp on validation.
  1157. */
  1158. this = _thisPvNm(pdcb, dcb);
  1159. hres = hresRunControlPanel(c_tszKeyboard);
  1160. ExitOleProcR();
  1161. return hres;
  1162. }
  1163. /*****************************************************************************
  1164. *
  1165. * @doc INTERNAL
  1166. *
  1167. * @method DWORD | CKbd | InitJapanese |
  1168. *
  1169. * Initialize the Japanese keyboard goo.
  1170. *
  1171. * Annoying quirk! On Windows 95, Japanese keyboards generate
  1172. * their own scan codes. But on Windows NT, they generate
  1173. * "nearly AT-compatible" scan codes.
  1174. *
  1175. * @returns
  1176. *
  1177. * KBDTYPE_ANYKBD or KBDTYPE_ANYKBD + KBDTYPE_NECTGL.
  1178. *
  1179. *****************************************************************************/
  1180. DWORD INTERNAL
  1181. CKbd_InitJapanese(PDK this, PVXDDEVICEFORMAT pdevf)
  1182. {
  1183. DWORD dwSubType;
  1184. UINT idKbd;
  1185. DWORD dwRc;
  1186. dwSubType = WrappedGetKeyboardType(1);
  1187. if (HIBYTE(dwSubType) == 0x0D) { /* NEC PC98 series */
  1188. switch (LOBYTE(dwSubType)) {
  1189. case 1:
  1190. default:
  1191. idKbd = IDDATA_KBD_NEC98;
  1192. this->dwKbdType = DIDEVTYPEKEYBOARD_NEC98;
  1193. dwRc = KBDTYPE_ANYKBD + KBDTYPE_NECTGL;
  1194. break;
  1195. case 4:
  1196. idKbd = IDDATA_KBD_NEC98LAPTOP;
  1197. this->dwKbdType = DIDEVTYPEKEYBOARD_NEC98LAPTOP;
  1198. dwRc = KBDTYPE_ANYKBD + KBDTYPE_NECTGL;
  1199. break;
  1200. case 5:
  1201. idKbd = IDDATA_KBD_NEC98_106;
  1202. this->dwKbdType = DIDEVTYPEKEYBOARD_NEC98106;
  1203. dwRc = KBDTYPE_ANYKBD + KBDTYPE_NECTGL;
  1204. break;
  1205. }
  1206. /*
  1207. * If the scan code for ESC is 1, then we're on an
  1208. * NEC98 keyboard that acts AT-like.
  1209. */
  1210. CAssertF(IDDATA_KBD_NEC98_NT - IDDATA_KBD_NEC98 ==
  1211. IDDATA_KBD_NEC98LAPTOP_NT - IDDATA_KBD_NEC98LAPTOP);
  1212. CAssertF(IDDATA_KBD_NEC98_NT - IDDATA_KBD_NEC98 ==
  1213. IDDATA_KBD_NEC98_106_NT - IDDATA_KBD_NEC98_106);
  1214. if (MapVirtualKey(VK_ESCAPE, 0) == DIK_ESCAPE) {
  1215. idKbd += IDDATA_KBD_NEC98_NT - IDDATA_KBD_NEC98;
  1216. }
  1217. } else {
  1218. switch (dwSubType) {
  1219. case 0:
  1220. this->dwKbdType = DIDEVTYPEKEYBOARD_PCENH;
  1221. dwRc = KBDTYPE_ENH;
  1222. goto done; /* Yuck */
  1223. case 1:
  1224. idKbd = IDDATA_KBD_JAPANAX;
  1225. this->dwKbdType = DIDEVTYPEKEYBOARD_JAPANAX;
  1226. dwRc = KBDTYPE_ANYKBD;
  1227. break;
  1228. case 13:
  1229. case 14:
  1230. case 15:
  1231. idKbd = IDDATA_KBD_J3100;
  1232. this->dwKbdType = DIDEVTYPEKEYBOARD_J3100;
  1233. dwRc = KBDTYPE_ANYKBD;
  1234. break;
  1235. case 4: /* Rumored to be Epson */
  1236. case 5: /* Rumored to be Fujitsu */
  1237. case 7: /* Rumored to be IBMJ */
  1238. case 10: /* Rumored to be Matsushita */
  1239. case 18: /* Rumored to be Toshiba */
  1240. default:
  1241. idKbd = IDDATA_KBD_JAPAN106;
  1242. this->dwKbdType = DIDEVTYPEKEYBOARD_JAPAN106;
  1243. dwRc = KBDTYPE_ANYKBD;
  1244. break;
  1245. }
  1246. }
  1247. if( fWinnt )
  1248. {
  1249. /*
  1250. * ISSUE-2001/03/29-timgill Japanese keyboard assumption needs testing
  1251. * All Japanese keyboards on NT have toggle keys
  1252. * Except subtype zero? Needs test
  1253. */
  1254. dwRc = KBDTYPE_ANYKBD + KBDTYPE_NTTGL;
  1255. }
  1256. /*
  1257. * Now load up the translation table goo.
  1258. */
  1259. pdevf->dwExtra = (UINT_PTR)pvFindResource(g_hinst, idKbd, RT_RCDATA);
  1260. if (pdevf->dwExtra == 0) {
  1261. dwRc = 0;
  1262. }
  1263. done:;
  1264. return dwRc;
  1265. }
  1266. /*****************************************************************************
  1267. *
  1268. * @doc INTERNAL
  1269. *
  1270. * @method HRESULT | CKbd | Init |
  1271. *
  1272. * Initialize the object by establishing the data format
  1273. * based on the keyboard type. Anything we don't recognize,
  1274. * we treat as a PC Enhanced keyboard.
  1275. *
  1276. * @parm REFGUID | rguid |
  1277. *
  1278. * The instance GUID we are being asked to create.
  1279. *
  1280. *****************************************************************************/
  1281. HRESULT INTERNAL
  1282. CKbd_Init(PDK this, REFGUID rguid)
  1283. {
  1284. DWORD dwDevType;
  1285. UINT ib;
  1286. HRESULT hres;
  1287. VXDDEVICEFORMAT devf;
  1288. EnterProc(CKbd_Init, (_ "pG", this, rguid));
  1289. #ifdef DEBUG
  1290. /*
  1291. * Check that the Japan tables aren't messed up.
  1292. */
  1293. {
  1294. UINT idk;
  1295. for (idk = IDDATA_KBD_NEC98; idk <= IDDATA_KBD_J3100; idk++) {
  1296. BYTE rgb[DIKBD_CKEYS];
  1297. HANDLE hrsrc;
  1298. LPBYTE pb;
  1299. ZeroX(rgb);
  1300. /*
  1301. * Make sure the table exists.
  1302. */
  1303. hrsrc = FindResource(g_hinst, (LPTSTR)(LONG_PTR)idk, RT_RCDATA);
  1304. AssertF(hrsrc);
  1305. pb = LoadResource(g_hinst, hrsrc);
  1306. /*
  1307. * Walk the table and make sure each thing that exists
  1308. * in the translation table also exists in our master table.
  1309. * Also make sure that it isn't a dup with something else
  1310. * in the same table.
  1311. */
  1312. /*
  1313. * Note, however, that the JAPAN106 keyboard contains
  1314. * dups so we can save having to write an entire
  1315. * translation table. And then NEC98_NT tables contain
  1316. * lots of dups out of sheer laziness.
  1317. */
  1318. for (ib = 0; ib < DIKBD_CKEYS; ib++) {
  1319. if (pb[ib]) {
  1320. AssertF(c_rgktWhich[pb[ib]] & KBDTYPE_ANYKBD);
  1321. AssertF(fLorFF(idk == IDDATA_KBD_JAPAN106 && ib == 0x73,
  1322. rgb[pb[ib]] == 0));
  1323. rgb[pb[ib]] = 1;
  1324. }
  1325. }
  1326. }
  1327. }
  1328. #endif
  1329. this->df.dwSize = cbX(DIDATAFORMAT);
  1330. this->df.dwObjSize = cbX(DIOBJECTDATAFORMAT);
  1331. this->df.dwDataSize = sizeof(KBDSTAT);
  1332. this->df.rgodf = this->rgodf;
  1333. this->dwKbdType = WrappedGetKeyboardType(0);
  1334. /*
  1335. * Create the object with the most optimistic data format.
  1336. * This allows apps to access new keys without having to rev DINPUT.
  1337. *
  1338. * However, leave out the following scan codes because some keyboards
  1339. * generate them spuriously:
  1340. *
  1341. * 0xB6
  1342. *
  1343. * If you hold the right shift key and then press an
  1344. * extended arrow key, then release both, some keyboards
  1345. * generate the following:
  1346. *
  1347. * 0x36 - right shift down
  1348. * 0xE0 0xB6 - extended right shift up (?)
  1349. * 0xE0 0x4B - extended left arrow down
  1350. * 0xE0 0xCB - extended left arrow up
  1351. * 0xE0 0x36 - extended right shift down (?)
  1352. * 0xE6 - right shift up
  1353. *
  1354. * The stray 0xE0 0x36 needs to be ignored.
  1355. *
  1356. * 0xAA
  1357. *
  1358. * Same as 0xB6, but with the left shift key.
  1359. *
  1360. *
  1361. */
  1362. for (ib = 0; ib < DIKBD_CKEYS; ib++) {
  1363. if (ib != 0xAA && ib != 0xB6) {
  1364. this->rgodf[ib].pguid = &GUID_Key;
  1365. this->rgodf[ib].dwOfs = ib;
  1366. this->rgodf[ib].dwType = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE(ib);
  1367. AssertF(this->rgodf[ib].dwFlags == 0);
  1368. }
  1369. }
  1370. devf.cObj = DIKBD_CKEYS;
  1371. devf.cbData = cbX(KBDSTAT);
  1372. devf.rgodf = this->rgodf;
  1373. /*
  1374. * But first a word from our sponsor: Figure out if this keyboard
  1375. * needs a translation table.
  1376. */
  1377. devf.dwExtra = 0; /* Assume no translation */
  1378. if (this->dwKbdType != 7) { /* Not a yucky Japanese keyboard */
  1379. switch (this->dwKbdType) {
  1380. case DIDEVTYPEKEYBOARD_PCXT: dwDevType = KBDTYPE_XT; break;
  1381. case DIDEVTYPEKEYBOARD_PCAT: dwDevType = KBDTYPE_AT; break;
  1382. default:
  1383. case DIDEVTYPEKEYBOARD_PCENH: dwDevType = KBDTYPE_ENH; break;
  1384. }
  1385. } else { /* Yucky Japanese keyboard */
  1386. dwDevType = CKbd_InitJapanese(this, &devf);
  1387. if (!dwDevType) {
  1388. goto justfail;
  1389. }
  1390. }
  1391. /*
  1392. * And now a word from our other sponsor: Figure out the
  1393. * emulation flags based on the GUID.
  1394. */
  1395. AssertF(GUID_SysKeyboard .Data1 == 0x6F1D2B61);
  1396. AssertF(GUID_SysKeyboardEm .Data1 == 0x6F1D2B82);
  1397. AssertF(GUID_SysKeyboardEm2.Data1 == 0x6F1D2B83);
  1398. switch (rguid->Data1) {
  1399. default:
  1400. case 0x6F1D2B61:
  1401. AssertF(IsEqualGUID(rguid, &GUID_SysKeyboard));
  1402. AssertF(this->flEmulation == 0);
  1403. break;
  1404. case 0x6F1D2B82:
  1405. AssertF(IsEqualGUID(rguid, &GUID_SysKeyboardEm));
  1406. this->flEmulation = DIEMFL_KBD;
  1407. break;
  1408. case 0x6F1D2B83:
  1409. AssertF(IsEqualGUID(rguid, &GUID_SysKeyboardEm2));
  1410. this->flEmulation = DIEMFL_KBD2;
  1411. break;
  1412. }
  1413. devf.dwEmulation = this->flEmulation;
  1414. //RPF("CKbd_Init: Kbd type: %d, subtype: %d, dwEmulation: %d", GetKeyboardType(0), GetKeyboardType(1), devf.dwEmulation);
  1415. hres = Hel_Kbd_CreateInstance(&devf, &this->pvi);
  1416. if (SUCCEEDED(hres)) {
  1417. UINT cobj;
  1418. BYTE rgbSeen[DIKBD_CKEYS];
  1419. AssertF(this->pvi);
  1420. AssertF(this->df.dwFlags == 0);
  1421. AssertF(this->df.dwNumObjs == 0);
  1422. /*
  1423. * Japanese keyboards have many-to-one mappings, so
  1424. * we need to filter out the dups or we end up in big
  1425. * trouble.
  1426. */
  1427. ZeroX(rgbSeen);
  1428. /*
  1429. * Now create the real data format.
  1430. *
  1431. * We shadow this->df.dwNumObjs in cobj so that the compiler
  1432. * can enregister it.
  1433. *
  1434. * Note that we filter through the translation table if there
  1435. * is one.
  1436. */
  1437. cobj = 0;
  1438. for (ib = 0; ib < DIKBD_CKEYS; ib++) {
  1439. BYTE bScan = devf.dwExtra ? ((LPBYTE)devf.dwExtra)[ib] : ib;
  1440. if ((c_rgktWhich[bScan] & dwDevType) && !rgbSeen[bScan]) {
  1441. PODF podf = &this->rgodf[cobj];
  1442. rgbSeen[bScan] = 1;
  1443. podf->pguid = &GUID_Key;
  1444. podf->dwOfs = bScan;
  1445. if (c_rgktWhich[bScan] & dwDevType & (KBDTYPE_NECTGL|KBDTYPE_NTTGL) ) {
  1446. podf->dwType = DIDFT_TGLBUTTON | DIDFT_MAKEINSTANCE(bScan);
  1447. } else {
  1448. podf->dwType = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE(bScan);
  1449. }
  1450. AssertF(podf->dwFlags == 0);
  1451. cobj++;
  1452. this->df.dwNumObjs++;
  1453. }
  1454. }
  1455. this->pksPhys = this->pvi->pState;
  1456. } else {
  1457. justfail:;
  1458. hres = E_FAIL;
  1459. }
  1460. ExitOleProc();
  1461. return hres;
  1462. }
  1463. /*****************************************************************************
  1464. *
  1465. * CKbd_New (constructor)
  1466. *
  1467. *****************************************************************************/
  1468. STDMETHODIMP
  1469. CKbd_New(PUNK punkOuter, REFGUID rguid, RIID riid, PPV ppvObj)
  1470. {
  1471. HRESULT hres;
  1472. EnterProcI(IDirectInputDeviceCallback::Kbd::<constructor>,
  1473. (_ "Gp", riid, ppvObj));
  1474. AssertF(IsEqualGUID(rguid, &GUID_SysKeyboard) ||
  1475. IsEqualGUID(rguid, &GUID_SysKeyboardEm) ||
  1476. IsEqualGUID(rguid, &GUID_SysKeyboardEm2));
  1477. hres = Common_NewRiid(CKbd, punkOuter, riid, ppvObj);
  1478. if (SUCCEEDED(hres)) {
  1479. /* Must use _thisPv in case of aggregation */
  1480. PDK this = _thisPv(*ppvObj);
  1481. if (SUCCEEDED(hres = CKbd_Init(this, rguid))) {
  1482. } else {
  1483. Invoke_Release(ppvObj);
  1484. }
  1485. }
  1486. ExitOleProcPpvR(ppvObj);
  1487. return hres;
  1488. }
  1489. /*****************************************************************************
  1490. *
  1491. * The long-awaited vtbls and templates
  1492. *
  1493. *****************************************************************************/
  1494. #pragma BEGIN_CONST_DATA
  1495. #define CKbd_Signature 0x2044424B /* "KBD " */
  1496. Interface_Template_Begin(CKbd)
  1497. Primary_Interface_Template(CKbd, IDirectInputDeviceCallback)
  1498. Interface_Template_End(CKbd)
  1499. Primary_Interface_Begin(CKbd, IDirectInputDeviceCallback)
  1500. CKbd_GetInstance,
  1501. CDefDcb_GetVersions,
  1502. CKbd_GetDataFormat,
  1503. CKbd_GetObjectInfo,
  1504. CKbd_GetCapabilities,
  1505. CKbd_Acquire,
  1506. CDefDcb_Unacquire,
  1507. CKbd_GetDeviceState,
  1508. CKbd_GetDeviceInfo,
  1509. CDefDcb_GetProperty,
  1510. CDefDcb_SetProperty,
  1511. CDefDcb_SetEventNotification,
  1512. CKbd_SetCooperativeLevel,
  1513. CKbd_RunControlPanel,
  1514. CDefDcb_CookDeviceData,
  1515. CDefDcb_CreateEffect,
  1516. CDefDcb_GetFFConfigKey,
  1517. CDefDcb_SendDeviceData,
  1518. CDefDcb_Poll,
  1519. CDefDcb_GetUsage,
  1520. CDefDcb_MapUsage,
  1521. CDefDcb_SetDIData,
  1522. Primary_Interface_End(CKbd, IDirectInputDeviceCallback)