Source code of Windows XP (NT5)
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.

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