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.

954 lines
24 KiB

  1. title "Fast Protected Mode services"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; fastwow.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements a fast mechanism for WOW apps to go back
  13. ; and forth from app code (protected mode, 16-bit segmented) to
  14. ; WOW32.DLL (flat).
  15. ;
  16. ;
  17. ; Author:
  18. ;
  19. ; Bob Day (bobday) 07-29-92
  20. ; copied from FASTPM.ASM written by Dave Hastings (daveh) 26-Jul-91
  21. ;
  22. ; barryb 11-nov-92 added fast callback mechanism, pared
  23. ; WOWBopEntry to the bare essentials (hopefully)
  24. ;
  25. ;
  26. ; rules of thumb:
  27. ; - monitor context gets saved on monitor stack on entry to
  28. ; FastWOWCallbackCall and restored on the way out of FastWOWCallbackRet
  29. ; - no need to save any VDM general registers - krnl286 uses the
  30. ; WOW16Call stack frame for this
  31. ; - you can't save anything on the 16-bit stack because the stack
  32. ; gets tinkered with by DispatchInterrupts
  33. ;
  34. ; WARNING WARNING WARNING WARNING WARNING WARNING WARNING
  35. ; these routines are optimized for the straight-through case, no
  36. ; interrupt being dispatched, so there's duplicate code in the
  37. ; routines. if you add stuff, be sure to add it to both paths.
  38. ; WARNING WARNING WARNING WARNING WARNING WARNING WARNING
  39. ;
  40. ; sudeepb 09-Dec-1992
  41. ; Changed all the refernces to virtual interrupt flag in the VDMTIB
  42. ; to fixed DOS location.
  43. ;--
  44. .386p
  45. include ks386.inc
  46. include bop.inc
  47. include wowtd.inc
  48. if DBG
  49. DEBUG equ 1
  50. endif
  51. ifdef DEBUG
  52. DEBUG_OR_WOWPROFILE equ 1
  53. endif
  54. ifdef WOWPROFILE
  55. DEBUG_OR_WOWPROFILE equ 1
  56. endif
  57. include wow.inc
  58. include callconv.inc
  59. include vint.inc
  60. include vdmtib.inc
  61. EXTRN __imp__CurrentMonitorTeb:DWORD
  62. EXTRN __imp__FlatAddress:DWORD
  63. _TEXT SEGMENT PARA PUBLIC 'CODE'
  64. ASSUME DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
  65. EXTRNP _DispatchInterrupts,0
  66. EXTRNP @W32PatchCodeWithLpfnw32, 2
  67. EXTRNP @InterpretThunk, 2
  68. EXTRNP _Ssync_WOW_CommDlg_Structs, 3
  69. ifdef DEBUG
  70. EXTRNP _logargs,2
  71. EXTRNP _logreturn,3
  72. endif
  73. _TEXT ENDS
  74. _DATA SEGMENT DWORD PUBLIC 'DATA'
  75. extrn _aw32WOW:Dword
  76. public _WowpLockPrefixTable
  77. _WowpLockPrefixTable label dword
  78. dd offset FLAT:_wowlock1
  79. dd offset FLAT:_wowlock2
  80. dd offset FLAT:_wowlock3
  81. dd offset FLAT:_wowlock4
  82. dd offset FLAT:_wowlock5
  83. dd offset FLAT:_wowlock6
  84. dd 0
  85. Stack16 LABEL DWORD
  86. _savesp16 DW 0
  87. _savess16 DW 0
  88. _saveip16 DD 0
  89. _savecs16 DD 0
  90. _saveebp32 DD 0
  91. _saveeax DD 0
  92. _saveebx DD 0
  93. _saveecx DD 0
  94. _saveedx DD 0
  95. _fKernelCSIPFixed DB 0
  96. _DATA ENDS
  97. public _saveeax
  98. public _saveebx
  99. public _saveecx
  100. public _saveedx
  101. public _savesp16
  102. public _savess16
  103. public _savecs16
  104. public _saveip16
  105. public _saveebp32
  106. public _fKernelCSIPFixed
  107. public Stack16
  108. ;
  109. ; The variable fKernelCSIPFixed is used so the fastbop/callback mechanism
  110. ; knows when it no longer needs to pop the 16-bit return address off the
  111. ; 16-bit stack on entry to WOWBopEntry and FastWOWCallbackRet because kernel
  112. ; has booted and the address won't be changing.
  113. ;
  114. ;
  115. ; The assumption is that we're always coming from the same place in kernel.
  116. ; It also saves a jmp when returning to kernel.
  117. ;
  118. _TEXT SEGMENT
  119. page ,132
  120. subttl "WOWBopEntry"
  121. ;++
  122. ;
  123. ; Routine Description:
  124. ;
  125. ; This routine switches from the VDM context to the monitor context.
  126. ; Then executes the appropriate WOW api call.
  127. ; Then returns back to the VDM context.
  128. ;
  129. ; Arguments:
  130. ;
  131. ; none
  132. ;
  133. ; Returns:
  134. ;
  135. ; puts result of WOW api call (EAX) into pFrame->wDX, pFrame->wAX
  136. ;
  137. ; [LATER] add a field to the frame and set it to !0 if a task switch
  138. ; has occurred. kernel can read this off the stack instead
  139. ; of having to load the kernelDS to look at wCurTDB
  140. ;
  141. assume DS:Nothing,ES:Nothing,SS:Nothing
  142. ALIGN 16
  143. cPublicProc _WOWBopEntry,0
  144. mov bx,KGDT_R3_DATA OR RPL_MASK ; Move back to Flat DS
  145. mov ds,bx ; so push and pop size same
  146. assume ds:_DATA
  147. mov _saveeax,eax ; Multi Media Apps call api's
  148. mov _saveebx,ebx ; at interrupt time which trash
  149. mov _saveecx,ecx ; the high parts of the 32 bit
  150. mov _saveedx,edx ; registers. [LATER] this
  151. ; should be moved to fame
  152. pushfd ; Save them flags
  153. ; we make here the assumption that the c compiler always keeps the
  154. ; direction flag clear. We clear it here instead of restoring it
  155. ; from the context for performance
  156. cld
  157. mov eax,KGDT_R3_TEB OR RPL_MASK ; restore flat FS
  158. mov fs,ax
  159. mov ebx, dword ptr fs:[PcTeb]
  160. mov ebx, dword ptr [ebx].TeVdm ; get pointer to contexts
  161. ;
  162. ; start saving some of the 16-bit context
  163. ;
  164. ; Interrupts are always enabled in WOW, but if we are trying
  165. ; to simulate the fact that they are disabled, we need to
  166. ; turn them off in the structure.
  167. pop eax
  168. mov edx,dword ptr ds:FIXED_NTVDMSTATE_LINEAR ; Get simulated bits
  169. or edx,NOT VDM_VIRTUAL_INTERRUPTS
  170. and eax,edx ; Pass on interrupt bit if it was on
  171. mov dword ptr [ebx].VtVdmContext.CsEFlags,eax
  172. ; Save the calling address
  173. ; this address remains constant once krnl286 has booted.
  174. ; these three instructions are cheaper than saving it
  175. ; [LATER] this can be reduced. how?
  176. cmp _fKernelCSIPFixed, 0
  177. je wbegetretaddress
  178. add esp, 8 ; pop cs, ip
  179. wbe10:
  180. ; Save the stack (pre-call)
  181. mov _savess16,di ; 16-bit SS put in di by krnl286
  182. mov _savesp16,sp
  183. ; switch Stacks
  184. .errnz (CsEsp + 4 - CsSegSS)
  185. lss esp, [ebx].VtMonitorContext.CsEsp
  186. ; Now running on Monitor stack
  187. ; save hiword of ESI, EDI
  188. ; note that di has already been trashed
  189. ;
  190. ; [LATER] move this to the vdmframe, don't need to push it twice
  191. push esi
  192. push edi
  193. push ebp
  194. cPublicFpo 6,0 ; locals, params
  195. ; we only save 3 but FastWOWCallbackCall
  196. ; saves 3 as well
  197. ; Set up flat segment registers
  198. mov edx,KGDT_R3_DATA OR RPL_MASK
  199. mov es,dx ; Make them all point to DS
  200. mov gs,dx ; [LATER] do we really have to set up GS?
  201. mov eax,KGDT_R3_TEB OR RPL_MASK ; restore flat FS
  202. mov fs,ax
  203. mov ebp, _saveebp32
  204. ; Update the CURRENTPTD->vpStack
  205. mov eax,fs:[PcTeb]
  206. mov ecx,[eax+TbWOW32Reserved] ; move CURRENTPTD into ecx
  207. mov esi, [Stack16]
  208. mov dword ptr [ecx],esi ; PTD->vpStack = vpCurrentStack
  209. ; Convert the 16:16 SS:SP pointer into a 32-bit flat pointer
  210. ; DI = 16-bit SS, put there by kernel
  211. and esi, 0FFFFh ; esi = 16-bit sp
  212. and edi, 0FFFFh ; remove junk from high word
  213. shr edi, 3 ; remove ring and table bits
  214. mov edx, dword ptr [__imp__FlatAddress]
  215. add esi, dword ptr [edx+edi*4]
  216. ; esi is now a flat pointer to the frame
  217. mov eax,dword ptr [ecx+cbOffCOMMDLGTD] ; ecx = CURRENTPTD
  218. cmp eax,0 ; eax = PTD->PCOMMDLGTD
  219. jnz SsyncCommDlg16to32
  220. SsyncContinue1:
  221. ifdef DEBUG
  222. push ecx
  223. stdCall _logargs,<3,esi>
  224. pop ecx
  225. endif
  226. ; Convert the wCallID into a Thunk routine address.
  227. mov edx, dword ptr [esi].vf_wCallID
  228. ; esi = pFrame
  229. mov [ecx].WtdFastWowEsp, esp
  230. test edx, 0ffff0000h
  231. mov eax, edx
  232. jnz MakeCall
  233. ifdef DEBUG
  234. imul edx, size W32
  235. else
  236. .errnz (size W32 - 4)
  237. shl edx, 2
  238. endif
  239. mov edx, dword ptr [_aw32WOW + edx] ; eax = aw32WOW[edx].lpfnW32
  240. test edx, 0ffff0000h ; check for intthunk (hiword 0)
  241. jnz @f
  242. mov eax, @InterpretThunk@8
  243. jmp MakeCall
  244. @@:
  245. mov ecx, esi ; ecx = pFrame & edx = lpfnW32
  246. call @W32PatchCodeWithLpfnw32@8
  247. MakeCall:
  248. mov ecx, esi ; ecx = pFrame & edx = lpfnW32
  249. call eax
  250. ApiReturnAddress:
  251. ;
  252. ; IMPORTANT NOTE: Upon retruned from wow32 worker routine, the
  253. ; non-volatile registers may be destroyed if it is returned via
  254. ; try-except handler.
  255. ;
  256. mov ebx, dword ptr [__imp__CurrentMonitorTeb]
  257. mov ecx,fs:[PcTeb]
  258. mov [ebx], ecx ; Tell NTVDM which is the active thread
  259. mov ecx,[ecx+TbWOW32Reserved] ; move CURRENTPTD into ecx
  260. mov ebx,dword ptr [ecx+cbOffCOMMDLGTD] ; ecx = CURRENTPTD
  261. cmp ebx,0 ; ebx = PTD->PCOMMDLGTD
  262. jnz SsyncCommDlg32to16
  263. SsyncContinue2:
  264. ifdef DEBUG
  265. push ecx
  266. push eax
  267. movzx esi, word ptr [ecx] ; offset
  268. movzx edi, word ptr [ecx+2] ; selector
  269. shr edi, 3 ; remove ring and table bits
  270. mov ebx, dword ptr [__imp__FlatAddress]
  271. add esi, dword ptr [ebx+edi*4] ; esi = offset + base
  272. stdCall _logreturn,<5, esi, eax>
  273. pop eax
  274. pop ecx
  275. endif
  276. mov ebx, dword ptr fs:[PcTeb]
  277. mov ebx, dword ptr [ebx].TeVdm ; get pointer to contexts
  278. push dword ptr [ebx].VtVdmContext.CsEFlags ;get 16-bit flags
  279. popfd ; in case the direction flag was set
  280. test dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_INTERRUPT_PENDING
  281. jnz wl70
  282. wl40:
  283. mov _saveebp32, ebp
  284. pop ebp
  285. pop edi
  286. pop esi
  287. mov [ebx].VtMonitorContext.CsEsp,esp
  288. mov [ecx].WtdFastWowEsp,esp
  289. ; return to vdm stack
  290. push word ptr [ecx+2]
  291. push word ptr 0
  292. push word ptr [ecx]
  293. lss esp,[esp]
  294. ; stick the API return value in the stack for kernel to pop.
  295. ; it's been in EAX since we called the thunk routine.
  296. mov bx, sp ; for temporary addressing
  297. mov dword ptr ss:[bx].vf_wAX, eax
  298. ; return to VDM, fake a far jump
  299. push _savecs16
  300. push _saveip16
  301. mov eax,_saveeax ; Retore High parts of regs
  302. mov ebx,_saveebx
  303. mov ecx,_saveecx
  304. mov edx,_saveedx
  305. retf
  306. ;
  307. wl60: ; Interrupts are disabled, turn them off in the virtual flags
  308. ;
  309. _wowlock1:
  310. lock and dword ptr ds:FIXED_NTVDMSTATE_LINEAR,NOT VDM_VIRTUAL_INTERRUPTS
  311. jmp wl40
  312. ;
  313. wl70: ; Interrupt came in, dispatch it
  314. ;
  315. ; translate the interrupt flag to the virtual interrupt flag
  316. ; if interrupts are disabled then blow it off
  317. test [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK
  318. jz wl60
  319. _wowlock2:
  320. lock or dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS
  321. push eax ; save API return value
  322. push ebx
  323. push ecx
  324. ;
  325. ; refresh VdmTib.VtVdmContext so DispatchInterrupts can party
  326. ;
  327. ; ecx points to CURRENTPTD->vpStack 16-bit ss:sp
  328. mov si, [ecx + 2]
  329. xor edi,edi
  330. mov di, [ecx]
  331. mov eax, _saveip16
  332. mov dword ptr [ebx].VtVdmContext.CsEip, eax
  333. mov eax, _savecs16
  334. mov dword ptr [ebx].VtVdmContext.CsSegCs, eax
  335. mov word ptr [ebx].VtVdmContext.CsSegSs, si
  336. mov dword ptr [ebx].VtVdmContext.CsEsp, edi
  337. stdCall _DispatchInterrupts
  338. test dword ptr [ebx].VtVdmContext.CsEFlags,VDM_VIRTUAL_INTERRUPTS
  339. jnz wl80
  340. _wowlock3:
  341. lock and dword ptr ds:FIXED_NTVDMSTATE_LINEAR,NOT VDM_VIRTUAL_INTERRUPTS
  342. wl80: pop ecx ; points to ptd->vpStack
  343. pop ebx
  344. pop eax ; eax = API return value
  345. mov _saveebp32, ebp
  346. ; restore the hiwords of esi, edi
  347. pop ebp
  348. pop edi
  349. pop esi
  350. mov dword ptr [ebx].VtMonitorContext.CsEsp,esp
  351. mov [ecx].WtdFastWowEsp,esp
  352. pushfd
  353. and dword ptr [esp], 0ffffbfffH
  354. popfd
  355. ;
  356. ; switch to 16-bit stack (probably an interrupt stack)
  357. ;
  358. .errnz (CsEsp + 4 - CsSegSS)
  359. lss esp, [ebx].VtVdmContext.CsEsp
  360. ;
  361. ; fake far jump to the 16-bit interrupt routine
  362. ;
  363. push dword ptr [ebx].VtVdmContext.CsEflags
  364. push dword ptr [ebx].VtVdmContext.CsSegCs
  365. push dword ptr [ebx].VtVdmContext.CsEip
  366. ; stick the API return value in the stack for kernel to pop.
  367. ; it's been in EAX since we called the thunk routine.
  368. ; les bx, Stack16
  369. les bx, [ecx]
  370. mov dword ptr es:[bx].vf_wAX, eax
  371. mov eax,_saveeax ; Retore High parts of regs
  372. mov ebx,_saveebx
  373. mov ecx,_saveecx
  374. mov edx,_saveedx
  375. iretd
  376. wbegetretaddress:
  377. pop eax
  378. mov _saveip16, eax
  379. pop edx
  380. mov _savecs16, edx
  381. jmp wbe10
  382. SsyncCommDlg16to32:
  383. push ecx ; save CURRENTPTD
  384. push dword ptr [esi+cbOffwThunkCSIP] ; esi = pFrame
  385. push 1 ; 16to32 flag
  386. push eax ; pComDlgTD
  387. call _Ssync_WOW_CommDlg_Structs@12
  388. pop ecx
  389. jmp SsyncContinue1
  390. SsyncCommDlg32to16:
  391. push ecx ; save CURRENTPTD
  392. push eax ; preserve API return value
  393. ; build a flat ptr to pFrame
  394. mov esi, [ecx]
  395. and esi, 0FFFFh ; esi = 16-bit sp
  396. ; edi should already be set
  397. mov edx, dword ptr [__imp__FlatAddress]
  398. add esi, dword ptr [edx+edi*4] ; esi = pframe
  399. push dword ptr [esi+cbOffwThunkCSIP] ; esi = pFrame
  400. push 0 ; 32to16 flag
  401. push ebx ; pComDlgTD
  402. call _Ssync_WOW_CommDlg_Structs@12
  403. pop eax
  404. pop ecx
  405. jmp SsyncContinue2
  406. stdENDP _WOWBopEntry
  407. cPublicProc _PostExceptionHandler,0
  408. assume ds:_DATA
  409. ;
  410. ; Fixed up Exception registration pointer (just in case)
  411. ;
  412. mov eax, fs:[PcExceptionList]
  413. peh00:
  414. cmp eax, esp
  415. jb short @f
  416. mov fs:[PcExceptionList], eax
  417. xor eax, eax
  418. jmp ApiReturnAddress
  419. @@:
  420. mov eax, [eax] ; move to next reg record
  421. jmp short peh00
  422. stdENDP _PostExceptionHandler
  423. ;++
  424. ;
  425. ; VOID
  426. ; W32SetExceptionContext (
  427. ; PCONTEXT ContextRecord
  428. ; );
  429. ;
  430. ; Routine Description:
  431. ;
  432. ; This functions updates exception context to our predefined
  433. ; post-exception handler such that if we continue exception
  434. ; execution the control will continue on our post-exception
  435. ; handling code.
  436. ;
  437. ; Arguments:
  438. ;
  439. ; ContextRecord - supplies a pointer to the exception context.
  440. ;
  441. ; Returns:
  442. ;
  443. ; Exception context updated.
  444. ;--
  445. cPublicProc _W32SetExceptionContext,1
  446. assume ds:_DATA
  447. push fs ; I don;t think we need this, just in case
  448. mov ecx,KGDT_R3_TEB OR RPL_MASK ; restore flat FS
  449. mov fs,cx
  450. mov ecx, fs:[PcTeb]
  451. mov ecx, dword [ecx].TeVdm
  452. pop fs
  453. mov edx, [esp+4] ; (edx) = Context Record
  454. mov ecx, dword ptr [ecx].VtMonitorContext.CsEsp
  455. mov [edx].CsEsp, ecx
  456. mov [edx].CsEip, offset FLAT:_PostExceptionHandler
  457. stdRET _W32SetExceptionContext
  458. stdENDP _W32SetExceptionContext
  459. ;++
  460. ;
  461. ; BOOLEAN
  462. ; IsW32WorkerException (
  463. ; VOID
  464. ; );
  465. ;
  466. ; Routine Description:
  467. ;
  468. ; This function checks if the exception occurred in WOW32 API.
  469. ;
  470. ; Arguments:
  471. ;
  472. ; None
  473. ;
  474. ; Returns:
  475. ;
  476. ; returns a BOOLEAN value to indicate if this is WOW32 API exception.
  477. ;
  478. ;--
  479. cPublicProc _IsW32WorkerException, 0
  480. assume ds:_DATA
  481. mov ecx, fs:[PcTeb]
  482. mov ecx, [ecx].TbWOW32Reserved
  483. mov eax, dword ptr [ecx].WtdFastWowEsp
  484. or eax, eax
  485. jz @f ; FastWowEsp is zero, not worker exception
  486. mov edx, [eax-4]
  487. cmp edx, offset FLAT:ApiReturnAddress
  488. ; eax is still monitor esp, so it's nonzero
  489. je short @f
  490. xor eax, eax
  491. @@: stdRET _IsW32WorkerException
  492. stdENDP _IsW32WorkerException
  493. _TEXT ends
  494. page ,132
  495. subttl "FastWOWCallbackCall"
  496. ;++
  497. ;
  498. ; Routine Description:
  499. ;
  500. ; This routine is a fast callback from WOW32 to 16-bit code.
  501. ; It assumes that the 16-bit stack pointer is already in Stack16.
  502. ; The caller must set this up with FastBopSetVDMStack() before
  503. ; calling this routine.
  504. ;
  505. ; WARNING: only the minimal set of registers are saved/restored
  506. ; as a speed optimization.
  507. ;
  508. ; Arguments:
  509. ;
  510. ; none
  511. ;
  512. ; Returns:
  513. ;
  514. ; nothing.
  515. ;
  516. _TEXT SEGMENT
  517. assume DS:FLAT
  518. cPublicProc _FastWOWCallbackCall,0
  519. ; Save monitor general registers on monitor stack
  520. ; we'll pick em back up on the way out of FastWOWCallbackRet
  521. push esi
  522. push edi
  523. push ebx
  524. mov ebx, fs:[PcTeb]
  525. mov ebx, dword ptr [ebx].TeVdm
  526. ; translate the interrupt flag to the virtual interrupt flag
  527. test [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK
  528. jz fe10
  529. _wowlock4:
  530. lock or dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS
  531. test dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_INTERRUPT_PENDING
  532. jnz fe70
  533. jmp fe20
  534. fe10:
  535. _wowlock5:
  536. lock and dword ptr ds:FIXED_NTVDMSTATE_LINEAR, NOT VDM_VIRTUAL_INTERRUPTS
  537. fe20:
  538. mov _saveebp32, ebp
  539. mov ecx, fs:[PcTeb]
  540. mov ecx, [ecx].TbWOW32Reserved ; move CURRENTPTD into ecx
  541. mov [ebx].VtMonitorContext.CsEsp,esp
  542. mov [ecx].WtdFastWowEsp,esp
  543. pushfd
  544. pop ecx
  545. mov [ebx].VtMonitorContext.CsEflags,ecx
  546. pushfd
  547. and dword ptr [esp], 0ffffbfffH
  548. popfd
  549. ; switch to vdm stack
  550. push _savess16
  551. push word ptr 0
  552. push _savesp16
  553. lss esp, [esp]
  554. ; before going to 16 bit, patch ebp to zero the high bits
  555. ; hijaak pro app is relying upon hiword of ebp being 0
  556. and ebp, 0ffffh
  557. ; put flags, cs, and ip onto the 16-bit stack so we can iret to krnl286
  558. push dword ptr [ebx].VtVdmContext.CsEflags
  559. push _savecs16
  560. push _saveip16
  561. ; return to krnl286
  562. iretd
  563. fe70: ; Interrupt pending, dispatch it
  564. ;
  565. push ebx
  566. push eax
  567. ;
  568. ; refresh VdmTib.VtVdmContext so DispatchInterrupts can party
  569. ;
  570. mov eax, _saveip16
  571. mov edx, _savecs16
  572. mov dword ptr [ebx].VtVdmContext.CsEip, eax
  573. mov dword ptr [ebx].VtVdmContext.CsSegCs, edx
  574. mov ax, _savess16
  575. xor edx,edx
  576. mov dx, _savesp16
  577. mov word ptr [ebx].VtVdmContext.CsSegSs, ax
  578. mov dword ptr [ebx].VtVdmContext.CsEsp, edx
  579. stdCall _DispatchInterrupts
  580. test dword ptr [ebx].VtVdmContext.CsEFlags,VDM_VIRTUAL_INTERRUPTS
  581. jnz fe80
  582. _wowlock6:
  583. lock and dword ptr ds:FIXED_NTVDMSTATE_LINEAR,NOT VDM_VIRTUAL_INTERRUPTS
  584. fe80: pop eax
  585. pop ebx
  586. mov _saveebp32, ebp
  587. mov ecx, fs:[PcTeb]
  588. mov ecx, [ecx].TbWOW32Reserved
  589. mov [ebx].VtMonitorContext.CsEsp,esp
  590. mov [ecx].WtdFastWowEsp,esp
  591. pushfd
  592. pop ecx
  593. mov [ebx].VtMonitorContext.CsEflags,ecx
  594. pushfd
  595. and dword ptr [esp], 0ffffbfffH
  596. popfd
  597. ; switch to vdm stack
  598. push word ptr [ebx].VtVdmContext.CsSegSs
  599. push dword ptr [ebx].VtVdmContext.CsEsp
  600. lss esp, [esp]
  601. ; put flags, cs, and ip onto the 16-bit stack so we can iret to krnl286
  602. ; before interrupts are dispatched, patch ebp to zero the high bits
  603. ; hijaak pro app is relying upon hiword of ebp being 0
  604. and ebp, 0ffffh
  605. push dword ptr [ebx].VtVdmContext.CsEflags
  606. push dword ptr [ebx].VtVdmContext.CsSegCs
  607. push dword ptr [ebx].VtVdmContext.CsEip
  608. ; return to krnl or interrupt routine
  609. iretd
  610. stdENDP _FastWOWCallbackCall
  611. ;++
  612. ;
  613. ; Routine Description:
  614. ;
  615. ; This routine is called by krnl286 upon returning from a
  616. ; callback.
  617. ;
  618. ; Arguments:
  619. ;
  620. ; none
  621. ;
  622. ; Returns:
  623. ;
  624. ; nothing
  625. ;
  626. ; WARNING: only the minimal set of registers are saved/restored
  627. ; as a speed optimization.
  628. ;
  629. ;
  630. assume DS:Nothing,ES:Nothing,SS:Nothing
  631. ALIGN 16
  632. cPublicProc _FastWOWCallbackRet,0
  633. mov ebx,KGDT_R3_DATA OR RPL_MASK
  634. mov ds,bx
  635. assume ds:_DATA
  636. mov ebx, KGDT_R3_TEB OR RPL_MASK
  637. mov fs, bx
  638. mov ebx, fs:[PcTeb]
  639. mov ebx, dword ptr [ebx].TeVdm
  640. pushfd
  641. pop eax
  642. mov dword ptr [ebx].VtVdmContext.CsEFlags,eax
  643. ; the words at top of stack are the return address of our
  644. ; caller (krnl286).
  645. ; this address remains constant once krnl286 has booted.
  646. ; these three instructions are cheaper than saving it
  647. cmp _fKernelCSIPFixed, 0
  648. je fwcbrgetretaddress
  649. add esp, 8 ; pop cs, ip
  650. fwcbr10:
  651. ; refresh CURRENTPTD->vpStack with the current stack
  652. ;mov ecx, KGDT_R3_TEB OR RPL_MASK
  653. ;mov fs, cx
  654. mov eax, fs:[PcTeb]
  655. mov ecx, [eax+TbWOW32Reserved] ; move CURRENTPTD into ecx
  656. mov _savess16,ss
  657. mov _savesp16,sp
  658. mov esi, [Stack16]
  659. mov [ecx], esi
  660. movzx esi,si
  661. mov dword ptr [ebx].VtVdmContext.CsEsp, esi
  662. mov word ptr [ebx].VtVdmContext.CsSegSs, ss
  663. ; switch Stacks
  664. .errnz (CsEsp + 4 - CsSegSS)
  665. lss esp, [ebx].VtMonitorContext.CsEsp
  666. ; Now running on Monitor stack
  667. test dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS
  668. jz fl10
  669. or [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK
  670. jmp fl20
  671. fl10: and dword ptr [ebx].VtVdmContext.CsEFlags, NOT EFLAGS_INTERRUPT_MASK
  672. fl20:
  673. ; set up Monitor regs
  674. mov esi, KGDT_R3_DATA OR RPL_MASK
  675. mov es, si
  676. ; [LATER] do we really have to set up the GS?
  677. mov gs, si
  678. ; set up Monitor general regs
  679. mov ebp, _saveebp32
  680. ; return
  681. pop ebx
  682. pop edi
  683. pop esi
  684. ret
  685. fwcbrgetretaddress:
  686. pop eax
  687. pop edx
  688. mov _saveip16, eax
  689. mov _savecs16, edx
  690. jmp fwcbr10
  691. stdENDP _FastWOWCallbackRet
  692. ;++
  693. ;
  694. ; Routine Description:
  695. ;
  696. ; This returns the current task's 16-bit ss:sp (vpStack)
  697. ;
  698. ; Arguments:
  699. ;
  700. ; none
  701. ;
  702. ; Returns:
  703. ;
  704. ; returns a 32-bit value that can be passed to GetVDMPointer
  705. ;
  706. assume DS:_DATA,SS:Nothing
  707. cPublicProc _FastBopVDMStack,0
  708. mov eax, [Stack16]
  709. stdRET _FastBopVDMStack
  710. stdENDP _FastBopVDMStack
  711. ;++
  712. ;
  713. ; Routine Description:
  714. ;
  715. ; This sets the current task's 16-bit ss:sp (vpStack),
  716. ; used only when FASTSTACK is enabled.
  717. ;
  718. ; Arguments:
  719. ;
  720. ; vpStack (32-bit ss:sp, not a flat pointer)
  721. ;
  722. ; Returns:
  723. ;
  724. ; none
  725. ;
  726. cPublicProc _FastBopSetVDMStack,1
  727. mov eax, [esp+4]
  728. mov [Stack16], eax
  729. stdRET _FastBopSetVDMStack
  730. stdENDP _FastBopSetVDMStack
  731. _TEXT ends
  732. end