Leaked source code of windows server 2003
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.

1284 lines
40 KiB

  1. PAGE ,132
  2. TITLE DXSTRT.ASM -- Dos Extender Startup Code
  3. ; Copyright (c) Microsoft Corporation 1988-1991. All Rights Reserved.
  4. ;****************************************************************
  5. ;* *
  6. ;* DXSTRT.ASM - Dos Extender Startup Code *
  7. ;* *
  8. ;****************************************************************
  9. ;* *
  10. ;* Module Description: *
  11. ;* *
  12. ;* This module contains the executive initialization code for *
  13. ;* the Dos Extender. The module DXBOOT.ASM contains the code *
  14. ;* specific to starting up the Dos Extender. The module *
  15. ;* DXINIT.ASM contains the code specific to starting up the *
  16. ;* child program of the Dos Extender. The code in these *
  17. ;* two modules is discarded at the end of the initialization. *
  18. ;* The code in this module calls the initialization routines *
  19. ;* in the other to init modules, and then performs the final *
  20. ;* juggling of things to throw away the low memory init code, *
  21. ;* and transfer control to start up the child program. *
  22. ;* *
  23. ;****************************************************************
  24. ;* Revision History: *
  25. ;* *
  26. ;* 01/09/91 amitc At exit time Co-Processor being reset *
  27. ;* 08/08/90 earleh DOSX and client privilege ring determined *
  28. ;* by equate in pmdefs.inc *
  29. ;* 12/08/89 jimmat Added call to reenable EMM driver. *
  30. ;* 08/29/89 jimmat Restores Int 2Fh vector at exit *
  31. ;* 08/20/89 jimmat Removed A20 code, since HIMEM version 2.07 *
  32. ;* A20 code now works properly. *
  33. ;* 06/28/89 jimmat Now calls OEM layer instead of NetMapper *
  34. ;* 06/16/89 jimmat Implemented Windows/386 startup/exit Int *
  35. ;* 2Fh calls and ifdef'd combined EXE code *
  36. ;* 05/17/89 jimmat ChildTerminationHandler sets its SS:SP *
  37. ;* 04/18/89 jimmat Added calls to init/term NetBIOS mapper *
  38. ;* 03/28/89 jimmat Incorporated bug fix from GeneA related *
  39. ;* to nested GP faults in ChildTermHandler *
  40. ;* 03/11/89 jimmat Added support for TSS & LDT *
  41. ;* 03/07/89 jimmat converted to use WDEB386 *
  42. ;* 02/27/89 (GeneA): shrink initial memory block size on entry *
  43. ;* 02/25/89 (GeneA): added support for combined exe file where *
  44. ;* the Dos Extender and the child reside in the same exe *
  45. ;* file. *
  46. ;* 02/17/89 (GeneA): fixed error termination code for startup *
  47. ;* errors that occur while in protected mode *
  48. ;* 02/14/89 (GeneA): added code to reduce size of real mode *
  49. ;* code segment to throw away initialization code. *
  50. ;* 01/31/89 (GeneA): created by copying code from the old *
  51. ;* DXINIT.ASM *
  52. ;* 18-Dec-1992 sudeepb Changed cli/sti to faster FCLI/FSTI
  53. ;****************************************************************
  54. .286p
  55. ; -------------------------------------------------------
  56. ; INCLUDE FILE DEFINITIONS
  57. ; -------------------------------------------------------
  58. .sall
  59. .xlist
  60. include segdefs.inc
  61. include gendefs.inc
  62. include pmdefs.inc
  63. include hostdata.inc
  64. include dpmi.inc
  65. include intmac.inc
  66. .list
  67. ; -------------------------------------------------------
  68. ; GENERAL SYMBOL DEFINITIONS
  69. ; -------------------------------------------------------
  70. WIN386_INIT equ 1605h ;Win/386 startup Int 2Fh
  71. WIN386_EXIT equ 1606h ;Win/386 shutdown Int 2Fh
  72. WIN386_DOSX equ 0001h ;Win/386 init/exit really DOSX flag
  73. ; -------------------------------------------------------
  74. ; EXTERNAL SYMBOL DEFINITIONS
  75. ; -------------------------------------------------------
  76. extrn InitDosExtender:NEAR
  77. extrn RestoreRMIntrVectors:NEAR
  78. extrn SaveRMIntrVectors:NEAR
  79. extrn EnterRealMode:NEAR
  80. extrn EnterProtectedMode:NEAR
  81. extrn InitializeOEM:NEAR
  82. extrn TerminateOEM:NEAR
  83. externNP NSetSegmentAccess
  84. extrn DupSegmentDscr:NEAR
  85. extrn EMMEnable:NEAR
  86. ifdef WOW_x86
  87. externFP NSetSegmentDscr
  88. else
  89. externFP NSetGDTSegmentDscr
  90. ENDIF; WOW_x86
  91. extrn PMIntr19:NEAR
  92. extrn PMIntr13:NEAR
  93. extrn PMIntr31:NEAR
  94. extrn PMIntr28:NEAR
  95. extrn PMIntr25:NEAR
  96. extrn PMIntr26:NEAR
  97. extrn PMIntr4B:NEAR
  98. extrn PMIntrDos:NEAR
  99. extrn PMIntrMisc:NEAR
  100. extrn PMIntrVideo:NEAR
  101. extrn PMIntrMouse:NEAR
  102. extrn PMIntrIgnore:NEAR
  103. extrn PMIntrEntryVector:NEAR
  104. extrn PMFaultEntryVector:NEAR
  105. ifdef NEC_98 ;
  106. extrn PMIntr11dummy:NEAR
  107. extrn PMIntrPrinter:NEAR
  108. extrn PMIntrCalTi:NEAR
  109. extrn PMIntrGraph:NEAR
  110. endif ;NEC_98 ;
  111. ; -------------------------------------------------------
  112. ; DATA SEGMENT DEFINITIONS
  113. ; -------------------------------------------------------
  114. ; -------------------------------------------------------
  115. DXDATA segment
  116. extrn A20EnableCount:WORD
  117. extrn lpfnUserMouseHandler:DWORD
  118. extrn lpfnUserPointingHandler:DWORD
  119. extrn f286_287:BYTE
  120. extrn cDPMIClients:WORD
  121. extrn selCurrentHostData:WORD
  122. extrn segCurrentHostData:WORD
  123. ifdef WOW_x86
  124. extrn FastBop:fword
  125. endif
  126. extrn DpmiFlags:WORD
  127. org 0
  128. public rgwStack,npEHStackLimit,npEHStacklet, selEHStack,
  129. ;
  130. ; Pmode fault handler stack used during initialization only.
  131. ;
  132. dw 80h dup (?)
  133. rgwStack label word
  134. ;
  135. ; This is the stack area used while running in the interrupt reflector.
  136. ; This is divided up into a number of stack frames to allow reentrant
  137. ; execution of the interrupt reflector. The stack pointer pbReflStack
  138. ; indicates the current stack frame to use. Each entry into the interrupt
  139. ; reflector decrements this variable by the size of the stack frame, and
  140. ; each exit from the interrupt reflector increments it.
  141. C_STKFRAME = 36
  142. CB_REFLSTACK = C_STKFRAME * CB_STKFRAME
  143. if DEBUG ;--------------------------------------------------------
  144. public StackGuard
  145. StackGuard dw 1022h ;unlikely value to check for stk overrun
  146. endif ;--------------------------------------------------------
  147. public pbReflStack,bReflStack
  148. if DBG
  149. bReflStack db CB_REFLSTACK dup (0AAh)
  150. else
  151. bReflStack db CB_REFLSTACK dup (?)
  152. endif
  153. ;----------------------------------------------------------------------------
  154. ; The following stack is used for hw interrupts while booting where
  155. ; the kernel or ntvdm switches the stack before an interrupt is reflected.
  156. ;----------------------------------------------------------------------------
  157. CB_HWINTRSTACK = 1000h
  158. if DBG
  159. bHwIntrStack db CB_HWINTRSTACK dup (0AAh)
  160. else
  161. bHwIntrStack db CB_HWINTRSTACK dup (?)
  162. endif
  163. public pbHwIntrStack
  164. pbHwIntrStack dw bHwIntrStack + CB_HWINTRSTACK
  165. pbReflStack dw bReflStack + CB_REFLSTACK
  166. npEHStackLimit dw offset DGROUP:rgwStack
  167. npEHStacklet dw offset DGROUP:rgwStack
  168. selEHStack dw 0
  169. public cdscGDTMax, selGDTFree, segGDT, selGDT
  170. cdscGDTMax dw CDSCGDTDEFAULT
  171. selGDTFree dw ? ;head of list of free descriptors in GDT
  172. segGDT dw 0 ;real mode paragraph address of the GDT
  173. ; This variable always stores the real mode
  174. ; paragraph address
  175. selGDT dw 0 ;current mode segment/selector for the GDT
  176. ; segment. This variable holds the real
  177. ; mode paragraph address during initialization
  178. ; and then holds the protected mode selector
  179. ; when running in protected mode.
  180. public bpGDT, bpGDTcb, bpGDTbase
  181. bpGDT label fword
  182. bpGDTcb dw ?
  183. bpGDTbase dd ?
  184. public segIDT, selIDT
  185. segIDT dw 0
  186. selIDT dw 0
  187. public bpIDT, bpIDTcb, bpIDTbase
  188. bpIDT label fword
  189. bpIDTcb dw ?
  190. bpIDTbase dd ?
  191. public bpRmIVT
  192. bpRmIVT dq 0FFFFh ;This is the segment descriptor for the real
  193. ; mode interrupt vector table.
  194. public lpfnXMSFunc
  195. lpfnXMSFunc dd 0 ;far pointer to XMS memory driver entry point
  196. public idCpuType
  197. idCpuType dw 0
  198. public segPSP, selPSP
  199. segPSP dw ? ;segment address of Dos Extender PSP
  200. selPSP dw ? ;selector for Dos Extender PSP
  201. ; code during processing of GP faults
  202. public selPSPChild, segPSPChild
  203. segPSPChild dw ? ;real mode segment address of child's PSP
  204. ; note the following in 1, so that in low mem heap management, we can use
  205. ; selPSPChild to mark the owner of the memory.
  206. selPSPChild dw 1 ;selector of child program's PSP
  207. public DtaSegment, DtaOffset, DtaSelector
  208. DtaSegment dw 0
  209. DtaSelector dw 0
  210. DtaOffset dw 0
  211. public regChildSP, regChildSS, regChildIP, regChildCS
  212. regChildSP dw ? ;initial user stack pointer from exe file
  213. regChildSS dw ? ;initial user stack segment from exe file
  214. regChildIP dw ? ;initial user program counter from exe file
  215. regChildCS dw ? ;initial user code segment from exe file
  216. public hmemDOSX
  217. hmemDOSX dw 0
  218. IFDEF ROM
  219. public segDXCode, segDXData
  220. segDXCode dw ? ;holds real mode paragraph address
  221. ; of the code segment
  222. segDXData dw ? ;holds real mode paragraph address
  223. ; of the data segment
  224. ENDIF
  225. ifdef NEC_98
  226. public fPCH98
  227. fPCH98 db 0 ;NZ if running on a Micro Channel system
  228. public fNHmode
  229. fNHmode db 0 ;NZ if running on a Hmode system
  230. endif ;!NEC_98
  231. public fFaultAbort, ExitCode
  232. fFaultAbort db 0 ;NZ if terminating due to unrecoverable fault
  233. ExitCode db 0FFh ;exit code to use when terminating
  234. fQuitting db 0
  235. fEMbit db 0FFh ;MSW EM bit at startup (FF = not checked yet)
  236. public fUsingHMA
  237. fUsingHMA db 0
  238. ; The one and only Task State Segment is here (it's too small to allocate
  239. ; a block for it in extended memory)
  240. public sysTSS
  241. sysTSS TSS286 <>
  242. ; After initialization is complete, the following buffers (rgbXfrBuf0 and
  243. ; rgbXfrBuf1) are used to transfer data between real mode address space
  244. ; and protected mode address space during the processing of various interrupt
  245. ; function calls. During the initialization process, these buffers are also
  246. ; used as temporary work space as described below:
  247. ; CheckCPUType uses the first 6 bytes of rgbXfrBuf0 as scratch space.
  248. ; The functions for moving the Dos Extender protected mode code segment
  249. ; and the GDT and IDT use rgbXfrBuf0 as buffer space for building a
  250. ; parameter block. The child loading code in DXINIT.ASM uses the buffer
  251. ; RELOC_BUFFER for holding the base part of the file name (name.exe portion)
  252. ; of the child exe file while determining the complete path to the child
  253. ; in the case where the child name is specified on the command line. Note,
  254. ; this buffer is also used for holding sectors from the relocation table
  255. ; while loading the program, but that occurs after the child exe file name
  256. ; has been determined.
  257. ; The child loading code in DXINIT.ASM also uses rgbXfrBuf1 to hold several
  258. ; buffers as well. The locations and purposes of these buffers are
  259. ; described in GENDEFS.INC. All of the buffers are defined with equates
  260. ; named EXEC_?????
  261. ;
  262. ; The file search logic in DXFIND.ASM assumes some parameters are setup in
  263. ; the rgbXfrBuf1 file name buffers. Some of the code was moved from
  264. ; DXINIT.ASM to DXFIND.ASM.
  265. public rgbXfrBuf0, rgbXfrBuf1
  266. public npXfrBuf0, npXfrBuf1
  267. align 2
  268. rgbXfrBuf0 db CB_XFRBUF0 dup (?)
  269. rgbXfrBuf1 db CB_XFRBUF1 dup (?)
  270. npXfrBuf0 dw offset DGROUP:rgbXfrBuf0
  271. npXfrBuf1 dw offset DGROUP:rgbXfrBuf1
  272. DtaBuffer dw 128 dup (0) ; used as the dta for PM if dta changed
  273. ; Parameter block for passing to DOS EXEC call to run the child
  274. ; program.
  275. ;
  276. public exec_par_blk
  277. exec_par_blk dw 0
  278. cmd_off dw OFFSET EXEC_CMNDLINE
  279. cmd_seg dw DXDATA
  280. dw OFFSET EXEC_FCB0
  281. fcb1_seg dw DXDATA
  282. dw OFFSET EXEC_FCB1
  283. fcb2_seg dw DXDATA
  284. ; The following variables are used during reading the relocation table
  285. ; from the exe file and relocating the child program.
  286. public fhExeFile
  287. public clpRelocItem
  288. public plpRelocItem
  289. fhExeFile dw ? ;DOS file handle for the exe file
  290. clpRelocItem dw ? ;number of relocation items in the exe file
  291. plpRelocItem dw ? ;pointer to next relocation item in the table
  292. szDebugHello label byte
  293. if DEBUG
  294. db 'DOSX: Beginning protected mode initialization.',13,10,0
  295. endif
  296. db 0
  297. FreeMem dw 0
  298. DXDATA ends
  299. ; -------------------------------------------------------
  300. page
  301. ; -------------------------------------------------------
  302. ; CODE SEGMENT VARIABLES
  303. ; -------------------------------------------------------
  304. DXCODE segment
  305. extrn CodeEnd:NEAR
  306. extrn ER_DXINIT:BYTE
  307. extrn ER_REALMEM:BYTE
  308. extrn RMDefaultInt24Handler:FAR
  309. public segDXCode, segDXData, selDgroup
  310. segDXCode dw ? ;holds the real mode paragraph address
  311. ; of the code segment
  312. segDXData dw ? ;holds the real mode paragraph address
  313. ; of the data segment
  314. selDgroup dw ? ;holds the paragraph address/selector for
  315. ; DGROUP depending on the current mode
  316. public PrevInt2FHandler
  317. PrevInt2FHandler dd ? ;previous real mode Int 2F handler
  318. DXCODE ends
  319. DXPMCODE segment
  320. extrn CodeEndPM:NEAR
  321. org 0
  322. public selDgroupPM, segDXCodePM, segDXDataPM
  323. selDgroupPM dw ? ;This variable always contains the
  324. ; data segment selector
  325. segDXCodePM dw ? ;This variable contains the paragraph
  326. ; address of the real mode code segment
  327. segDXDataPM dw ? ;This variable contains the paragraph
  328. ; address of the data segment
  329. externFP NSetSegmentDscr
  330. DXPMCODE ends
  331. ; -------------------------------------------------------
  332. BeginLowSegment
  333. ; -------------------------------------------------------
  334. ; DOS EXTENDER ENTRY FUNCTION
  335. ; -------------------------------------------------------
  336. ;
  337. ; This is the program entry point for the Dos Extender. This
  338. ; function decides if the Dos Extender is being run as a single
  339. ; time operation to extend a single program, or if it is being
  340. ; run as a TSR to wait for programs to request its services
  341. ; later on.
  342. ;
  343. assume ds:PSPSEG,es:PSPSEG,ss:NOTHING
  344. public start
  345. start:
  346. ; Set up the initial segment registers.
  347. mov ax,DGROUP
  348. mov ds,ax
  349. assume ds:DGROUP
  350. mov segPSP,es ;save the PSP segment address
  351. mov ss,ax
  352. mov sp,offset DGROUP:rgwStack
  353. assume ss:DGROUP
  354. ;
  355. ; Set up the INT 24h handler. The default INT 24h handler fails the
  356. ; system call in progress, for DPMI compatibility.
  357. ;
  358. push ds
  359. mov ax,cs
  360. mov ds,ax
  361. mov dx,offset DXCODE:RMDefaultInt24Handler
  362. mov ax,2524h
  363. int 21h
  364. pop ds
  365. ; Issue the Win/386 startup Int 2Fh (almost) first thing
  366. push ds
  367. mov ax,WIN386_INIT ;gives other PM software a chance
  368. xor bx,bx ; to disable itself, release XMS, etc.
  369. mov cx,bx
  370. mov si,bx
  371. mov ds,bx
  372. mov es,bx
  373. assume ds:NOTHING, es:NOTHING
  374. mov dx,WIN386_DOSX
  375. mov di,DXVERSION
  376. int 2Fh
  377. pop ax ;restore ds/es DGROUP addressability
  378. mov ds,ax
  379. mov es,ax
  380. assume ds:DGROUP, es:DGROUP
  381. jcxz Allow_Startup ;if cx still == 0, keep going (we ignore
  382. ; all the other possible return values)
  383. mov ExitCode,2 ; otherwise we should abort now
  384. jmp RealModeCleanUp
  385. Allow_Startup:
  386. ; Initialize the Dos Extender
  387. call InitDosExtender ;NOTE: passes data to InitChildProgram
  388. jnc @F ; in rgbXfrBuf1 -- don't overwrite it!
  389. jmp strt88
  390. @@:
  391. ; Save the state of the MSW EM bit (Emulate Math coprocessor), and turn
  392. ; it off (win87em wants it off).
  393. ifndef WOW_x86
  394. smsw ax
  395. out1 <What to do about this?>
  396. test al,01h ;in V86 mode?
  397. jnz @f ; can't do the lmsw if so
  398. push ax
  399. and al,04h
  400. mov fEMbit,al
  401. pop ax
  402. and al,not 04h
  403. lmsw ax
  404. @@:
  405. endif ; WOW_x86
  406. ; Switch the machine into protected mode.
  407. FCLI
  408. call SaveRMIntrVectors
  409. SwitchToProtectedMode
  410. public DXPMInit
  411. DXPMInit LABEL BYTE
  412. if DEBUG
  413. Trace_Out "*******************************************************************************"
  414. Trace_Out "*******************************************************************************"
  415. Trace_Out "**** ****"
  416. Trace_Out "**** THIS IS A DEBUG RELEASE THIS IS A DEBUG RELEASE ****"
  417. Trace_Out "**** ****"
  418. Trace_Out "*******************************************************************************"
  419. Trace_Out "*******************************************************************************"
  420. endif
  421. assume ds:DGROUP,es:NOTHING
  422. mov ax,SEL_IDT or STD_RING
  423. mov selIDT,ax
  424. mov ax,SEL_LDT_ALIAS OR STD_RING
  425. mov selGDT,ax
  426. ; Initialize the LDT now that we are in protected mode. First, set the
  427. ; contents to zero.
  428. mov es,selGDT ; actually LDT
  429. assume es:NOTHING
  430. mov cx,cdscGDTMax
  431. IFDEF WOW
  432. mov di,GDT_SIZE
  433. sub cx,di
  434. ENDIF
  435. shl cx,2 ; CX = words in LDT segment
  436. xor ax,ax ; AX = 0
  437. IFNDEF WOW
  438. mov di,ax
  439. ENDIF
  440. cld
  441. rep stosw ; CX = 0
  442. dec cx ; CX = 0FFFFh
  443. push ax
  444. push cx
  445. mov ax,es ; LDT selector
  446. lsl cx,ax ; LDT size
  447. mov di,SEL_USER and SELECTOR_INDEX
  448. DPMIBOP InitLDT
  449. pop cx
  450. pop ax
  451. ;
  452. ; Set the two scratch selectors to 64k data starting at zero. Actual
  453. ; addresses set as used.
  454. ;
  455. cCall NSetSegmentDscr,<SEL_SCR0,ax,ax,ax,cx,STD_DATA>
  456. cCall NSetSegmentDscr,<SEL_SCR1,ax,ax,ax,cx,STD_DATA>
  457. ifndef WOW_x86
  458. mov dx,40h*16
  459. cCall NSetGDTSegmentDscr,<040h,ax,dx,ax,cx,STD_DATA>
  460. endif
  461. ; Bop to initialize 32 bit support.
  462. push es
  463. mov ax,SEL_DXCODE OR STD_RING
  464. mov es,ax
  465. assume es:DXCODE
  466. mov di, sp ;original stack offset
  467. push ds
  468. push offset DGROUP:DtaBuffer
  469. push ds
  470. push offset DGROUP:pbReflStack
  471. push ds
  472. push offset DGROUP:rgbXfrBuf1
  473. push ds
  474. push offset DGROUP:rgbXfrBuf0
  475. mov si,sp ;pass stack offset
  476. FBOP BOP_DPMI,InitDosx,FastBop
  477. mov sp, di ;restore stack
  478. pop es
  479. assume es:nothing
  480. call AllocateExceptionStack
  481. FSTI ;don't need ints disabled
  482. ; Shrink the size of our real mode code segment to throw away init code.
  483. SwitchToRealMode
  484. mov bx,(offset CodeEnd) + 15
  485. shr bx,4
  486. add bx,segDXCode
  487. sub bx,segPSP
  488. push es
  489. mov es,segPSP
  490. dossvc 4Ah
  491. pop es
  492. call DetermineFreeMemory
  493. mov FreeMem,bx
  494. SwitchToProtectedMode
  495. ; Initialize the OEM layer. This can allocate DOS memory, so it goes
  496. ; after the final program shrink.
  497. call InitializeOEM ;currently initializes NetBIOS mapper
  498. if1
  499. %OUT InitializeOEM can fail!!!!!
  500. endif
  501. FBOP BOP_DPMI,ResetLDTUserBase,FastBop
  502. ; Exec the child application
  503. SwitchToRealMode
  504. FSTI
  505. ;; bugbug hack ...... williamh
  506. ;; turn off A20 line before we terminate and keep resident.
  507. cmp A20EnableCount, 0
  508. jz A20IsOff
  509. @@:
  510. xmssvc 6
  511. dec A20EnableCount
  512. jnz @B
  513. A20IsOff:
  514. mov ax,segPSP
  515. mov es,ax
  516. assume es:nothing
  517. mov ax,es:[2ch]
  518. mov es,ax
  519. dossvc 49h ; free env block
  520. call DetermineFreeMemory
  521. mov dx,(offset CodeEnd) + 15
  522. shr dx,4
  523. add dx,FreeMem
  524. sub dx,bx
  525. add dx,segDXCode
  526. sub dx,segPSP
  527. mov al,0
  528. dossvc 31h ; tsr.
  529. help: int 3 ; should never get here
  530. jmp help
  531. lea bx, exec_par_blk
  532. lea dx, EXEC_PROGNAME
  533. xor al, al
  534. dossvc 4bh
  535. ; If we get here, the EXEC failed for some reason!
  536. mov bx,offset DXCODE:ER_REALMEM ;assume insufficient memory
  537. xchg ax,bx
  538. cmp bx,8 ;is it really?
  539. jz strt88
  540. mov ax,offset DXCODE:ER_DXINIT ;no, use generic msg
  541. strt88:
  542. mov ExitCode,1 ;return NZ exit code
  543. mov dx,cs ;pass msg ptr in DX:AX (ax already set)
  544. push cs ;fake a far call so no fixup
  545. push offset DXCODE:RealModeCleanUp ; needed -- return to clean up
  546. jmp near ptr DisplayErrorMsg
  547. ; -------------------------------------------------------
  548. ; ChildTerminationHandler -- This routine receives control
  549. ; when the child program running under the Dos Extender
  550. ; terminates. It will free all resources being used by
  551. ; the child. If we were not running TSR, then the Dos
  552. ; Extender will complete cleaning up and terminate itself.
  553. ;
  554. ; Input: none
  555. ; Output: none
  556. ; Errors: none
  557. ; Uses:
  558. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  559. public DosxTerminationHandler
  560. DosxTerminationHandler:
  561. mov ds,selDgroup
  562. mov es,selDgroup
  563. mov ss,selDgroup ;make sure we know where the
  564. mov sp,offset DGROUP:rgwStack ; stack is when we get here
  565. assume ds:DGROUP,es:DGROUP
  566. ; Check if we are already in the middle of a termination sequence and
  567. ; bail out if so. This will prevent us from hanging up in an infinite
  568. ; loop if we get a GP fault while we are quitting.
  569. cmp fQuitting,0
  570. jz @f
  571. jmp chtm90
  572. @@:
  573. mov fQuitting,1
  574. ; Terminate the OEM layer
  575. call TerminateOEM ;current term's NetBIOS mapper & low net heap
  576. ; Make sure that no interrupt vectors still point to us.
  577. call RestoreRMIntrVectors
  578. ; if this is a 80286 & 80287 configuration, we should reset the Co-Processor.
  579. cmp [f286_287],0 ;286 and 287 config ?
  580. jz CTH_Not286And287 ;no.
  581. ; reset the 80287 Co-Processor to make sure that it gets out of protected
  582. ; mode.
  583. xor al,al ;need to out 0
  584. out 0F1H,al ;reset the coprocessor
  585. CTH_Not286And287:
  586. ; If we're aborting due to a processor fault, do some extra clean-up on
  587. ; the mouse (just to be nice). If this is a normal termination, we leave
  588. ; it up to the child to save/restore the mouse state.
  589. test fFaultAbort,0FFh
  590. jz normal_exit
  591. ; Check if the mouse driver callback function has been set, and
  592. ; reset the mouse driver if so.
  593. mov ax,word ptr lpfnUserMouseHandler
  594. or ax,word ptr lpfnUserMouseHandler+2
  595. jz @F
  596. xor ax,ax
  597. int 33h
  598. @@:
  599. ; Check if the PS/2 Pointing Device Handler Address has been set and
  600. ; disable it if so.
  601. ifndef NEC_98
  602. mov ax,word ptr lpfnUserPointingHandler
  603. or ax,word ptr lpfnUserPointingHandler+2
  604. jz @f
  605. mov ax,0C200h
  606. xor bh,bh
  607. int 15h
  608. @@:
  609. endif ;!NEC_98
  610. ; Hmmm, we have HP mouse code in dxhpbios.asm, but no clean up here...
  611. normal_exit:
  612. ; Release the extended memory heap.
  613. ; call ReleaseXmemHeap
  614. ; Release the space being used for the descriptor tables and
  615. ; the protected mode code segment.
  616. ;
  617. ; If we have allocated an extended memory block, then free it.
  618. ; If we have allocated the HMA, then free it.
  619. ;
  620. mov dx,hmemDOSX
  621. or dx,dx
  622. jz @F
  623. xmssvc 0Dh
  624. xmssvc 0Ah
  625. @@:
  626. cmp fUsingHMA,0
  627. je @F
  628. xmssvc 2
  629. @@:
  630. ; Clean up after real mode code (and possible real mode incomplete
  631. ; initialization) -- restore real mode interrupt vectors.
  632. chtm90:
  633. RealModeCleanUp:
  634. ; Disable A20 if it was left enabled (normally 1 on 386 systems, 0 on 286)
  635. mov cx,A20EnableCount
  636. jcxz A20Okay
  637. @@: xmssvc 6
  638. loop @b
  639. A20Okay:
  640. ; Restore the MSW EM bit (Emulate Math coprocessor) to its initial state
  641. ifndef WOW_x86
  642. inc fEMbit ;if fEMbit = FF, we never got far 'nuff to
  643. jz @f ; change it
  644. dec fEMbit
  645. smsw ax
  646. test al,01h ;in V86 mode?
  647. jnz @f ; can't do the lmsw if so
  648. or al,fEMbit
  649. lmsw ax
  650. @@:
  651. endif
  652. ; Make sure DOS knows that the DOS extender is the current process
  653. mov bx,segPSP
  654. dossvc 50h
  655. ; Reenable a friendly EMM driver if we disabled it at startup
  656. call EMMEnable
  657. ; Restore real mode interrupt vectors
  658. push ds
  659. lds dx,PrevInt2FHandler ;Int 2Fh handler
  660. assume ds:NOTHING
  661. mov ax,ds ;may not have gotten far enough to
  662. or ax,dx ; set interrupt vectors, so make
  663. jz @f ; sure before resotring.
  664. mov ax,252Fh
  665. int 21h
  666. @@:
  667. pop ds
  668. assume ds:DGROUP
  669. ; We have cleaned up after ourselves, so now we can quit.
  670. mov ax,WIN386_EXIT ;use Win/386 exit Int 2Fh to tell any
  671. mov dx,WIN386_DOSX ; interested parties that we are
  672. int 2Fh ; terminating
  673. mov al,ExitCode ;exit the extender with either the exit
  674. cmp al,0FFH ; status from the child, or a status
  675. jnz @f ; that we have forced
  676. dossvc 4Dh ;get child exit status if we haven't forced it
  677. @@:
  678. ifdef NEC_98
  679. push ax
  680. push es ; Dec IN_BIOS(0:456)
  681. mov ax, 0040h
  682. mov es, ax
  683. test byte ptr es:[0], 20h ; check suspend/redume
  684. jz @f
  685. dec byte ptr es:[056h] ; for Y55
  686. @@:
  687. pop es
  688. pop ax
  689. endif ;NEC_98
  690. dossvc 4Ch ;say goodnight Gracy...
  691. ; -------------------------------------------------------
  692. ; ChildTerminationHandler --
  693. ; Input: none
  694. ; Output: none
  695. ; Errors: none
  696. ; Uses:
  697. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  698. public ChildTerminationHandler
  699. ChildTerminationHandler:
  700. sub sp,4 ; room for far ret
  701. push ds
  702. push es
  703. pusha
  704. mov si,ss
  705. mov di,sp
  706. mov ds,selDgroup
  707. mov es,selDgroup
  708. mov ss,selDgroup ;make sure we know where the
  709. mov sp,offset DGROUP:rgwStack ; stack is when we get here
  710. assume ds:DGROUP,es:DGROUP
  711. ;bugbug less than zero?
  712. dec cDPMIClients
  713. test DpmiFlags,DPMI_32BIT
  714. jz cth05
  715. ;
  716. ; Return the stack frame used by the Wow32Intr16 interrupt handler
  717. ;
  718. add pbReflStack,CB_STKFRAME
  719. cth05: cmp cDPMIClients,0
  720. jne cth20
  721. SwitchToProtectedMode
  722. mov dx, selPspChild
  723. mov cx, 0 ; No parent
  724. FBOP BOP_DPMI,TerminateApp,FastBop
  725. ;
  726. ; Reset the exception stack pointer to indicate free'd memory
  727. ;
  728. mov selEHStack,0
  729. ;
  730. ; Give back the xms memory
  731. ;
  732. FCLI
  733. call ReInitIdt
  734. push 0
  735. pop es
  736. call ReInitGdt
  737. FBOP BOP_DPMI,DpmiNoLongerInUse,FastBop
  738. SwitchToRealMode
  739. cth20: mov ax,[SegCurrentHostData]
  740. mov es,ax
  741. mov ax,es:[HdSegParent]
  742. mov [SegCurrentHostData],ax
  743. mov ax,es:[HdSelParent]
  744. mov [SelCurrentHostData],ax
  745. mov ax,es:[HdPSPParent]
  746. mov dx, selPspChild ; save outging psp in dx
  747. mov SelPSPChild,ax ; set new psp
  748. cmp CDPMIClients, 0
  749. je short @f
  750. push es ; We need to preserve es. The SwitchToRealMode
  751. ; somehow trashes es. (bug?)
  752. push dx
  753. push ax
  754. ; free xmem allocated to this client
  755. SwitchToProtectedMode
  756. pop cx
  757. pop dx
  758. FBOP BOP_DPMI,TerminateApp,FastBop
  759. SwitchToRealMode
  760. pop es
  761. @@:
  762. mov ax,word ptr es:[HdPspTerminate + 2]
  763. mov bx,word ptr es:[HdPspTerminate]
  764. mov cx,segPSPChild
  765. mov ds,cx
  766. assume ds:nothing
  767. ;
  768. ; Restore termination vector (app may think it knows what's here)
  769. ;
  770. mov ds:[0ah],bx
  771. mov ds:[0ch],ax
  772. xor cx,cx
  773. mov ds,cx
  774. ;
  775. ; Restore int 22 vector (terminate) Just in case
  776. ;
  777. mov ds:[22h * 4],bx
  778. mov ds:[22h * 4 + 2],ax
  779. mov es,si
  780. mov es:[di+20],bx
  781. mov es:[di+22],ax
  782. mov ss,si
  783. mov sp,di
  784. popa
  785. pop es
  786. pop ds
  787. retf
  788. ; -------------------------------------------------------
  789. ; DisplayErrorMsg -- Display an error message on the screen. We set the
  790. ; video adapter to a text mode so the msg is visable (and gets rid
  791. ; of any bizarre mode that others may have set (like WIN.COM)).
  792. ;
  793. ; Note: This routine can be executed in real OR protected mode, so
  794. ; don't do anything mode specific--keep is short and sweet.
  795. ;
  796. ; Input: AX - offset of msg to display
  797. ; DX - segment of msg to display
  798. ; Output: None.
  799. ; Uses: AX, DX modified, all else preserved
  800. assume ds:NOTHING, es:NOTHING
  801. public DisplayErrorMsg
  802. DisplayErrorMsg proc far
  803. push ds ;save current DS
  804. push ax ;save msg offset
  805. ; Set a text mode (normally 3, but possibly 7)
  806. ifdef NEC_98
  807. mov ah,41h ;
  808. int 18h
  809. mov ah,0Ch ;
  810. int 18h
  811. else ;!NEC_98
  812. mov ax,0003h ;set video mode 3
  813. int 10h
  814. mov ah,0Fh ;get video mode
  815. int 10h
  816. cmp al,03h ;did we change to 3?
  817. jz @f
  818. mov ax,0007h ;no, must be mode 7
  819. int 10h
  820. @@:
  821. endif ;!NEC_98
  822. ; Display the msg
  823. mov ds,dx
  824. pop dx
  825. dossvc 9
  826. pop ds
  827. ret
  828. DisplayErrorMsg endp
  829. ; -------------------------------------------------------
  830. ; DetermineFreeMemory -- Determine how much memory is free
  831. ;
  832. ; Input: none
  833. ; Output: bx = #paragraphs free memory
  834. ; Uses: bx
  835. ;
  836. assume ds:dgroup,es:nothing
  837. public DetermineFreeMemory
  838. DetermineFreeMemory proc near
  839. push ax
  840. mov bx,0ffffh ; allocate all of memory
  841. dossvc 48h
  842. jnc @f
  843. pop ax
  844. ret
  845. ;bugbug report error
  846. @@: mov bx,0ffffh
  847. pop ax
  848. ret
  849. DetermineFreeMemory endp
  850. EndLowSegment
  851. DXPMCODE segment
  852. assume cs:DXPMCODE
  853. ;--------------------------------------------------------
  854. ; ReInitIdt -- Set Idt entries back to default values
  855. ;
  856. ; Input: none
  857. ; Output: none
  858. ; uses: none
  859. ;
  860. assume ds:dgroup,es:nothing
  861. public ReInitIdt
  862. ReInitIdt proc near
  863. push bx
  864. push cx
  865. push dx
  866. push si
  867. push di
  868. push es
  869. mov ax,SEL_IDT OR STD_RING
  870. mov es,ax
  871. ; Fill the IDT with interrupt gates that point to the fault handler and
  872. ; interrupt reflector entry vector.
  873. xor di,di
  874. mov dx,offset DXPMCODE:PmIntrEntryVector
  875. mov cx,256
  876. iidt23: mov es:[di].offDest,dx
  877. mov es:[di].selDest,SEL_DXPMCODE or STD_RING
  878. mov es:[di].cwParam,0
  879. mov es:[di].arbGate,STD_TRAP ; BUGBUG- int gates not set up
  880. mov es:[di].rsvdGate,0
  881. add dx,5
  882. add di,8
  883. loop iidt23
  884. ; Now, fix up the ones that don't point to the interrupt reflector.
  885. IFDEF WOW_x86
  886. mov es:[1h*8].offDest,offset PMIntrIgnore
  887. mov es:[3h*8].offDest,offset PMIntrIgnore
  888. ifdef NEC_98
  889. mov es:[11h*8].offDest,offset PMIntr11dummy
  890. mov es:[18h*8].offDest,offset PMIntrVideo
  891. mov es:[1ah*8].offDest,offset PMIntrPrinter
  892. mov es:[1bh*8].offDest,offset PMIntr13
  893. mov es:[1ch*8].offDest,offset PMIntrCalTi
  894. mov es:[1dh*8].offDest,offset PMIntrGraph
  895. mov es:[1fh*8].offDest,offset PMIntrMisc
  896. else ;!NEC_98
  897. mov es:[10h*8].offDest,offset PMIntrVideo
  898. mov es:[13h*8].offDest,offset PMIntr13
  899. mov es:[15h*8].offDest,offset PMIntrMisc
  900. mov es:[19h*8].offDest,offset PMIntr19
  901. endif ;!NEC_98
  902. ENDIF
  903. mov es:[21h*8].offDest,offset DXPMCODE:PMIntrDos
  904. mov es:[25h*8].offDest,offset DXPMCODE:PMIntr25
  905. mov es:[26h*8].offDest,offset DXPMCODE:PMIntr26
  906. mov es:[28h*8].offDest,offset DXPMCODE:PMIntr28
  907. mov es:[30h*8].offDest,offset DXPMCODE:PMIntrIgnore
  908. mov es:[31h*8].offDest,offset DXPMCODE:PMIntr31
  909. mov es:[33h*8].offDest,offset DXPMCODE:PMIntrMouse
  910. mov es:[41h*8].offDest,offset DXPMCODE:PMIntrIgnore
  911. ifndef WOW_x86
  912. mov es:[4Bh*8].offDest,offset DXPMCODE:PMIntr4B
  913. ifdef NEC_98
  914. ; Sound BIOS Int D2h handler
  915. mov es:[0D2h*8].offDest,offset DXPMCODE:PMIntrSound
  916. ; extended DOS Int DCh handler (KANA/KANJI)
  917. mov es:[0DCh*8].offDest,offset DXPMCODE:PMIntrExDos
  918. endif ;!NEC_98
  919. endif
  920. ;
  921. ; Set up the IDT, and dpmi32 state
  922. ;
  923. mov ax,es ; Idt selector
  924. mov bx,VDM_INT_16
  925. DPMIBOP InitIDT
  926. mov ax,5 ; handler increment
  927. mov cx,SEL_DXPMCODE OR STD_RING
  928. mov dx,offset DXPMCODE:PmFaultEntryVector
  929. DPMIBOP InitExceptionHandlers
  930. IFDEF WOW_x86
  931. ; make the stacks 16 bit again
  932. cCall NSetSegmentAccess,<selDgroupPM,STD_DATA>
  933. cCall NSetSegmentAccess,<selEHStack,STD_DATA>
  934. ENDIF
  935. ; All done
  936. iidt90: pop es
  937. pop di
  938. pop si
  939. pop dx
  940. pop cx
  941. pop bx
  942. ret
  943. ReInitIdt endp
  944. assume ds:DGROUP,es:NOTHING
  945. public ReInitGdt
  946. ReInitGdt proc near
  947. push ax
  948. push cx
  949. push di
  950. mov ax,selGDT ; LDT selector
  951. lsl cx,ax ; LDT size
  952. mov di,SEL_USER and SELECTOR_INDEX
  953. DPMIBOP InitLDT
  954. pop di
  955. pop cx
  956. pop ax
  957. ret
  958. ReInitGdt endp
  959. ;--------------------------------------------------------
  960. ; AllocateExceptionStack -- Get space for exception handler
  961. ;
  962. ; Input: none
  963. ; Output: none
  964. ; carry set on error
  965. ; uses: AX, BX, CX, DX, SI, DI
  966. ;
  967. assume ds:dgroup,es:nothing
  968. public AllocateExceptionStack
  969. AllocateExceptionStack proc near
  970. cmp selEHStack, 0 ;have we allocated one already
  971. jnz aes_ok ;yes, return no carry
  972. xor bx,bx
  973. mov dx,bx
  974. mov cx,1000h ;length of block
  975. mov ax, 501h
  976. push ds
  977. FBOP BOP_DPMI, Int31Call, FastBop
  978. jc @F
  979. mov ax, SEL_USER_STACK or STD_RING
  980. mov selEHStack,ax
  981. cCall NSetSegmentDscr,<ax,bx,cx,0,0fffh,STD_DATA>
  982. mov ax,selEHStack
  983. mov cx,1000h ;reload length
  984. dec cx
  985. and cx,0fffeh ; Make sure SP is WORD aligned
  986. mov npEHStackLimit,cx
  987. ;; mark the stack with 0DEADh
  988. mov bx, cx
  989. push ds
  990. mov ds,ax
  991. sub bx,2
  992. mov word ptr [bx],0DEADh
  993. pop ds
  994. mov npEHStacklet, bx
  995. push es
  996. mov ax, selEHStack
  997. mov es, ax
  998. mov bx, npEHStackLimit
  999. DPMIBOP InitPmStackInfo
  1000. pop es
  1001. aes_ok:
  1002. clc
  1003. @@:
  1004. ret
  1005. AllocateExceptionStack endp
  1006. DXPMCODE ends
  1007. ;****************************************************************
  1008. end start