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.

534 lines
15 KiB

  1. //
  2. // Input Manager
  3. //
  4. #ifndef _H_IM
  5. #define _H_IM
  6. #if defined(DLL_CORE) || defined(DLL_HOOK)
  7. //
  8. //
  9. // CONSTANTS
  10. //
  11. //
  12. //
  13. // Values used when accumulating events to return from IEM_TranslateLocal
  14. // and IEM_TranslateRemote.
  15. //
  16. #define IEM_EVENT_CTRL_DOWN 1
  17. #define IEM_EVENT_CTRL_UP 2
  18. #define IEM_EVENT_SHIFT_DOWN 3
  19. #define IEM_EVENT_SHIFT_UP 4
  20. #define IEM_EVENT_MENU_DOWN 5
  21. #define IEM_EVENT_MENU_UP 6
  22. #define IEM_EVENT_FORWARD 7
  23. #define IEM_EVENT_CONSUMED 8
  24. #define IEM_EVENT_REPLAY 9
  25. #define IEM_EVENT_REPLAY_VK 10
  26. #define IEM_EVENT_REPLAY_VK_DOWN 11
  27. #define IEM_EVENT_REPLAY_VK_UP 12
  28. #define IEM_EVENT_CAPS_LOCK_UP 13
  29. #define IEM_EVENT_CAPS_LOCK_DOWN 14
  30. #define IEM_EVENT_NUM_LOCK_UP 15
  31. #define IEM_EVENT_NUM_LOCK_DOWN 16
  32. #define IEM_EVENT_SCROLL_LOCK_UP 17
  33. #define IEM_EVENT_SCROLL_LOCK_DOWN 18
  34. #define IEM_EVENT_REPLAY_SPECIAL_VK 21
  35. #define IEM_EVENT_EXTENDED_KEY 22
  36. #define IEM_EVENT_REPLAY_SECONDARY 23
  37. #define IEM_EVENT_SYSTEM 24
  38. #define IEM_EVENT_NORMAL 25
  39. #define IEM_EVENT_HOTKEY_BASE 50
  40. //
  41. // Range of hotkeys is 0 - 99
  42. //
  43. #define IEM_EVENT_KEYPAD0_DOWN 150
  44. //
  45. // Range of keypad down is 0-9
  46. //
  47. #define IEM_EVENT_KEYPAD0_UP 160
  48. //
  49. // The flags used in the return value from VkKeyScan.
  50. //
  51. #define IEM_SHIFT_DOWN 0x0001
  52. #define IEM_CTRL_DOWN 0x0002
  53. #define IEM_MENU_DOWN 0x0004
  54. //
  55. // Virtual key codes.
  56. //
  57. #define VK_INVALID 0xFF
  58. //
  59. // Given the keyboard packet flags the following macros tell us things
  60. // about the key event.
  61. //
  62. //
  63. // This is TRUE if this event is a key press. It is FALSE for key releases
  64. // and key repeats.
  65. //
  66. #define IS_IM_KEY_PRESS(A) \
  67. (((A) & (TSHR_UINT16)(IM_FLAG_KEYBOARD_RELEASE | IM_FLAG_KEYBOARD_DOWN))==0)
  68. //
  69. // This is TRUE if this event is a key release. It is FALSE for key
  70. // presses and key repeats. Note that it is also TRUE for the
  71. // theoretically impossible case of a key release when the key is already
  72. // up (this combination could conceviably be generated if events are
  73. // discarded by USER or our emulation of USER).
  74. //
  75. #define IS_IM_KEY_RELEASE(A) (((A) & IM_FLAG_KEYBOARD_RELEASE))
  76. //
  77. // This is TRUE if this event is a key repeat. It is FALSE for key presses
  78. // and key releases.
  79. //
  80. #define IS_IM_KEY_REPEAT(A) \
  81. (((A) & (IM_FLAG_KEYBOARD_RELEASE | IM_FLAG_KEYBOARD_DOWN))==\
  82. IM_FLAG_KEYBOARD_DOWN)
  83. //
  84. // This is TRUE if the key is the right-variant of a modifier. It is FALSE
  85. // otherwise.
  86. //
  87. #define IS_IM_KEY_RIGHT(A) (((A) & IM_FLAG_KEYBOARD_RIGHT))
  88. //
  89. // The maximum amount of time that we expect an injected event to take to
  90. // pass through USER.
  91. //
  92. #define IM_EVENT_PERCOLATE_TIME 300
  93. //
  94. // Max VK sync attempts.
  95. //
  96. #define IM_MAX_VK_SYNC_ATTEMPTS 10
  97. //
  98. // Declare our function prototype for <ImmGetVirtualKey>.
  99. //
  100. typedef UINT (WINAPI* IMMGVK)(HWND);
  101. //
  102. //
  103. // MACROS
  104. //
  105. //
  106. //
  107. // Macros to convert between logical mouse co-ordinates (e.g. (320,240) for
  108. // the centre of a VGA screen to the full 16-bit range co-ordinates used
  109. // by Windows (e.g. (320,240) is (32767, 32767).
  110. //
  111. #define IM_MOUSEPOS_LOG_TO_OS(coord, size) \
  112. (((65535L * (TSHR_UINT32)coord) + 32768L) / (TSHR_UINT32)size)
  113. //
  114. // Macros extracting information from the mouse event flags field (event
  115. // mask).
  116. //
  117. #define IM_MEV_MOVE_ONLY(e) ((e).event.mouse.flags == MOUSEEVENTF_MOVE)
  118. #define IM_MEV_MOVE(e) (((e).event.mouse.flags & MOUSEEVENTF_MOVE) != 0 )
  119. #define IM_MEV_ABS_MOVE(e) (((e).event.mouse.flags & \
  120. (MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE) == \
  121. (MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE) ))
  122. #define IM_MEV_BUTTON_DOWN(e) \
  123. (((e).event.mouse.flags & IM_MOUSEEVENTF_BUTTONDOWN_FLAGS) != 0 )
  124. #define IM_MEV_BUTTON_UP(e) \
  125. (((e).event.mouse.flags & IM_MOUSEEVENTF_BUTTONUP_FLAGS) != 0 )
  126. #define IM_EVMASK_B1_DOWN(m) (((m) & MOUSEEVENTF_LEFTDOWN) != 0 )
  127. #define IM_EVMASK_B1_UP(m) (((m) & MOUSEEVENTF_LEFTUP) != 0 )
  128. #define IM_EVMASK_B2_DOWN(m) (((m) & MOUSEEVENTF_RIGHTDOWN) != 0 )
  129. #define IM_EVMASK_B2_UP(m) (((m) & MOUSEEVENTF_RIGHTUP) != 0 )
  130. #define IM_EVMASK_B3_DOWN(m) (((m) & MOUSEEVENTF_MIDDLEDOWN) != 0 )
  131. #define IM_EVMASK_B3_UP(m) (((m) & MOUSEEVENTF_MIDDLEUP) != 0 )
  132. #define IM_MEV_BUTTON1_DOWN(e) (IM_EVMASK_B1_DOWN((e).event.mouse.flags))
  133. #define IM_MEV_BUTTON2_DOWN(e) (IM_EVMASK_B2_DOWN((e).event.mouse.flags))
  134. #define IM_MEV_BUTTON3_DOWN(e) (IM_EVMASK_B3_DOWN((e).event.mouse.flags))
  135. #define IM_MEV_BUTTON1_UP(e) (IM_EVMASK_B1_UP((e).event.mouse.flags))
  136. #define IM_MEV_BUTTON2_UP(e) (IM_EVMASK_B2_UP((e).event.mouse.flags))
  137. #define IM_MEV_BUTTON3_UP(e) (IM_EVMASK_B3_UP((e).event.mouse.flags))
  138. #define IM_KEV_KEYUP(e) ((e).event.keyboard.flags & KEYEVENTF_KEYUP)
  139. #define IM_KEV_KEYDOWN(e) (!IM_KEV_KEYUP(e))
  140. #define IM_KEV_VKCODE(e) ((e).event.keyboard.vkCode)
  141. #define IM_MOUSEEVENTF_BASE_FLAGS ( MOUSEEVENTF_MOVE | \
  142. MOUSEEVENTF_LEFTUP | \
  143. MOUSEEVENTF_LEFTDOWN | \
  144. MOUSEEVENTF_RIGHTUP | \
  145. MOUSEEVENTF_RIGHTDOWN | \
  146. MOUSEEVENTF_MIDDLEUP | \
  147. MOUSEEVENTF_MIDDLEDOWN )
  148. #define IM_MOUSEEVENTF_CLICK_FLAGS ( MOUSEEVENTF_LEFTUP | \
  149. MOUSEEVENTF_LEFTDOWN | \
  150. MOUSEEVENTF_RIGHTUP | \
  151. MOUSEEVENTF_RIGHTDOWN | \
  152. MOUSEEVENTF_MIDDLEUP | \
  153. MOUSEEVENTF_MIDDLEDOWN )
  154. #define IM_MOUSEEVENTF_BUTTONDOWN_FLAGS ( MOUSEEVENTF_LEFTDOWN | \
  155. MOUSEEVENTF_RIGHTDOWN | \
  156. MOUSEEVENTF_MIDDLEDOWN )
  157. #define IM_MOUSEEVENTF_BUTTONUP_FLAGS ( MOUSEEVENTF_LEFTUP | \
  158. MOUSEEVENTF_RIGHTUP | \
  159. MOUSEEVENTF_MIDDLEUP )
  160. typedef struct tagKBDEV
  161. {
  162. WORD vkCode;
  163. WORD scanCode;
  164. DWORD flags;
  165. DWORD time;
  166. DWORD dwExtraInfo;
  167. }
  168. KBDEV, FAR *LPKBDEV;
  169. typedef struct tagMSEV
  170. {
  171. POINTL pt;
  172. DWORD cButtons;
  173. DWORD mouseData;
  174. DWORD flags;
  175. DWORD time;
  176. DWORD dwExtraInfo;
  177. }
  178. MSEV, FAR *LPMSEV;
  179. //
  180. // The IMOSEVENTS which we queue as they arrive from the mouse or
  181. // keyboard hooks or after IMINCOMINGEVENTS have been translated into local
  182. // events by the IEM.
  183. //
  184. typedef struct tagIMOSEVENT
  185. {
  186. TSHR_UINT32 type;
  187. #define IM_MOUSE_EVENT 1
  188. #define IM_KEYBOARD_EVENT 2
  189. TSHR_UINT32 flags;
  190. #define IM_FLAG_DONT_REPLAY 0x0001
  191. #define IM_FLAG_UPDATESTATE 0x0002
  192. TSHR_UINT32 time;
  193. union
  194. {
  195. MSEV mouse;
  196. KBDEV keyboard;
  197. }
  198. event;
  199. }
  200. IMOSEVENT;
  201. typedef IMOSEVENT FAR * LPIMOSEVENT;
  202. #define IM_TRANSFER_EVENT_BUFFER_SIZE 32
  203. #define IM_MAX_TRANSFER_EVENT_INDEX (IM_TRANSFER_EVENT_BUFFER_SIZE-1)
  204. typedef struct tagIMTRANSFEREVENT
  205. {
  206. LONG fInUse;
  207. IMOSEVENT event;
  208. }
  209. IMTRANSFEREVENT, FAR * LPIMTRANSFEREVENT;
  210. //
  211. // For handling keyboard events in hooks
  212. //
  213. #define IM_MASK_KEYBOARD_SYSFLAGS 0xE100
  214. #define IM_MASK_KEYBOARD_SYSSCANCODE 0x00FF
  215. #define IM_MAX_DEAD_KEYS 20
  216. #define IM_SIZE_EVENTQ 40
  217. #define IM_SIZE_OSQ 80 // 2*EVENTQ size - key up/down
  218. //
  219. // Define the flags that can be returned by IMConvertIMPacketToOSEvent().
  220. //
  221. #define IM_IMQUEUEREMOVE 0x0001
  222. #define IM_OSQUEUEINJECT 0x0002
  223. //
  224. // For managing our key state arrays.
  225. //
  226. #define IM_KEY_STATE_FLAG_TOGGLE (BYTE)0x01
  227. #define IM_KEY_STATE_FLAG_DOWN (BYTE)0x80
  228. //
  229. // Bounds for local mouse spoiling and packet piggyback target withhold
  230. // Note that these are local spoiling values, to prevent the data pipe from
  231. // getting clogged and introducing unnecessary latency. Now, you may think
  232. // that 30 move messages per second is a little low, but put this up any
  233. // higher and USER at the other end will just spoil them when it injects
  234. // them into the app - that would be totally wasteful of precious bandwidth.
  235. //
  236. #define IM_LOCAL_MOUSE_SAMPLING_GAP_LOW_MS 100
  237. #define IM_LOCAL_MOUSE_SAMPLING_GAP_MEDIUM_MS 75
  238. #define IM_LOCAL_MOUSE_SAMPLING_GAP_HIGH_MS 50
  239. #define IM_LOCAL_WITHHOLD_DELAY 150
  240. #define IM_LOCAL_MOUSE_WITHHOLD 5
  241. #define IM_LOCAL_KEYBOARD_WITHHOLD 2
  242. //
  243. // For pacing the accumulation and injecting of mouse events.
  244. // We should play back at the same rate as the highest local sampling rate
  245. // less a small amount for processing delay on the remote system
  246. //
  247. #define IM_REMOTE_MOUSE_PLAYBACK_GAP_MS 20
  248. //
  249. // The amount of time to hold on to a mouse button down event in case a the
  250. // user is just clicking on eg a scroll button. If we did not hold on to
  251. // the mouse button down event then the mouse button up would be sent in
  252. // the next packet. On a slow network this means the remote application
  253. // may process the down period for much longer than the user wanted.
  254. //
  255. #define IM_MOUSE_UP_WAIT_TIME 50
  256. #define IM_MIN_RECONVERSION_INTERVAL_MS 150
  257. //
  258. // #define used non-Windows to flag a VK code that equates to an ascii char
  259. //
  260. #define IM_TYPE_VK_ASCII ((TSHR_UINT16)0x8880)
  261. //
  262. // Used for checking events about to be injected.
  263. //
  264. #define IM_KEY_IS_TOGGLE(A) \
  265. (((A)==VK_CAPITAL)||((A)==VK_SCROLL)||((A)==VK_NUMLOCK))
  266. #define IM_KEY_IS_MODIFIER(A) \
  267. (((A)==VK_SHIFT)||((A)==VK_CONTROL)||((A)==VK_MENU))
  268. //
  269. // Used to check values in key state arrays.
  270. //
  271. #define IM_KEY_STATE_IS_UP(A) (!((A)&IM_KEY_STATE_FLAG_DOWN))
  272. #define IM_KEY_STATE_IS_DOWN(A) ((A)&IM_KEY_STATE_FLAG_DOWN)
  273. //
  274. // Used to determine what sort of mouse event this is from the flags.
  275. //
  276. #define IM_IS_MOUSE_MOVE(A) \
  277. ((A) & IM_FLAG_MOUSE_MOVE)
  278. #define IM_IS_MOUSE_PRESS(A) \
  279. ((!IM_IS_MOUSE_MOVE(A)) && ((A) & IM_FLAG_MOUSE_DOWN))
  280. #define IM_IS_MOUSE_RELEASE(A) \
  281. ((!IM_IS_MOUSE_MOVE(A)) && !((A) & IM_FLAG_MOUSE_DOWN))
  282. #define IM_IS_LEFT_CLICK(A) \
  283. (((A) & (IM_FLAG_MOUSE_DOWN | IM_FLAG_MOUSE_BUTTON1 | IM_FLAG_MOUSE_DOUBLE)) == (IM_FLAG_MOUSE_DOWN | IM_FLAG_MOUSE_BUTTON1))
  284. #define IM_IS_LEFT_DCLICK(A) \
  285. (((A) & (IM_FLAG_MOUSE_DOWN | IM_FLAG_MOUSE_BUTTON1 | IM_FLAG_MOUSE_DOUBLE)) == (IM_FLAG_MOUSE_DOWN | IM_FLAG_MOUSE_BUTTON1 | IM_FLAG_MOUSE_DOUBLE))
  286. //
  287. // Holds NETWORK events, to person controlled by us, or from person in control
  288. // of us.
  289. //
  290. typedef struct tagIMEVENTQ
  291. {
  292. DWORD head;
  293. DWORD numEvents;
  294. IMEVENT events[IM_SIZE_EVENTQ];
  295. }
  296. IMEVENTQ;
  297. typedef IMEVENTQ FAR * LPIMEVENTQ;
  298. //
  299. // Holds translated events, suitable for injection from person
  300. // in control of us, or pre-translated events to person controlled by us.
  301. //
  302. typedef struct tagIMOSQ
  303. {
  304. DWORD head;
  305. DWORD numEvents;
  306. IMOSEVENT events[IM_SIZE_OSQ];
  307. }
  308. IMOSQ;
  309. typedef IMOSQ FAR * LPIMOSQ;
  310. #define CIRCULAR_INDEX(start, rel_index, size) \
  311. (((start) + (rel_index)) % (size))
  312. //
  313. // To support collaboration in both NT (background service thread) and Win95
  314. // (win16 code) with as much of the common incoming/outgoing processing in
  315. // one places, the IM data is separated into 4 types. There are structures
  316. // for each of these types, so that moving a variable from one to another
  317. // is as easy as possible. Note that the declarations are bitness-safe;
  318. // they are the same size in 16-bit and 32-bit code. And that the structures
  319. // are DWORD aligned.
  320. //
  321. // (1) IM_SHARED_DATA
  322. // This is data that both the CPI32 library needs to access, and one or
  323. // more of the NT/Win95 implementations of collaboration.
  324. //
  325. // (2) IM_NT_DATA
  326. // This is data that only the NT version of collaboration needs.
  327. //
  328. // (3) IM_WIN95_DATA
  329. // This is data that only the Win95 version of collaboration needs.
  330. //
  331. //
  332. // For NT, this shared structures is just declared in MNMCPI32.NT's data,
  333. // and a pointer to it is used by the common lib.
  334. //
  335. // For Win95, this shared structure is allocated in a global memory block
  336. // that can GlobalSmartPageLock() it as needed for access at interrupt time,
  337. // and a pointer to it is mapped flat and returned to the common lib.
  338. //
  339. typedef struct tagIM_SHARED_DATA
  340. {
  341. #ifdef DEBUG
  342. DWORD cbSize; // To make sure everybody agrees on size
  343. #endif
  344. //
  345. // For critical errors -- nonzero if one is up
  346. //
  347. DWORD imSuspended;
  348. //
  349. // Control state
  350. //
  351. LONG imControlled;
  352. LONG imPaused;
  353. LONG imUnattended;
  354. }
  355. IM_SHARED_DATA, FAR* LPIM_SHARED_DATA;
  356. // NT specific IM state variables
  357. typedef struct tagIM_NT_DATA
  358. {
  359. //
  360. // Low level hook thread
  361. //
  362. DWORD imLowLevelInputThread;
  363. //
  364. // Other desktop injection helper thread
  365. //
  366. DWORD imOtherDesktopThread;
  367. //
  368. // Low level hook handles
  369. //
  370. HHOOK imhLowLevelMouseHook;
  371. HHOOK imhLowLevelKeyboardHook;
  372. }
  373. IM_NT_DATA, FAR* LPIM_NT_DATA;
  374. // Win95 specific IM state variables
  375. typedef struct tagIM_WIN95_DATA
  376. {
  377. BOOL imInjecting;
  378. BOOL imLowLevelHooks;
  379. //
  380. // High level hook handles
  381. //
  382. HHOOK imhHighLevelMouseHook;
  383. }
  384. IM_WIN95_DATA, FAR* LPIM_WIN95_DATA;
  385. //
  386. //
  387. // MACROS
  388. //
  389. //
  390. #define IM_SET_VK_DOWN(A) (A) |= (BYTE)0x80
  391. #define IM_SET_VK_UP(A) (A) &= (BYTE)0x7F
  392. #define IM_TOGGLE_VK(A) (A) ^= (BYTE)0x01
  393. //
  394. //
  395. // PROTOTYPES
  396. //
  397. //
  398. // NT only
  399. BOOL WINAPI OSI_InstallHighLevelMouseHook(BOOL fOn);
  400. BOOL WINAPI OSI_InstallControlledHooks(BOOL fOn);
  401. void WINAPI OSI_InjectMouseEvent(DWORD flags, LONG x, LONG y, DWORD mouseData, DWORD dwExtraInfo);
  402. void WINAPI OSI_InjectKeyboardEvent(DWORD flags, WORD vkCode, WORD scanCode, DWORD dwExtraInfo);
  403. void WINAPI OSI_InjectCtrlAltDel(void);
  404. void WINAPI OSI_DesktopSwitch(UINT from, UINT to);
  405. //
  406. // Internal Hook DLL functions.
  407. //
  408. #ifdef DLL_HOOK
  409. #ifdef IS_16
  410. BOOL IM_DDInit(void);
  411. void IM_DDTerm(void);
  412. #endif // IS_16
  413. LRESULT CALLBACK IMMouseHookProc(int code,
  414. WPARAM wParam,
  415. LPARAM lParam);
  416. #endif // DLL_HOOK
  417. #ifdef IS_16
  418. void IMCheckWin16LockPulse(void);
  419. #else
  420. DWORD WINAPI IMLowLevelInputProcessor(LPVOID hEventWait);
  421. DWORD WINAPI IMOtherDesktopProc(LPVOID hEventWait);
  422. LRESULT CALLBACK IMLowLevelMouseProc(int, WPARAM, LPARAM);
  423. LRESULT CALLBACK IMLowLevelKeyboardProc(int, WPARAM, LPARAM);
  424. #endif // IS_16
  425. #endif // DLL_CORE or DLL_HOOK
  426. #endif // _H_IM