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.

610 lines
16 KiB

  1. TITLE TASKING.ASM - WOW Tasking Support
  2. PAGE ,132
  3. ;
  4. ; WOW v1.0
  5. ;
  6. ; Copyright (c) 1991, Microsoft Corporation
  7. ;
  8. ; TASKING.ASM
  9. ; WOW Tasking Support on 16 bit side - also see wkman.c
  10. ;
  11. ; History:
  12. ; 23-May-91 Matt Felton (mattfe) Created
  13. ; 12-FEB-92 Cleanup
  14. ;
  15. .xlist
  16. include kernel.inc
  17. include tdb.inc
  18. include newexe.inc
  19. include wow.inc
  20. include vint.inc
  21. .list
  22. if PMODE32
  23. .386
  24. else
  25. .286
  26. endif
  27. if KDEBUG
  28. externFP OutputDebugString
  29. endif
  30. DataBegin
  31. externB Kernel_InDOS
  32. externB Kernel_flags
  33. externB InScheduler
  34. ifndef WOW
  35. externB fProfileDirty
  36. endif
  37. externW WinFlags
  38. externW cur_drive_owner
  39. externW curTDB
  40. externW Win_PDB
  41. externW LockTDB
  42. externW headTDB
  43. externW hShell
  44. externW pGlobalHeap
  45. externW hExeHead
  46. externW f8087
  47. externD pIsUserIdle
  48. externW wCurTaskSS
  49. externW wCurTaskBP
  50. globalw gwHackpTDB,0
  51. globalw gwHackTaskSS,0
  52. globalw gwHackTaskSP,0
  53. if PMODE32
  54. externW PagingFlags
  55. endif
  56. DataEnd
  57. ifdef WOW
  58. externFP ExitKernelThunk
  59. externFP WowInitTask
  60. externFP Yield
  61. externFP WOW16CallNewTaskRet
  62. externFP WowKillTask
  63. externFP WOW16DoneBoot
  64. externFP WOWGetCurrentDirectory
  65. externFP ExitCall
  66. externFP WowSyncTask
  67. endif
  68. sBegin CODE
  69. assumes cs,CODE
  70. assumes ds,NOTHING
  71. assumes es,NOTHING
  72. ife PMODE
  73. externNP patch_cached_p
  74. endif
  75. externNP LoadSegment
  76. externNP DeleteTask
  77. externNP InsertTask
  78. if PMODE32
  79. externNP ShrinkHeap
  80. endif
  81. ifdef WOW
  82. externNP Int21Handler
  83. endif
  84. if SDEBUG
  85. externNP DebugSwitchOut
  86. externNP DebugSwitchIn
  87. endif
  88. ;-----------------------------------------------------------------------;
  89. ; StartWOWTask ;
  90. ; ;
  91. ; Start a WOW 32 Task ;
  92. ; ;
  93. ; Arguments: ;
  94. ; Parmw1 -> TDB Of New Task ;
  95. ; Parmw2 New Task SS ;
  96. ; Parmw3 New Task SP ;
  97. ; Returns: ;
  98. ; AX - TRUE/FALSE if we we able to create a new WOW task ;
  99. ; Error Returns: ;
  100. ; none ;
  101. ; Registers Preserved: ;
  102. ; ;
  103. ; Registers Destroyed: ;
  104. ; BX,CX,DX ;
  105. ; Calls: ;
  106. ; See Notes ;
  107. ; History: ;
  108. ; ;
  109. ; Fre 24-May-1991 14:30 -by- Matthew A. Felton [mattfe] ;
  110. ; Created ;
  111. ;-----------------------------------------------------------------------;
  112. ; The 16-Bit Kernel has created the new task and its ready to go
  113. ; 1. Temporarily Switch to New Task Stack S2
  114. ; 2. Fake Far Return from Thunk to point to StartW16Task
  115. ; 3. Thunk to WOW32 - This will create a new Thread and call Win32 InitTask()
  116. ; Note InitTask() will not return from the non-preemptive scheduler until
  117. ; This thread does a Yield.
  118. ; 4. When the thunk returns is jmps to WOW16TaskStarted on S2 leaving
  119. ; S2 ready for the new task when it returns
  120. ; 5. Restore S1 - Original Task Stack
  121. ; 6. Return Back to LoadModule who will Yield and start T2 going.
  122. assumes ds, nothing
  123. assumes es, nothing
  124. cProc StartWOWTask,<PUBLIC,FAR>
  125. parmW pTDB
  126. parmW wTaskSS
  127. parmW wTaskSP
  128. cBegin
  129. SetKernelDS ds
  130. mov es,pTDB ; Get New Task TDB, will use later
  131. push curTDB ; Save our TDB
  132. push bp ; save BP (we don't exit wow16cal directly)
  133. mov di,ss ; Save Current Task Stack
  134. mov cx,sp ; di=ss cx=sp
  135. ; switch to new task stack temporarily
  136. FCLI ; Disable Ints Till We get Back
  137. ; To presever new fram
  138. mov si,wTaskSP ; Grab this before SS goes away
  139. mov ss,wTaskSS ; Switch to new task stack.
  140. mov sp,si ;
  141. mov curTDB,es ; Set curTDB to new task
  142. ;
  143. pushf
  144. pop ax
  145. or ax,0200h ; Re-enable interrupts
  146. push ax
  147. push es ; hTask
  148. mov es, es:[TDB_pModule] ; exehdr
  149. mov ax, es:[ne_expver]
  150. mov dx, es:[ne_flags]
  151. and dx, NEWINPROT ; prop. font bit
  152. push es ; hModule
  153. push es ; Pointer to module name
  154. push es:ne_restab
  155. push es ; Pointer to module path
  156. push word ptr es:ne_crc+2
  157. push dx ; expwinver. argument for WOWINITTASK
  158. push ax
  159. mov es, curTDB ; resotre es, just being safe
  160. ; thunk to wow32 to create a thread and task
  161. push cs ; Fake Out FAR Return to StartW16Task
  162. push offset StartW16Task
  163. jmp WowInitTask ; Start Up the W32 Thread
  164. public WOW16TaskStarted
  165. WOW16TaskStarted:
  166. mov ss,di ; Restore Calling Task Stack
  167. mov sp,cx
  168. pop bp
  169. pop curTDB ; Restore real CurTDB
  170. FSTI ; OK we look like old task
  171. cEnd
  172. ;
  173. ; First code executed By New Task - Setup Registers and Go
  174. ;
  175. StartW16Task:
  176. add sp,+12
  177. pop ax ; Flags
  178. mov bp,sp
  179. xchg ax,[bp+20] ; Put flags down & pick up cs
  180. xchg ax,[bp+18] ; Put cs down & pick up ip
  181. xchg ax,[bp+16] ; Put ip down & pick up bp
  182. mov bp,ax
  183. dec bp
  184. pop dx
  185. pop bx
  186. pop es
  187. pop cx
  188. pop ax
  189. pop di
  190. pop si
  191. pop ds
  192. call SyncTask
  193. iret ; App Code Starts From Here
  194. ; ExitKernel
  195. ;
  196. ; Enter When the 16 bit Kernel is going away -- never returns.
  197. ; In WOW this is a register-args wrapper for the stack-args
  198. ; thunk ExitKernelThunk.
  199. public ExitKernel
  200. ExitKernel:
  201. cCall ExitKernelThunk, <ax>
  202. INT3_NEVER ; ExitKernel never returns.
  203. ; BootSchedule
  204. ;
  205. ; Entered When Bogus Boot Task goes Away - treated same as task exit.
  206. public BootSchedule
  207. BootSchedule:
  208. CheckKernelDS DS ; Make Sure we Address Kernel DS
  209. mov [curTDB],0 ; Make No Task the Current Task
  210. jmp WOW16DONEBOOT
  211. ; ExitSchedule
  212. ;
  213. ; We get here when a 16 bit task has exited - go kill this task
  214. ; Win32 non-preemptive scheduler will wake someone else to run.
  215. public ExitSchedule
  216. ExitSchedule:
  217. CheckKernelDS DS ; Make Sure we Address Kernel DS
  218. mov ax,[LockTDB] ; If I am the locked TDB then clear flag
  219. cmp ax,[curTDB]
  220. jnz @f
  221. mov [LockTDB],0
  222. @@:
  223. mov [curTDB],0 ; Make No Task the Current Task
  224. if PMODE32
  225. call ShrinkHeap
  226. endif; PMODE32
  227. jmp WowKillTask ; Go Kill Myself (NEVER RETURNS)
  228. ;-----------------------------------------------------------------------;
  229. ; SwitchTask - This is NOT a subroutine DO NOT CALL IT
  230. ;
  231. ; This routine does a Win 3.1 compatible task switch.
  232. ;
  233. ; Arguments:
  234. ; AX == Next Tasks TDB pointer
  235. ; Returns:
  236. ; nothing
  237. ; Error Returns:
  238. ; nothing
  239. ; Registers Preserved:
  240. ;
  241. ; Registers Destroyed:
  242. ;
  243. ; Calls:
  244. ; SaveState
  245. ; RestoreState
  246. ;
  247. ; History:
  248. ; 22-May-91 Matt Felton (MattFe) Created
  249. ; Using idea's from Win 3.1 Schedule.Asm
  250. ;
  251. ;-----------------------------------------------------------------------;
  252. assumes ds, nothing
  253. assumes es, nothing
  254. public SwitchTask
  255. SwitchTask:
  256. CheckKernelDS ds
  257. ReSetKernelDS ds
  258. inc InScheduler ; set flag for INT 24...
  259. cmp curTDB,0 ; Previous Task Gone Away ?
  260. jnz @f ; No ->
  261. ; Yes
  262. mov di,ax ; DI = New TDB
  263. mov ds,ax ; DS = New TDB
  264. jmps dont_save_state ; Get Set for this new guy
  265. @@:
  266. push ax ; Save Next Tasks TDB pointer
  267. ; COMPAT 22-May-91 Mattfe, Idle callout for funky screen drivers is done by
  268. ; the Windows scheduler - that will not happen either from WOW. INT 28
  269. ; and Win386 1689 int2f call
  270. ; There was PokeAtSegments code which during idle time brought back segments !
  271. ; Do Debuggers Care that the stack frame of registers looks like a Windows stack frame
  272. ; when we do the debugger callout ? - check with someone in CVW land.
  273. mov es,curTDB ; ES = Previous Task TDB
  274. mov ax,es ; Don't SS,SP For DEAD Task
  275. or ax,ax
  276. jz @F
  277. mov ax,wCurTaskSS ; FAKE Out TDB_taskSS,SP so that
  278. mov es:[TDB_taskSS],ax ; The Old Task Task_BP looks right
  279. mov ax,wCurTaskBP
  280. sub ax,(Task_BP-Task_DX)
  281. mov es:[TDB_taskSP],ax
  282. @@:
  283. pop ds ; DS = Next Task TDB
  284. UnSetKernelDS ds
  285. if KDEBUG
  286. ; Assertion Check TDB_taskSS == SS for current Task
  287. mov ax,ds:[TDB_taskSS]
  288. mov di,ss
  289. cmp di,ax
  290. jz @F
  291. ; int 3
  292. @@:
  293. endif; KDEBUG
  294. mov di,ds ; DI = destination task
  295. xor si,si ; SI is an argument to RestoreState
  296. mov ax,es ; NOTE TDB_SS,SP Are note Correct
  297. or ax,ax ; might affect debugger compatability.
  298. jz short dont_save_state
  299. cmp es:[TDB_sig],TDB_SIGNATURE
  300. jnz short dont_save_state
  301. mov si,es ; SI = Old Task
  302. cCall SaveState,<si>
  303. if SDEBUG
  304. push ds
  305. mov ds,ax
  306. call DebugSwitchOut ; Note Stack Frame is not Compatible
  307. pop ds ; Do we care ?
  308. endif
  309. dont_save_state:
  310. SetKernelDS es
  311. mov curTDB,di
  312. mov ax, ds:[TDB_PDB] ; Set our idea of the PDB
  313. mov Win_PDB, ax
  314. SetKernelDS es
  315. cmp di,0 ; the first task, will never get 0
  316. jz dont_restore_state
  317. ife PMODE
  318. call RestoreState
  319. endif
  320. or Kernel_flags,kf_restore_CtrlC OR kf_restore_disk
  321. if SDEBUG
  322. call DebugSwitchIn
  323. endif
  324. dont_restore_state:
  325. ; Switch to new task stack.
  326. mov curTDB,di
  327. dec InScheduler ; reset flag for INT 24
  328. SetKernelDS ds ; Set the Kernel DS again
  329. ;the word at [vf_wES] is a selector that's about to be popped into
  330. ;the ES in WOW16CallNewTaskRet. this selector could be the TDB of
  331. ;a task that just died, in which case it's invalid. so let's
  332. ;shove something in there that won't cause a GP when we do the POP ES.
  333. ;
  334. ; In some cases we are switching tasks while returning to a callback.
  335. ; When this happens our stack is a CBVDMFRAME instead of a VDMFRAME.
  336. ; We only want to shove a safe ES,FS,GS value when it's a VDMFRAME and
  337. ; we're returning from an API call rather than calling back to
  338. ; 16-bit code.
  339. ;
  340. ; Regardless of which frame we're using, ss:sp points to wRetID.
  341. mov bx, sp
  342. cmp WORD PTR ss:[bx], RET_DEBUGRETURN ; if (wRetID > RET_DEBUGRETURN)
  343. ja dont_stuff_regs ; goto dont_stuff_regs
  344. sub bx,vf_wTDB + 2 ;bx is now start of VDMFRAME struct
  345. mov ss:[bx+vf_wES],es ;put something safe in there
  346. ;Win31 does not save fs, gs over task switches, so we zero them out here
  347. mov word ptr ss:[bx+vf_wFS],0 ;put something safe in there
  348. mov word ptr ss:[bx+vf_wGS],0 ;put something safe in there
  349. dont_stuff_regs:
  350. if KDEBUG
  351. mov bx, sp
  352. cmp WORD PTR ss:[bx], RET_TASKSTARTED
  353. jne @f
  354. INT3_NEVER ; We need to stuff ES for RET_TASKSTARTED
  355. ; if we hit this breakpoint.
  356. @@:
  357. endif
  358. ; Hung App Support
  359. ; If the new task is the one we want to kill then force it to exit
  360. mov bx,curTDB ; if ( curTDB == LockTDB )
  361. cmp bx,LockTDB
  362. jnz SW_DontKillIt
  363. mov ax,4CFFH ; YES -> Exit
  364. DOSCALL
  365. INT3_NEVER
  366. SW_DontKillIt:
  367. jmp WOW16CallNewTaskRet ; Continue with the new task.
  368. ;-----------------------------------------------------------------------;
  369. ; SaveState ;
  370. ; ;
  371. ; Saves the state of the current MS-DOS process. This means the per ;
  372. ; task interrupt vectors, the drive and directory, EEMS land if any, ;
  373. ; and old app stuff if any. ;
  374. ; ;
  375. ; Arguments: ;
  376. ; parmW destination ;
  377. ; ;
  378. ; Returns: ;
  379. ; DS returned in AX. ;
  380. ; ;
  381. ; Error Returns: ;
  382. ; ;
  383. ; Registers Preserved: ;
  384. ; ;
  385. ; Registers Destroyed: ;
  386. ; ;
  387. ; Calls: ;
  388. ; ;
  389. ; History: ;
  390. ; ;
  391. ; Mon 07-Aug-1989 21:53:42 -by- David N. Weise [davidw] ;
  392. ; Removed the WinOldApp support. ;
  393. ; ;
  394. ; Tue Feb 03, 1987 08:21:53p -by- David N. Weise [davidw] ;
  395. ; Got rid of the rest of the DOS version dependencies. ;
  396. ; ;
  397. ; Thu Jan 22, 1987 03:15:15a -by- David N. Weise [davidw] ;
  398. ; Took out the saving of the ^C state, DTA address, and ErrorMode. ;
  399. ; ;
  400. ; Sun Jan 04, 1987 04:40:44p -by- David N. Weise [davidw] ;
  401. ; Added this nifty comment block. ;
  402. ;-----------------------------------------------------------------------;
  403. assumes ds, nothing
  404. assumes es, nothing
  405. cProc SaveState,<PUBLIC,NEAR>,<si,di,ds>
  406. parmW destination
  407. cBegin
  408. cld
  409. ife PMODE
  410. SaveTaskInts destination
  411. endif
  412. SetKernelDS
  413. mov ax,f8087
  414. UnSetKernelDS
  415. mov ds,destination
  416. or ax,ax
  417. if 0
  418. jz short no_fstcw
  419. .8087
  420. fstcw ds:[TDB_FCW]
  421. endif
  422. no_fstcw:
  423. test ds:[TDB_Drive],10000000b; if hi bit set....
  424. jnz short ss_ret ; ...no need to get dir
  425. mov ah,19h
  426. DOSCALL
  427. mov dl,al
  428. inc dl
  429. or al,10000000b
  430. mov ds:[TDB_Drive],al ; save it (A=0, B=1, etc.)
  431. mov si,TDB_LFNDirectory
  432. mov byte ptr [si],'\' ; set "\"
  433. inc si
  434. ; get Long path
  435. cCall WowGetCurrentDirectory,<80h, ds, si>
  436. or dx, dx
  437. jz short ss_ret
  438. mov byte ptr [si-1],0 ; indicate error with null byte
  439. ss_ret: mov ax,ds
  440. cEnd
  441. ;-----------------------------------------------------------------------;
  442. ; RestoreState ;
  443. ; ;
  444. ; Restores the MS-DOS interrupt vectors in real mode. ;
  445. ; ;
  446. ; Arguments: ;
  447. ; none ;
  448. ; Returns: ;
  449. ; none ;
  450. ; Error Returns: ;
  451. ; none ;
  452. ; Registers Preserved: ;
  453. ; BX,CX,DX,DI,SI,DS,ES ;
  454. ; Registers Destroyed: ;
  455. ; AX ;
  456. ; Calls: ;
  457. ; nothing ;
  458. ; History: ;
  459. ; ;
  460. ; Mon 07-Aug-1989 21:53:42 -by- David N. Weise [davidw] ;
  461. ; Removed the WinOldApp support. ;
  462. ; ;
  463. ; Tue Feb 03, 1987 08:21:53p -by- David N. Weise [davidw] ;
  464. ; Got rid of the rest of the DOS version dependencies. ;
  465. ; ;
  466. ; Thu Jan 22, 1987 03:15:15a -by- David N. Weise [davidw] ;
  467. ; Took out the restoring of the ^C state, DTA address, and ErrorMode. ;
  468. ; ;
  469. ; Sun Jan 04, 1987 04:45:31p -by- David N. Weise [davidw] ;
  470. ; Added this nifty comment block. ;
  471. ;-----------------------------------------------------------------------;
  472. ife PMODE
  473. assumes ds, nothing
  474. assumes es, nothing
  475. cProc RestoreState,<PUBLIC,NEAR>
  476. cBegin nogen
  477. push di
  478. push si
  479. push ds
  480. push es
  481. cld
  482. RestTaskInts di ; restore DOS interrupts
  483. pop es
  484. pop ds
  485. pop si
  486. pop di
  487. ret
  488. cEnd nogen
  489. endif ; PMODE
  490. ; SyncTask
  491. ;
  492. ; Enter: when new task starts
  493. ; check if the new task is blocked by appshelp
  494. cProc SyncTask,<PUBLIC,NEAR> <ax,bx,cx,dx,di,si,es,ds>
  495. cBegin
  496. STL:
  497. cCall WowSyncTask
  498. cmp ax, 0
  499. je @F
  500. jg STL
  501. call ExitCall
  502. @@:
  503. cEnd
  504. sEnd CODE
  505. end