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.

492 lines
10 KiB

  1. ;
  2. ; UT.ASM
  3. ; Tracing goop, debug only
  4. ; Mouse/Keyboard event interrupt junk, all flavors
  5. ;
  6. .386
  7. option oldstructs
  8. option readonly
  9. option segment:use16
  10. .model large,pascal
  11. ifdef DEBUG
  12. externDef _wsprintf:far16
  13. externDef OutputDebugString:far16
  14. externDef DebugBreak:far16
  15. endif ; DEBUG
  16. externDef DrvMouseEvent:far16
  17. externDef DrvKeyboardEvent:far16
  18. externDef mouse_event:far16
  19. externDef keybd_event:far16
  20. externDef MaphinstLS:far16
  21. .data
  22. ifdef DEBUG
  23. externDef g_szDbgBuf:word
  24. externDef g_szNewline:word
  25. externDef g_dbgRet:word
  26. externDef g_trcConfig:word
  27. endif ; DEBUG
  28. if 0
  29. ; DOS key redirection
  30. externDef g_imDOSShellVDDEntry:dword
  31. externDef g_imDOSVKDEntry:dword
  32. endif
  33. .code _TEXT
  34. ifdef DEBUG
  35. ;
  36. ; We come in here with _cdecl var args. We use DebugOutput() to spit out
  37. ; the message. Then we do the debugbreak ourself.
  38. ;
  39. _DbgZPrintWarning proc near
  40. ; Save IP of caller. What's left on stack is var args
  41. pop [g_dbgRet] ; Save IP of output caller
  42. ; Push g_szDbgBuf to put result into.
  43. push ds
  44. push offset g_szDbgBuf
  45. ; We now have _cdecl args to wsprintf
  46. call _wsprintf
  47. ;
  48. ; The same args are left on the stack, since wsprintf is _cdecl. The
  49. ; first is g_szDbgBuf. So we can convienently pass this to OutputDebugString().
  50. ; That routine is NOT _cdecl, so when it returns, we have exactly the
  51. ; same args that were passed in to us.
  52. ;
  53. call OutputDebugString
  54. ; Now output a new line
  55. push ds
  56. push offset g_szNewline
  57. call OutputDebugString
  58. ; Now we just need to do a near RET to the caller
  59. push [g_dbgRet]
  60. ret
  61. _DbgZPrintWarning endp
  62. ;
  63. ; We come in here with _cdecl var args
  64. ;
  65. _DbgZPrintTrace proc near
  66. ; Is tracing on?
  67. test [g_trcConfig], 0001h
  68. jnz _DbgZPrintWarning
  69. ret
  70. _DbgZPrintTrace endp
  71. _DbgZPrintError proc near
  72. ; Save IP of caller. What's left on stack is var args
  73. pop [g_dbgRet] ; Save IP of output caller
  74. ; Push g_szDbgBuf to put result into.
  75. push ds
  76. push offset g_szDbgBuf
  77. ; We now have _cdecl args to wsprintf
  78. call _wsprintf
  79. ;
  80. ; The same args are left on the stack, since wsprintf is _cdecl. The
  81. ; first is g_szDbgBuf. So we can convienently pass this to OutputDebugString().
  82. ; That routine is NOT _cdecl, so when it returns, we have exactly the
  83. ; same args that were passed in to us.
  84. ;
  85. call OutputDebugString
  86. ; Now output a new line
  87. push ds
  88. push offset g_szNewline
  89. call OutputDebugString
  90. ; Break into the debugger
  91. call DebugBreak
  92. ; Now we just need to do a near RET to the caller
  93. push [g_dbgRet]
  94. ret
  95. _DbgZprintError endp
  96. endif
  97. ;
  98. ; ASMMouseEvent()
  99. ; This passes the registers as parameters to a C function, DrvMouseEvent.
  100. ; It is basically the inverse of CallMouseEvent().
  101. ;
  102. ; NOTE:
  103. ; To be on the safe side, we preserve all registers just like keybd_event().
  104. ; USER trashes some registers, but it would not come as a surprise to find
  105. ; mouse drivers that expect incorrectly a register or two to not be
  106. ; altered.
  107. ;
  108. ASMMouseEvent proc far
  109. ; Save registers that C code doesn't preserve
  110. push eax
  111. push ebx
  112. push ecx
  113. push edx
  114. ; Save original flags for turning ints off/on
  115. pushf
  116. ; Push AX for DrvMouseEvent() call
  117. push ax
  118. ; Do we need to turn interrupts off? We don't if they are already
  119. pushf
  120. pop ax
  121. test ax, 0200h
  122. jz SkipCli
  123. cli
  124. SkipCli:
  125. ; AX has already been pushed; push the rest of the parameters
  126. push bx
  127. push cx
  128. push dx
  129. push si
  130. push di
  131. cld
  132. call DrvMouseEvent
  133. ; If interrupts were not disabled before, enable them now.
  134. pop cx ; saved flags
  135. pushf
  136. pop ax ; current flags
  137. ; Find out what is different
  138. xor ax, cx
  139. test ax, 0200h
  140. jz InterruptsOk
  141. ; The interrupt flag needs to be changed, do it
  142. test cx, 0200h
  143. jnz EnableInterrupts
  144. cli
  145. jmp InterruptsOk
  146. EnableInterrupts:
  147. sti
  148. InterruptsOk:
  149. ; Does the direction flag need to be changed?
  150. test ax, 0400h
  151. jz DirectionOk
  152. ; The direction flag needs to be changed, do it
  153. test cx, 0400h
  154. jnz SetDirectionFlag
  155. cld
  156. jmp DirectionOk
  157. SetDirectionFlag:
  158. std
  159. DirectionOk:
  160. ; Restore registers
  161. pop edx
  162. pop ecx
  163. pop ebx
  164. pop eax
  165. retf
  166. ASMMouseEvent endp
  167. ;
  168. ; CallMouseEvent()
  169. ; This puts the parameters into registers and calls the original mouse_event.
  170. ;
  171. ; There are two ways we can call this function:
  172. ; (1) Injection code is piping mouse events through USER. It is
  173. ; responsible for disabling/enabling interrupts before calling us.
  174. ; (2) mouse_event patch is calling through to USER.
  175. ;
  176. CallMouseEvent proc near
  177. ;
  178. ; This is the stack, BP relative:
  179. ; WORD bpSave
  180. ; WORD near_ret
  181. ; WORD regDI
  182. ; WORD regSI
  183. ; WORD regDX
  184. ; WORD regCX
  185. ; WORD regBX
  186. ; WORD regAX
  187. ;
  188. ; We must preserve SI and DI
  189. ;
  190. push bp
  191. mov bp, sp
  192. push si
  193. push di
  194. mov di, word ptr ss:[bp+4]
  195. mov si, word ptr ss:[bp+6]
  196. mov dx, word ptr ss:[bp+8]
  197. mov cx, word ptr ss:[bp+10]
  198. mov bx, word ptr ss:[bp+12]
  199. mov ax, word ptr ss:[bp+14]
  200. call mouse_event
  201. pop di
  202. pop si
  203. mov sp, bp
  204. pop bp
  205. ret 6*2
  206. CallMouseEvent endp
  207. ;
  208. ; ASMKeyboardEvent()
  209. ; This passes the registers as parameters to a C function, DrvKeyboardEvent.
  210. ; It is basically the inverse of CallKeyboardEvent().
  211. ;
  212. ; NOTE:
  213. ; keybd_event() MUST preserve all registers, unlike mouse_event().
  214. ;
  215. ASMKeyboardEvent proc far
  216. ; Save flags and registers that aren't preserved in C code
  217. push eax
  218. push ebx
  219. push ecx
  220. push edx
  221. pushf
  222. ; Push AX for DrvKeyboardEvent() call
  223. push ax
  224. ; Check if interrupts off, w/o trashing CX permanently
  225. pushf
  226. pop ax
  227. test ax, 0200h
  228. jz SkipCli
  229. cli
  230. SkipCli:
  231. ; AX has already been pushed; push the rest of the parameters
  232. push bx
  233. push si
  234. push di
  235. cld
  236. call DrvKeyboardEvent
  237. ;
  238. ; Restore the interrupt and string move direction flags to what they
  239. ; were before.
  240. ;
  241. pop cx ; Original flags
  242. pushf
  243. pop ax ; Current flags
  244. ; What has changed?
  245. xor ax, cx
  246. ; Has the interrupt state been altered?
  247. test ax, 0200h
  248. jz InterruptsOk
  249. ; Interrupts need to be turned on/off
  250. test cx, 0200h
  251. jnz EnableInterrupts
  252. cli
  253. jmp InterruptsOk
  254. EnableInterrupts:
  255. sti
  256. InterruptsOk:
  257. ; Has the direction flag been altered?
  258. test ax, 0400h
  259. jz DirectionOk
  260. ; Direction flag needs to be set/cleared
  261. test cx, 0400h
  262. jnz SetDirection
  263. cld
  264. jmp DirectionOk
  265. SetDirection:
  266. std
  267. DirectionOk:
  268. ; Restore registers
  269. pop edx
  270. pop ecx
  271. pop ebx
  272. pop eax
  273. retf
  274. ASMKeyboardEvent endp
  275. ;
  276. ; CallKeyboardEvent()
  277. ; This puts the parameters in registers and calls USER's keybd_event.
  278. ;
  279. ; There are two ways we can call this function:
  280. ; (1) Injection code is piping keybd events through USER. It is
  281. ; responsible for disabling/enabling interrupts before calling us.
  282. ; (2) keybd_event patch is calling through to USER.
  283. ;
  284. CallKeyboardEvent proc near
  285. ;
  286. ; This is the stack, BP relative:
  287. ; WORD bpSave
  288. ; WORD near_ret
  289. ; WORD regDI
  290. ; WORD regSI
  291. ; WORD regBX
  292. ; WORD regAX
  293. ;
  294. ; We must preserve SI and DI
  295. ;
  296. push bp
  297. mov bp, sp
  298. push si
  299. push di
  300. mov di, word ptr ss:[bp+4]
  301. mov si, word ptr ss:[bp+6]
  302. mov bx, word ptr ss:[bp+8]
  303. mov ax, word ptr ss:[bp+10]
  304. call keybd_event
  305. pop di
  306. pop si
  307. mov sp, bp
  308. pop bp
  309. ret 4*2
  310. CallKeyboardEvent endp
  311. ;
  312. ; This is our wrapper around krnl386's MaphinstLS() routine, which expects
  313. ; the 32-bit instance handle in EAX
  314. ;
  315. MapInstance32 proc far
  316. ; Pop far return, pop 32-bit instance into eax, and replace far return
  317. pop edx
  318. pop eax
  319. push edx
  320. ; Call krnl386 -- when MaphinstLS returns, it will return to our caller
  321. jmp MaphinstLS
  322. MapInstance32 endp
  323. if 0
  324. ;
  325. ; DOS box key injection gunk. We use the shell vdd service.
  326. ;
  327. IMGetDOSShellVDDEntry proc near
  328. ; Save DI, int2f will trash it
  329. push di
  330. ; int2f 0x1684, vdd 0x0017 (shell) gets the service entry point
  331. ; It is returned in es:di
  332. mov ax, 1684h
  333. mov bx, 017h
  334. int 2F
  335. ; Save the address (even if null)
  336. mov word ptr ds:[g_imDOSShellVDDEntry], di
  337. mov word ptr ds:[g_imDOSShellVDDEntry+2], es
  338. pop di
  339. ret
  340. IMGetDOSShellVDDEntry endp
  341. IMGetDOSVKDEntry proc near
  342. ; Save DI, int2f will trash it
  343. push di
  344. ; int2f 0x1684, vkd 0x000d (vkd) gets the service entry point
  345. ; It is returned in es:di
  346. mov ax, 1684h
  347. mov bx, 00dh
  348. int 2Fh
  349. mov word ptr ds:[g_imDOSVKDEntry], di
  350. mov word ptr ds:[g_imDOSVKDEntry+1], es
  351. pop di
  352. ret
  353. IMGetDOSVKDEntry endp
  354. IMForceDOSKey proc near
  355. ; ss:[sp] is near ret
  356. ; ss:[sp+2] is scanCode
  357. ; ss:[sp+4] is keyState
  358. push bp
  359. mov bp, sp
  360. ; Preserve extended registers
  361. push ebx
  362. push ecx
  363. push edx
  364. ; Setup for VKD call
  365. mov eax, 1 ; Service 1, stuff key
  366. xor ebx, ebx ; VM 0, current VM
  367. movzx ecx, word ptr ss:[bp+4]
  368. shl ecx, 8 ; Scan code in high byte
  369. or ecx, 1 ; Repeat count in low byte
  370. movzx edx, word ptr ss:[bp+6] ; Shift state
  371. call dword ptr ds:[g_imDOSVKDEntry]
  372. mov ax, 0
  373. ; Failure?
  374. jc DoneForceKey
  375. ; Success!
  376. inc ax
  377. DoneForceKey:
  378. pop edx
  379. pop ecx
  380. pop ebx
  381. mov sp, bp
  382. pop bp
  383. ret 2+2
  384. IMForceDOSKey endp
  385. endif ; if 0 for DOS key redirection
  386. end