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.

2346 lines
80 KiB

  1. PAGE ,132
  2. TITLE DXMAIN.ASM -- Main Module for Dos Extender
  3. ; Copyright (c) Microsoft Corporation 1988-1991. All Rights Reserved.
  4. ;****************************************************************
  5. ;* *
  6. ;* DXMAIN.ASM - Dos Extender Main Module *
  7. ;* *
  8. ;****************************************************************
  9. ;* *
  10. ;* Module Description: *
  11. ;* *
  12. ;* This module contains the main routines for the Dos *
  13. ;* Extender. This is based on code written for Microsoft *
  14. ;* by Murray Sargent of Scroll Systems from Tucson Arizona. *
  15. ;* *
  16. ;* The Dos Extender provides support to allows specially *
  17. ;* written programs to run in protected mode mode on the *
  18. ;* 80286 and 80386 under MS-DOS. The following areas of *
  19. ;* support are provided to accomplish this: *
  20. ;* *
  21. ;* Program Loading and Initialization *
  22. ;* This involves creating a program segment prefix and *
  23. ;* then loading and relocating the exe file. When *
  24. ;* loading an exe for protected mode operation, it is *
  25. ;* necessary to create segment descriptors for all *
  26. ;* segments used by the program and to then substitute *
  27. ;* the corresponding selectors when fixing up the segment *
  28. ;* references in the code. *
  29. ;* *
  30. ;* Dos Function Call Support *
  31. ;* Since Dos must execute in real mode, it is necessary *
  32. ;* to perform mode switching into real mode and the back *
  33. ;* to protected mode when the application makes Dos calls. *
  34. ;* Also, any far pointers that are parameters to the *
  35. ;* function must be converted from the selector:offset *
  36. ;* form that the application uses to a segment:offset form *
  37. ;* that Dos can use, with the corresponding data being *
  38. ;* buffered from the application's extended memory address *
  39. ;* space to Dos's real mode address space. *
  40. ;* *
  41. ;* Other Interrupt Support *
  42. ;* Hardware interrupts are processed in real mode, and *
  43. ;* so the Dos Extender performs mode switching on each *
  44. ;* interrupt. Also other system resources (such as the *
  45. ;* mouse driver and the bios) are entered through software *
  46. ;* interrupts, and require the same kind of buffering *
  47. ;* and parameter translation that the Dos functions *
  48. ;* require. *
  49. ;* *
  50. ;* Extended Memory Management *
  51. ;* The protected mode application has access to the full *
  52. ;* address space of the machine, and a memory manager is *
  53. ;* provided that duplicates the functions of the Dos *
  54. ;* memory manager over the entire address space of the *
  55. ;* machine. *
  56. ;* *
  57. ;****************************************************************
  58. ;* Revision History: *
  59. ;* *
  60. ;* 08/08/90 earleh DOSX and Client privilege ring determined *
  61. ;* by equate in pmdefs.inc *
  62. ;* 03/23/90 davidw Added the reflecting of it 23h, ^C. *
  63. ;* 11/09/89 jimmat Added more IOCTL 0Dh support for Windows. *
  64. ;* 10/11/89 jimmat Changed hooking of Int 1,2,3 under a *
  65. ;* debugger to work better with CVW. *
  66. ;* 07/28/89 jimmat Fixed Int 21h/56h (Rename), fixed Int 21 *
  67. ;* calls that just returned a pointer. *
  68. ;* 06/07/89 jimmat Fixed length of FCB moves and special *
  69. ;* case hooking Int 1Eh. *
  70. ;* 05/30/89 jimmat Completed Int 21h/5Ah processing. *
  71. ;* 04/25/89 jimmat Added support for undocumented INT 21h *
  72. ;* 5Fh/05 DOS call. *
  73. ;* 04/12/89 jimmat Allow one level of nested DOS calls to *
  74. ;* support PM critical error handlers *
  75. ;* 04/10/89 jimmat Supported INT 21h/5Eh & 5Fh--also small *
  76. ;* clean-up of the dosentry/dosexit code. *
  77. ;* 04/05/89 jimmat Fixed MOVDAT FCB length check. *
  78. ;* 04/04/89 jimmat Stop reflecting real mode software ints *
  79. ;* to protect mode. This is how Windows/386 *
  80. ;* works, and it fixes a problem with DOS *
  81. ;* networks since the real mode redirector *
  82. ;* expects to have access to the DOS stack, *
  83. ;* not a DOS extender interrupt stack frame. *
  84. ;* 03/28/89 jimmat Incorporated bug fixes from GeneA *
  85. ;* 03/17/89 jimmat Some code clean-up and debugging checks *
  86. ;* 03/15/89 jimmat Minor changes to run child in ring 1 *
  87. ;* 02/22/89 (GeneA): removed dead code and data left over *
  88. ;* from the Murray Sargent/SST days. *
  89. ;* 02/22/89 (GeneA): moved handlers for all interrupts but *
  90. ;* Int 21h to DXINTR.ASM. Fixed problem with re-entrancy *
  91. ;* caused when the other interrupts were executed while *
  92. ;* in DOS. (int 15h was causing the specific problem). *
  93. ;* 02/14/89 (GeneA): fixed bug in IntExitMisc. Was storing *
  94. ;* return value in rmrg.xes, changed to pmrg.xes. *
  95. ;* 02/10/89 (GeneA): changed Dos Extender from small model to *
  96. ;* medium model. *
  97. ;* 12/01/88 (GeneA): Changed name of mentry and mexit to *
  98. ;* IntEntryMouse and IntExitMouse. Added functions *
  99. ;* IntEntryMisc and IntExitMisc to handle entry and *
  100. ;* exit processing for BIOS INT 15h. *
  101. ;* 11/20/88 (GeneA): modified DFSetVector so that is checks to *
  102. ;* see if a vector has already been hooked before saving *
  103. ;* the old value in the real mode interrupt vector shadow *
  104. ;* buffer. *
  105. ;* 09/15/88 (GeneA): created by extracting code from the *
  106. ;* SST debugger modules DOSXTND.ASM, VIRTMD.ASM, *
  107. ;* VRTUTIL.ASM, and INTERRPT.ASM *
  108. ;* *
  109. ;****************************************************************
  110. .286p
  111. .287
  112. ; -------------------------------------------------------
  113. ; INCLUDE FILE DEFINITIONS
  114. ; -------------------------------------------------------
  115. .xlist
  116. .sall
  117. include segdefs.inc
  118. include gendefs.inc
  119. include pmdefs.inc
  120. include intmac.inc
  121. include bop.inc
  122. include dpmi.inc
  123. include hostdata.inc
  124. .list
  125. ; -------------------------------------------------------
  126. ; GENERAL SYMBOL DEFINITIONS
  127. ; -------------------------------------------------------
  128. ; STKSTR -- stack layout structure for user registers in the pmrg and
  129. ; rmrg arrays in the data segment DXDATA. pmrg is an exact replica of the pm
  130. ; user registers on entry to the Dos Extender (DE). rmrg is a translated
  131. ; version used to communicate with the real-mode world. The rmrg array is
  132. ; initially set equal to the pm user values by the instructions push ds, push
  133. ; es, pusha. The pmrg array es and ds are inevitably set equal to the pm user
  134. ; values and its general register values are defined if data translations may be
  135. ; required (int-10/21).
  136. stkstr struc ;Level-0 Stack structure. bp is set = sp here
  137. xdi dw ?
  138. xsi dw ?
  139. xbp dw ?
  140. xasp dw ? ;Alternate sp
  141. xbx dw ?
  142. xdx dw ?
  143. xcx dw ?
  144. xax dw ? ;pusha pushes xax to xdi
  145. xes dw ?
  146. xds dw ?
  147. stkstr ends
  148. ; -------------------------------------------------------
  149. ; This structure describes the EXEC parameter block used
  150. ; by MS-DOS function 4Bh.
  151. execblk struc ;INT-21 ah=4bh EXEC parameter block
  152. evrnmt dw ? ;Paragraph of environment string to be passed
  153. cmdptr dd ? ;Ptr to command line to be placed at PSP+80h
  154. fcb1ptr dd ? ;Ptr to default FCB to be passed at PSP+5ch
  155. fcb2ptr dd ? ;Ptr to default FCB to be passed at PSP+6ch
  156. xsssp dd ? ;Initial program stack ss:sp
  157. xcsip dd ? ;Program entry point cs:ip
  158. execblk ends
  159. ; -------------------------------------------------------
  160. ; EXTERNAL SYMBOL DEFINITIONS
  161. ; -------------------------------------------------------
  162. extrn gtpara:NEAR
  163. extrn GetSegmentAddress:NEAR
  164. extrn EnterRealMode:NEAR
  165. extrn EnterProtectedMode:NEAR
  166. extrn SelOff2SegOff:NEAR
  167. extrn ParaToLDTSelector:NEAR
  168. extrn NSetSegmentDscr:FAR
  169. extrn ChildTerminationHandler:NEAR
  170. ; -------------------------------------------------------
  171. ; DATA SEGMENT DEFINITIONS
  172. ; -------------------------------------------------------
  173. DXDATA segment
  174. extrn selGDT:WORD
  175. extrn segPSPChild:WORD
  176. extrn npXfrBuf1:WORD
  177. extrn rgbXfrBuf0:BYTE
  178. IFDEF WOW_x86
  179. extrn FastBop:FWORD
  180. ENDIF
  181. extrn segDXCode:word
  182. extrn segCurrentHostData:word
  183. ; -------------------------------------------------------
  184. ; General DOS EXTENDER Variables
  185. ; -------------------------------------------------------
  186. pmdta dw 2 dup(?) ;PM DTA. Used for getting dir info
  187. EntryFlag db -1 ;Flag to check for nested DOS interrupts
  188. rcount dw ? ;Remaining requested file byte count to read/write
  189. ccount dw ? ;Current count of total read/written
  190. ;=======================================================================
  191. ;Keep from here thru Iend in the following order:
  192. align 2
  193. Ibegin label byte ;start of PMIntrDos nested 'Instance' data
  194. dw 128 dup(?) ;Extra stack for real mode
  195. rmrg stkstr <> ;Corresponding real-mode set
  196. rmivip dw ? ;Real-mode interrupt-vector offset
  197. rmivcs dw ? ;Real-mode interrupt-vector segment
  198. rmivfl dw ? ;Real-mode interrupt flags to be used
  199. rmroff dw ? ;Real-mode return address offset
  200. rmrseg dw ? ;Real-mode return address segment
  201. rmflags dw ? ;flags
  202. pmrg stkstr <> ;Protected-mode user registers
  203. public pmusrss, pmusrsp
  204. pmusrsp dw ? ;PM user sp
  205. pmusrss dw ? ;PM user ss
  206. enxseg dw ? ;transfer segment used on dos function exit
  207. Iend label byte ;end of PMIntrDos nested 'Instance' data
  208. ;=======================================================================
  209. ILENGTH equ Iend - Ibegin ;length of instance data
  210. Isave db ILENGTH dup (?) ;instance data save area
  211. DXDATA ends
  212. ; -------------------------------------------------------
  213. ; CODE SEGMENT VARIABLES
  214. ; -------------------------------------------------------
  215. DXCODE segment
  216. extrn segDXData:WORD
  217. extrn selDgroup:WORD
  218. DXCODE ends
  219. DXPMCODE segment
  220. extrn selDgroupPM:WORD
  221. extrn segDXCodePM:WORD
  222. extrn segDXDataPM:WORD
  223. ; -------------------------------------------------------
  224. ; Dos Function Parameter Tables
  225. ; -------------------------------------------------------
  226. ; The Dos Extender provides parameter buffering and translation
  227. ; on entry to and exit from Dos system calls. The following table
  228. ; is used to describe the operations to be performed for this process.
  229. ; The basic idea is that there is an entry parameter code and an
  230. ; exit paramter code. This code describes whether any data buffering
  231. ; is necessary. If buffering is necessary, it describes the nature of
  232. ; the data being transferred (e.g. ASCIIZ string, FCB, etc.) which is
  233. ; used to determine the transfer length. The entry/exit code also
  234. ; describes which temporary buffer to use for the transfer, and which
  235. ; user register (e.g. DS:DX, ES:BX, etc) points to the data to transfer.
  236. ;
  237. ; The data transfers described by this table is sufficient to handle
  238. ; the majority of the Dos system calls. However, any Dos call which
  239. ; requires the transfer of more than one buffer of data, or which requires
  240. ; that additional processing be performed other than simply copying a
  241. ; buffer is handled with special case code.
  242. ; The following symbols define various parts of the entry/exit codes
  243. ; used in the parameter table.
  244. ; Nibble 0 of a transfer word is a code that specifies the length of the
  245. ; transfer as follows:
  246. ; 0 no xfer
  247. ; 1 FCB to/from (f,10,11,12,13,16,17,23,24,29
  248. ; 2 PTR$ from (1b,1c,34)
  249. ; 3 ASCZ to/from (39,3a,3b,3c,3d,41,43,4b,4e,56
  250. ; 5a,5b)
  251. ; 4 DOLLAR terminated to DOS (9)
  252. ; 5 AX$ from (3f)
  253. ; 6 CX$ to/from (3f,40,44)
  254. ; 7 KEYBUF to/from DOS (a)
  255. ; 8 Country INFO (34) to/from (38)
  256. ; 9 EXTERR (22) to (5d)
  257. ; a DIRectory (64) from (47)
  258. ; b EXEC parm (14) to (4b)
  259. ; c file MATCH (43) to/from (4e,4f)
  260. ; d CMND line (128) to (29)
  261. ; e PALETTE (17) to (int-10/1002)
  262. ; f VBIOS (64) from (int-10/1b)
  263. ;
  264. ;
  265. ; Nibble 1 specifies the segment value transferred as follows (DOS entries
  266. ; affected are listed in parentheses):
  267. ;
  268. ; Segment ptr
  269. ;
  270. ; 0 none
  271. ; 1 ds:dx to/from DOS (9,a,f,10,11,12,13,14,16,17,21,22,23,24,25,27
  272. ; 28,39,3a,3b,3c,3d,3f,40,41,43,44,4b,4e,4f,56
  273. ; 5a,5b)
  274. ; 2 DTA to/from (11,12,14,15,21,22,27,28,4e)
  275. ; 3 ds:bx from (1b,1c) (Allocation table info)
  276. ; 4 ds:si to/from (29,47) (Parse FN, get dir)
  277. ; 5 es:di to/from (29,56) (Parse FN, rename)
  278. ; 6 es:bx to/from (2f,35,4b) (Get DTA, intvct, EXEC)
  279. ; 7 es to (49,4a) (RAM allocation)
  280. ;
  281. ; Byte 1 (high byte) on has meanings:
  282. ;
  283. ; bit 0 = 1 (A0) use small data area 0 (limited to 60h bytes)
  284. ; bit 1 = 1 (A1) use large area 1 (4K)
  285. ; bit 2 = 1 (RP) Real/Protect mode transfer needed (for int 21 ah = 3f/40)
  286. ; bit 7 = 1/0 (EX) exitcd/entrycd
  287. entrycd record EnArea:4,EnSegCod:4,EnLenCod:4
  288. exitcd record ExArea:8,ExSegCod:4,ExLenCod:4
  289. ;Length codes:
  290. FCB equ 1
  291. PTR$ equ 2 ;only supports DSBX & ESBX for now (and DSSI if DBCS)
  292. ASCZ equ 3
  293. DOL equ 4
  294. AX$ equ 5
  295. CX$ equ 6
  296. KYB equ 7
  297. INFO equ 8 ;Constant length transfers from here down vvvvvvvv
  298. EXTERR equ 9
  299. DIR equ 0Ah
  300. EXEC equ 0Bh
  301. MTCH equ 0Ch
  302. CMD equ 0Dh
  303. PALETTE equ 0Eh
  304. VBIOS equ 0Fh ;Constant length transfers from here up ^^^^^^^^^^
  305. ;Segment codes:
  306. DSDX equ 1
  307. DTA equ 2
  308. DSBX equ 3
  309. DSSI equ 4
  310. ESDI equ 5 ;Also used by int-10/ah=1bh
  311. ESBX equ 6 ;Also used by int-10/ah=1ch
  312. ES$ equ 7
  313. ESDX equ 8 ;Used by int-10/ah=10,12, int-33/ah=22,23
  314. ESBP equ 9 ;Used by int-10/ah=11,13
  315. ;RAM area codes:
  316. A0 equ 1
  317. A1 equ 2
  318. RP equ 4
  319. EX equ 80h
  320. pmrmxfr entrycd <> ;0 - Program Terminate
  321. exitcd <>
  322. entrycd <> ;1 - Keyboard Input
  323. exitcd <>
  324. entrycd <> ;2 - Display output
  325. exitcd <>
  326. entrycd <> ;3 - Auxiliary Input
  327. exitcd <>
  328. entrycd <> ;4 - Auxiliary Output
  329. exitcd <>
  330. entrycd <> ;5 - Printer Output
  331. exitcd <>
  332. entrycd <> ;6 - Direct Console I/O
  333. exitcd <>
  334. entrycd <> ;7 - Direct Console Input Without Echo
  335. exitcd <>
  336. entrycd <> ;8 - Console Input Without Echo
  337. exitcd <>
  338. entrycd <A1,DSDX,DOL> ;9 - Print string
  339. exitcd <>
  340. entrycd <A1,DSDX,KYB> ;0A - Buffered Keyboard Input
  341. exitcd <EX+A0,DSDX,KYB>
  342. entrycd <> ;0B - Check Standard Input Status
  343. exitcd <>
  344. entrycd <> ;0C - Clear Kbd Buffer and Invoke Kbd Function
  345. exitcd <>
  346. entrycd <> ;0D - Disk Reset
  347. exitcd <>
  348. entrycd <> ;0E - Select Disk
  349. exitcd <>
  350. entrycd <> ;0F - Open File ** Unsupported! **
  351. exitcd <>
  352. entrycd <> ;10 - Close File ** Unsupported! **
  353. exitcd <>
  354. entrycd <A0,DSDX,FCB> ;11 - Search for First Entry
  355. exitcd <EX+A1,DTA,FCB>
  356. entrycd <A0,DSDX,FCB> ;12 - Search for Next Entry
  357. exitcd <EX+A1,DTA,FCB>
  358. entrycd <A0,DSDX,FCB> ;13 - Delete File
  359. exitcd <>
  360. entrycd <> ;14 - Sequential Read ** Unsupported! **
  361. exitcd <>
  362. entrycd <> ;15 - Sequential Write ** Unsupported! **
  363. exitcd <>
  364. entrycd <> ;16 - Create File ** Unsupported! **
  365. exitcd <>
  366. entrycd <A0,DSDX,FCB> ;17 - Rename File
  367. exitcd <>
  368. entrycd <> ;18 - Used Internally by DOS
  369. exitcd <>
  370. entrycd <> ;19 - Current Disk
  371. exitcd <>
  372. entrycd <A1,DSDX,> ;1A - Set Disk Transfer Address
  373. exitcd <>
  374. entrycd <> ;1B - Allocation Table Info
  375. exitcd <,DSBX,PTR$>
  376. entrycd <> ;1C - Alloc Table Info for Specific Device
  377. exitcd <,DSBX,PTR$>
  378. entrycd <> ;1D - Used Internally by DOS
  379. exitcd <>
  380. entrycd <> ;1E - Used Internally by DOS
  381. exitcd <>
  382. entrycd <> ;1F - Used Internally by DOS
  383. exitcd <>
  384. entrycd <> ;20 - Used Internally by DOS
  385. exitcd <>
  386. entrycd <> ;21 - Random Read ** Unsupported! **
  387. exitcd <>
  388. entrycd <> ;22 - Random Write ** Unsupported! **
  389. exitcd <>
  390. entrycd <> ;23 - File Size ** Unsupported! **
  391. exitcd <>
  392. entrycd <> ;24 - Set Relative Record Field ** Unsupported! **
  393. exitcd <>
  394. entrycd <,DSDX,> ;25 - Set Interrupt Vector (0/ds:dx/0)
  395. exitcd <>
  396. entrycd <,DSDX,> ;26 - Create new PSP
  397. exitcd <>
  398. entrycd <> ;27 - Random Block Read ** Unsupported! **
  399. exitcd <>
  400. entrycd <> ;28 - Random Block Write ** Unsupported! **
  401. exitcd <>
  402. entrycd <A0,DSSI,ASCZ> ;29 - Parse Filename
  403. exitcd <EX+A1,ESDI,FCB>
  404. entrycd <> ;2A - Get Date
  405. exitcd <>
  406. entrycd <> ;2B - Set Date
  407. exitcd <>
  408. entrycd <> ;2C - Get Time
  409. exitcd <>
  410. entrycd <> ;2D - Set Time
  411. exitcd <>
  412. entrycd <> ;2E - Set/Reset Verify Switch
  413. exitcd <>
  414. entrycd <> ;2F - Get Disk Transfer Address
  415. exitcd <EX+A0,ESBX,>
  416. entrycd <> ;30 - Get DOS Version Number
  417. exitcd <>
  418. entrycd <> ;31 - Terminate and Stay Resident
  419. exitcd <>
  420. entrycd <> ;32 - Get Drive Parameter Block
  421. exitcd <,DSBX,PTR$>
  422. entrycd <> ;33 - Ctrl-Break Check
  423. exitcd <>
  424. entrycd <> ;34 - Get InDOS flag address
  425. exitcd <,ESBX,PTR$>
  426. entrycd <> ;35 - Get Interrupt Vector
  427. exitcd <EX,ESBX,>
  428. entrycd <> ;36 - Get Disk Free Space
  429. exitcd <>
  430. entrycd <> ;37 - Used Internally by DOS
  431. exitcd <>
  432. entrycd <A1,DSDX,> ;38 - Set/Get Country Dependent Info
  433. exitcd <EX+A1,DSDX,INFO>
  434. entrycd <A0,DSDX,ASCZ> ;39 - MKDIR
  435. exitcd <>
  436. entrycd <A0,DSDX,ASCZ> ;3A - RMDIR
  437. exitcd <>
  438. entrycd <A0,DSDX,ASCZ> ;3B - CHDIR
  439. exitcd <>
  440. entrycd <A0,DSDX,ASCZ> ;3C - Create a File
  441. exitcd <>
  442. entrycd <A0,DSDX,ASCZ> ;3D - Open a File
  443. exitcd <>
  444. entrycd <> ;3E - Close a File Handle
  445. exitcd <>
  446. entrycd <RP,DSDX,> ;3F - Read from a File or Device
  447. exitcd <EX+RP,DSDX,AX$>
  448. entrycd <RP,DSDX,CX$> ;40 - Write to a File or Device
  449. exitcd <>
  450. entrycd <A0,DSDX,ASCZ> ;41 - Delete a File from a Specified Directory
  451. exitcd <>
  452. entrycd <> ;42 - Move File Read/Write Pointer
  453. exitcd <>
  454. entrycd <A0,DSDX,ASCZ> ;43 - Change File Mode
  455. exitcd <>
  456. entrycd <> ;44 - I/O Control for Devices
  457. exitcd <> ;See ioctlw for write
  458. entrycd <> ;45 - Duplicate a File Handle
  459. exitcd <>
  460. entrycd <> ;46 - Force a Duplicate of a File Handle
  461. exitcd <>
  462. entrycd <A0,DSSI,> ;47 - Get Current Directory
  463. exitcd <EX+A0,DSSI,ASCZ>
  464. entrycd <> ;48 - Allocate Memory
  465. exitcd <>
  466. entrycd <,ES$,> ;49 - Free Allocated Memory
  467. exitcd <>
  468. entrycd <,ES$,> ;4A - Modify Allocated Memory Blocks
  469. exitcd <>
  470. entrycd <A0,DSDX,ASCZ> ;4B - Load or Execute a Program (EXEC)
  471. exitcd <>
  472. entrycd <> ;4C - Terminate a Process
  473. exitcd <>
  474. entrycd <> ;4D - Get Return Code of a Sub-process
  475. exitcd <>
  476. entrycd <A0,DSDX,ASCZ> ;4E - Find First Matching File
  477. exitcd <EX+A1,DTA, MTCH>
  478. entrycd <A1,DTA,MTCH> ;4F - Find Next Matching File
  479. exitcd <EX+A1,DTA, MTCH>
  480. entrycd <,ESBX,> ;50 - Set current PSP (code restores bx)
  481. exitcd <>
  482. entrycd <> ;51 - Get current PSP
  483. exitcd <>
  484. entrycd <> ;52 - Get Pointer to SysInit Variables
  485. exitcd <,ESBX,PTR$>
  486. entrycd <A1,DSSI,DIR> ;53 - Set Drive Parameter Block
  487. exitcd <>
  488. entrycd <> ;54 - Get Verify Setting
  489. exitcd <>
  490. entrycd <,DSDX,> ;55 - Duplicate PSP
  491. exitcd <>
  492. entrycd <A0,DSDX,ASCZ> ;56 - Rename a File
  493. exitcd <>
  494. entrycd <> ;57 - Get/Set a File's Date and Time
  495. exitcd <>
  496. entrycd <> ;58 - Get/Set Allocation Strategy
  497. exitcd <>
  498. entrycd <> ;59 - Get Extended Error
  499. exitcd <>
  500. entrycd <A0,DSDX,ASCZ> ;5A - Create Temporary File
  501. exitcd <EX+A0,DSDX,ASCZ>
  502. entrycd <A0,DSDX,ASCZ> ;5B - Create New File
  503. exitcd <>
  504. entrycd <> ;5C - Lock/Unlock File Access
  505. exitcd <>
  506. entrycd <A0,DSDX,EXTERR> ;5D - Used Internally by DOS
  507. exitcd <>
  508. entrycd <> ;5E - Network Machine Name/Printer Setup
  509. exitcd <>
  510. entrycd <> ;5F - Get/Make Assign-List Entry
  511. exitcd <>
  512. entrycd <> ;60 - Used Internally by DOS
  513. exitcd <>
  514. entrycd <> ;61 - Used Internally by DOS
  515. exitcd <>
  516. entrycd <> ;62 - Get PSP Address
  517. exitcd <>
  518. entrycd <> ;63 - Get Lead Byte Table ** Unsupported! **
  519. exitcd <>
  520. entrycd <> ;64 - Used Internally by DOS
  521. exitcd <>
  522. entrycd <> ;65 - Get Extended Country Info
  523. exitcd <EX+A1,ESDI,CX$>; ** Only Partially Supported **
  524. entrycd <> ;66 - Get/Set Code Page
  525. exitcd <>
  526. entrycd <> ;67 - Set Handle Count
  527. exitcd <>
  528. entrycd <> ;68 - Commit File
  529. exitcd <>
  530. entrycd <> ;69 - Used Internally by DOS
  531. exitcd <>
  532. entrycd <> ;6A - Used Internally by DOS
  533. exitcd <>
  534. entrycd <> ;6B - Used Internally by DOS
  535. exitcd <>
  536. entrycd <A0,DSSI,ASCZ> ;6C - Extended Open File
  537. exitcd <>
  538. MaxInt21 equ 06Ch ;max supported Int 21h function
  539. UnSupported entrycd <> ;for unsupported DOS calls
  540. exitcd <>
  541. if DEBUG ;------------------------------------------------------------
  542. ; Table of partially supported/unsupported/unknown Int 21h functions
  543. ifdef DBCS
  544. tblBad21 db 18h,1Dh,1Eh,1Fh,20h,37h,5Dh,60h,61h
  545. db 64h,65h,6Ah,6Bh,0
  546. else
  547. tblBad21 db 18h,1Dh,1Eh,1Fh,20h,37h,5Dh,60h,61h,63h
  548. db 64h,65h,6Ah,6Bh,0
  549. endif
  550. endif ;DEBUG --------------------------------------------------------
  551. ;
  552. ; For compatibility with WIN386, the following FCB calls are failed
  553. ; unconditionally.
  554. ;
  555. MIN_REAL_BAD_21 equ 0fh
  556. MAX_REAL_BAD_21 equ 28h
  557. tblRealBad21 db 0fh,10h,14h,15h,16h,21h,22h,23h,24h,27h,28h,0
  558. ; Special codes for special INT 21h functions
  559. int215E entrycd <A0,DSDX,> ;5E/00 - Get Machine Name
  560. exitcd <EX+A0,DSDX,ASCZ>
  561. entrycd <A0,DSDX,ASCZ> ;5E/01 - Set Machine name
  562. exitcd <>
  563. entrycd <A0,DSSI,CX$> ;5E/02 - Set Printer Setup Str
  564. exitcd <>
  565. entrycd <A0,ESDI,> ;5E/03 - Get Printer Setup Str
  566. exitcd <EX+A0,ESDI,CX$>
  567. int215F02 entrycd <A0,DSSI> ;5F/02 - Get Redir List Entry
  568. exitcd <EX+A0,DSSI,ASCZ>
  569. entrycd <A0,DSSI,ASCZ> ;5F/03 - Set Redir List Entry
  570. exitcd <>
  571. entrycd <A0,DSSI,ASCZ> ;5F/04 - Cancel Redirection
  572. exitcd <>
  573. entrycd <A0,DSSI> ;5F/05 - Get Redir List Entry
  574. exitcd <EX+A0,DSSI,ASCZ>
  575. ifdef DBCS
  576. int2163 entrycd <> ;63/00 - Get Lead Byte Table Entry
  577. exitcd <,DSSI,PTR$>
  578. endif ; DBCS
  579. int21esdi entrycd <A1,ESDI,ASCZ> ;56 & 5F/02&03&05 eXtra buffer
  580. exitcd <EX+A1,ESDI,ASCZ>
  581. ;
  582. ; We only use the entry code from the following. If we don't
  583. ; we trash the stack in applications like borland c++
  584. ;
  585. int21pfn entrycd <A1,ESDI,FCB> ;29, fcb buffer
  586. exitcd <>
  587. ; Additional tables for run time support associated with register
  588. ; translation and buffering.
  589. ; 8 9 a b c d e f
  590. ; INFO EXTERR DIR EXEC MATCH CMND PALETTE VBIOS
  591. mvcnt db 34, 22, 40h, 0Eh, 43, 80h, 17, 64
  592. ; 1 2 3 4 5 6 7 8 9
  593. ; DSDX, DTA, DSBX, DSSI, ESDI, ESBX, ES$, esdx, esbp
  594. regoffs dw xdx, 0, xbx, xsi, xdi, xbx, 0, xdx, xbp
  595. DXPMCODE ends
  596. ; -------------------------------------------------------
  597. subttl Main Program
  598. page
  599. ; -------------------------------------------------------
  600. ; MAIN PROGRAM
  601. ; -------------------------------------------------------
  602. DXPMCODE segment
  603. assume cs:DXPMCODE
  604. ; -------------------------------------------------------
  605. ; PMIntrDos -- This function is the main handler for int 21h calls
  606. ; that require special case processing. Most interrupts
  607. ; go through the interrupt reflector (PMIntrReflector in
  608. ; dxintr.asm). DOS int 21h interrupts are vectored here.
  609. ;
  610. ; This routine performs any register manipulation, data buffering
  611. ; etc. needed to pass the interrupt parameters from the
  612. ; protected mode caller to the real mode handler. Register
  613. ; manipulation and data transfers can occur either on entry
  614. ; to the interrupt handler or on exit from the interrupt
  615. ; handler (to fix up return values.)
  616. ;
  617. ; Input: normal registers for Dos calls
  618. ; Output: normal register returns for Dos calls
  619. ; Errors: normal Dos errors
  620. ; Uses: In general, all registers are preserved. For interrupts where
  621. ; register translation or buffering occurs, some registers may
  622. ; be changed, depending on the interrupt and its parameters.
  623. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  624. public PMIntrDos
  625. PMIntrDos proc far
  626. push ds
  627. push ax
  628. mov ax,SEL_DXDATA OR STD_RING
  629. mov ds,ax
  630. assume ds:DGROUP
  631. mov ax,ss
  632. mov pmusrss,ax
  633. mov ax,sp
  634. add ax,4
  635. mov pmusrsp,ax
  636. pop ax
  637. FBOP BOP_DPMI,XlatInt21Call,FastBop
  638. ; If we get here, the api wasn't translated. The translation code will
  639. ; simulate the iret
  640. assume ds:nothing
  641. NotXlated:
  642. cld ;Code assumes direction flag is cleared
  643. ; Save PM user ds, es, and flags, and switch to DOS extender stack
  644. push ax ;Save caller's AX
  645. push bp
  646. mov bp,sp ;[bp] = bp ax ip cs fl - 286 int gates assumed
  647. ; 0 2 4 6 8
  648. push es
  649. mov es,selDgroupPM ;Address our DGROUP
  650. assume es:DGROUP
  651. ; Check for nested DOS interrupts--this code was written with the assumption
  652. ; that we would never be reentered, but it turns out that we may need to
  653. ; support nested DOS calls from a critical error handler. If this is one
  654. ; of those ultra-rare occasions, save our previous 'instance' data in Isave.
  655. inc EntryFlag ;The normal case will be to jump
  656. jz @f
  657. push cx ;Being reentered, save last instance data
  658. push di
  659. push si
  660. mov cx,ILENGTH ;NOTE!!! The next movs has
  661. mov si,offset DGROUP:Ibegin ; an es override, if ints
  662. mov di,offset DGROUP:Isave ; are enabled, an interrupt
  663. rep movs byte ptr [di],byte ptr es:[si] ; on this instr can 'forget'
  664. ; about the es override with
  665. pop si ; some processors
  666. pop di
  667. pop cx
  668. @@:
  669. ; Start saving callers state.
  670. mov pmrg.xds,ds ;Save PM user ds
  671. mov ax,[bp+8] ;Get ax = flags when int occurred
  672. mov rmflags,ax ;Store flags for real-mode handler
  673. pop pmrg.xes ;Save PM user es
  674. pop bp
  675. pop ax ;Recover user ax. [sp] = ip cs fl
  676. ; At this point all general registers (but not ES) have the user's values
  677. push es ;Address DGROUP, user's DS already
  678. pop ds ; saved in pmrg.xds
  679. assume ds:DGROUP
  680. mov pmusrss,ss ;Save PM user stack ptr
  681. mov pmusrsp,sp ;[sp] = ds ip cs fl
  682. ; 0 2 4 6
  683. mov pmrg.xsi,si ;Save PM si since need to use before pusha
  684. push ds ;Switch to rmrg stack for this routine
  685. pop ss
  686. mov sp,offset DGROUP:rmflags ;PM flags already on stack
  687. FSTI ;We don't really need interrupts disabled
  688. ; Setup iret frames for iret'ing to real-mode handler and for that handler
  689. ; returning to the DOS extender
  690. pop si ;Get rmflags
  691. and si,not 4100h ;Kill NT, TF
  692. push si ;Push flags for iret to BackFromDOS
  693. push segDXCodePM ;Push return cs:ip for iret
  694. push offset BackFromDOS
  695. and si,not 0200h ;Kill IF
  696. push si ;Push flags for iret to real-mode handler
  697. sub sp,4 ; make room for stack frame
  698. push bp
  699. mov bp,sp
  700. push es
  701. push ax
  702. mov ax,SEL_RMIVT OR STD_RING
  703. mov es,ax
  704. mov ax,es:[21h*4]
  705. mov [bp + 2],ax
  706. mov ax,es:[21h*4 + 2]
  707. mov [bp + 4],ax
  708. pop ax
  709. pop es
  710. pop bp
  711. ; Setup protected mode and real mode copies of registers.
  712. mov si,pmrg.xsi ;Restore si
  713. push ds ;Save space for real mode ds
  714. push es ; and es
  715. pusha ;Save user general registers
  716. mov si,offset DGROUP:rmrg ;Copy user values to PM set for
  717. mov di,offset DGROUP:pmrg ; reference (real-mode set may change)
  718. mov cx,8 ;8 general registers (es and ds already stored)
  719. rep movsw
  720. mov ax,segDXDataPM ;ax = DOS extender real-mode dgroup segment
  721. mov rmrg.xds,ax ;Default real-mode data segments
  722. mov rmrg.xes,ax ; (dosentry may change them)
  723. mov ax,rmrg.xax
  724. if DEBUG ;------------------------------------------------------------
  725. ; Check for partially supported/unsupported/unknown DOS calls
  726. cmp ah,0DCh ;krnl286 is doing this now, quit
  727. jz goodfunc ; complaining about it
  728. cmp ax,5D0Ah ;Set Extended Error is the only
  729. jz goodfunc ;5Dh function handled properly!
  730. cmp ah,MaxInt21 ;is the request within our range?
  731. ja badfunc
  732. mov bx,offset DXPMCODE:tblBad21
  733. @@:
  734. cmp ah,cs:[bx]
  735. jb goodfunc
  736. jz badfunc
  737. inc bx
  738. jmp short @b
  739. badfunc: Trace_Out "Possible Unsupported DOS Call! AX=#AX"
  740. goodfunc:
  741. endif ;DEBUG --------------------------------------------------------
  742. ; Check for FCB calls that we fail unconditionally (because WIN386 does.)
  743. cmp ah,MIN_REAL_BAD_21
  744. jb goodfunc1
  745. cmp ah,MAX_REAL_BAD_21
  746. ja goodfunc1
  747. mov bx,offset DXPMCODE:tblRealBad21
  748. @@:
  749. cmp ah,cs:[bx]
  750. je badfunc1
  751. inc bx
  752. cmp byte ptr cs:[bx],0
  753. jz goodfunc1 ; Ran off end of table.
  754. jmp short @b
  755. badfunc1:
  756. if DEBUG
  757. Debug_Out "Unsupported DOS Call! AX=#AX"
  758. endif ;DEBUG
  759. or byte ptr rmflags,1 ; Set CF
  760. call xfrflg
  761. jmp LeaveDOSExtender
  762. goodfunc1:
  763. ; int 21 entry register translations and data transfers
  764. cmp ah,00h ;old style DOS Exit call?
  765. jnz @f
  766. call DosExitCall ;sets CY if it handles the call, otherwise
  767. jnc @f ; do it normally...
  768. jmp LeaveDOSExtender
  769. @@:
  770. ;
  771. ; Handle terminate specially. We mess with the PSP here to set
  772. ; up a terminate vector we like. We don't do anything special for
  773. ; TSR (31h)
  774. ;
  775. cmp ah,4ch ; terminate?
  776. jnz @f
  777. call TerminateProcess
  778. @@:
  779. cmp ah, 5dh ; check for unsupported 5d codes
  780. jnz short @f
  781. cmp al, 0ah
  782. jz short @f
  783. jmp LeaveDOSExtender
  784. @@:
  785. mov rcount,0 ;Default no remaining bytes to read/write
  786. mov ccount,0 ;No bytes read or written yet
  787. cmp ah,3Fh ;If read
  788. jz @f
  789. cmp ah,40h ; or write,
  790. jnz TransferLoop
  791. @@:
  792. mov cx,pmrg.xcx ; initialize remaining count = requested value
  793. mov rcount,cx
  794. ; Start of loop for doing large read/write transfers
  795. TransferLoop:
  796. call dosentry ;Do selector translations, data buffering
  797. ; Come here after entry register translations and data transfers are complete
  798. SwitchToRealMode ;Switch back to real mode. ds = es = rm dgroup
  799. ;Stack is at same place in memory
  800. ; Set registers to possibly translated values and iret to real-mode DOS.
  801. ; DOS then irets to BackFromDOS.
  802. popa ;Set appropriate general register values
  803. pop es
  804. pop ds
  805. public GoingToDOS
  806. GoingToDOS: ;for debugging, etc.
  807. iret ;invoke real mode DOS
  808. assume ds:NOTHING, es:NOTHING, ss:NOTHING
  809. ; Return here from real-mode interrupt handler (DOS)
  810. public BackFromDOS
  811. BackFromDOS:
  812. pushf ;Save return flags (to rmflags)
  813. cld ; (better safe than sorry)
  814. push cs ;Push return cs:ip for multiple xfers
  815. push offset BackFromDOS
  816. sub sp,2*3 ;Bypass room for iret to interrupt handler
  817. ; (to keep stack layout the same as on entry)
  818. push ds ;Save register set
  819. push es
  820. pusha
  821. mov ds,segDXData
  822. assume ds:DGROUP
  823. ; "push" iret frame for real mode int 21 rtn in case we need to do it again
  824. mov ax,rmflags
  825. and ax,not 4300h ;Kill NT, TF, and IF
  826. mov rmivfl,ax
  827. xor ax,ax
  828. mov es,ax
  829. mov ax,word ptr es:[21h*4+2]
  830. mov rmivcs,ax
  831. mov ax,word ptr es:[21h*4]
  832. mov rmivip,ax
  833. ; Switch back to protected mode
  834. SwitchToProtectedMode ;Switch back to protected mode
  835. assume ds:DGROUP,es:DGROUP
  836. FSTI ;Don't need ints disabled
  837. call xfrflg ;Transfer relevant return flags over to pm iret frame
  838. mov ax,pmrg.xax ;Recover AX from caller
  839. ; Perform any int-21 selector translations, data buffering
  840. call dosexit
  841. ; Check for large xfers (Read File 3Fh, Write File 40h, some IOCTL 44h)
  842. cmp rcount,0 ;Read/write more bytes?
  843. jz TransferDone
  844. mov cx,rmrg.xax ;Maybe. cx = count transferred (if 3Fh or 40h)
  845. mov ax,pmrg.xax ;Restore entry code
  846. mov rmrg.xax,ax
  847. cmp ah,40h ;Write?
  848. jnz @f
  849. sub rcount,cx ;Yes. Written all originally requested?
  850. jz TransferDone
  851. cmp cx,rmrg.xcx ; No. Written all last specified?
  852. jz @f ; Yes. Go do some more
  853. mov ax,ccount ;A large write has failed! ccount has already
  854. sub ax,rmrg.xcx ; been updated assuming success, back out the
  855. add ax,cx ; attempted xfer amount, and add in
  856. jmp short TransferCount ; the actual, then split
  857. @@:
  858. jmp TransferLoop ;Yep (or 3Fh or 44h). Do another xfer
  859. TransferDone:
  860. mov ax,ccount ;Multiple count xfer?
  861. or ax,ax
  862. jz LeaveDOSExtender
  863. TransferCount:
  864. mov rmrg.xax,ax ;Yes update return amount
  865. mov ax,pmrg.xcx
  866. mov rmrg.xcx,ax ;Restore initial request count
  867. ; Restore possibly translated registers and to return to pm caller
  868. public LeaveDOSExtender
  869. LeaveDOSExtender:
  870. popa ;Restore possibly changed user registers
  871. mov ss,pmusrss ;Restore pm user stack
  872. mov sp,pmusrsp
  873. assume ss:NOTHING
  874. push pmrg.xds ;push user seg regs on user stack
  875. push pmrg.xes
  876. dec EntryFlag ;dec nested entry flag - normal case is to jmp
  877. jnz NotNested
  878. ;If this was a nested DOS call (from
  879. push cx ; a critical error handler), restore
  880. push si ; the state for the prior DOS call
  881. push di ; which is still in progress
  882. mov cx,ds ;make darn sure es -> DGROUP
  883. mov es,cx
  884. cld ;NOTE: we need to retreive
  885. mov cx,ILENGTH ; all current user registers
  886. mov di,offset DGROUP:Ibegin ; before moving this data
  887. mov si,offset DGROUP:Isave
  888. rep movsb
  889. pop di
  890. pop si
  891. pop cx
  892. NotNested:
  893. pop es ;restore user seg regs
  894. pop ds
  895. assume ds:NOTHING,es:NOTHING
  896. public DOSXiret
  897. DOSXiret: ;for debugging, etc.
  898. iret ;return to caller
  899. PMIntrDos endp
  900. ; -------------------------------------------------------
  901. ; DOSENTRY -- This function performs buffering and register
  902. ; translation for entry into MS-DOS functions.
  903. ;
  904. ; Input: AX: AX value at time of INT 21h
  905. ; Output:
  906. ; Errors:
  907. ; Uses:
  908. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  909. dosentry:
  910. cmp ah,26h ;Create new PSP?
  911. jnz @f
  912. mov si,rmrg.xdx ;yes, translate selector to paragraph
  913. call gtpara
  914. mov rmrg.xdx,ax
  915. return
  916. @@:
  917. cmp ah,53h ;Set drive parameter block?
  918. jnz @f
  919. push ax
  920. mov si,pmrg.xes ;int 21h/53h has an extra parameter in ES:BP
  921. call gtpara ; we change the selector to a segment, but
  922. mov rmrg.xes,ax ; the segment had better already be in
  923. pop ax ; conventional memory
  924. jmp short dentr2b
  925. @@:
  926. cmp ah,50h ;Set current PSP?
  927. jnz dentr1
  928. mov si,rmrg.xbx ;Yes. Translate selector to paragraph
  929. call gtpara
  930. mov rmrg.xbx,ax
  931. return
  932. dentr1: cmp ah,55h ;Duplicate PSP?
  933. jnz dentr2
  934. mov si,rmrg.xbx ;Translate selector bx to paragraph
  935. call gtpara
  936. mov rmrg.xbx,ax
  937. mov si,rmrg.xdx ; and dx also
  938. call gtpara
  939. mov rmrg.xdx,ax
  940. return
  941. dentr2:
  942. cmp ah,56h ;Rename?
  943. jnz dentr2a
  944. push ax ;rename has a second ASCIIZ buffer
  945. push pmrg.xes ; pointed to by es:di -- move that
  946. pop enxseg ; now, the ds:dx one below
  947. mov ax,int21esdi
  948. call gtarea ;let the 'standard' gtarea/movdat
  949. mov dx,enxseg ; routines take care of it
  950. call movdat
  951. pop ax
  952. jmp short dentr2b
  953. dentr2a:
  954. cmp ah,5Fh ;Get/Make Assign-List Entry?
  955. jne dentr2a1
  956. call net5Fenter ; Yes, may require extra buffering
  957. jmp short dentr2b
  958. dentr2a1:
  959. cmp ah,29h ; parse filename?
  960. jne dentr2b
  961. push ax
  962. push pmrg.xes
  963. pop enxseg
  964. mov ax,int21pfn
  965. call gtarea
  966. mov dx,enxseg
  967. call movdat
  968. pop ax
  969. ;; jmp short dentr2b
  970. dentr2b:
  971. call GetEntryCd ;ax = func entry code, di = ptr to entry cd
  972. or ax,ax ;Entry code specify something to do?
  973. rz
  974. cmp byte ptr pmrg.xax+1,1Ah ;Store DTA?
  975. jnz dentr3
  976. mov pmdta,dx ; Yes. Save it for data returns
  977. push pmrg.xds
  978. pop pmdta+2
  979. jmp short dentr4
  980. dentr3: cmp byte ptr pmrg.xax+1,4Bh ;EXEC program?
  981. callz dosxec
  982. ; DENTR4 - enter with ax = entrycd/exitcd. Translate ptr's for real-
  983. ; mode calls and transfer any data indicated.
  984. dentr4: push pmrg.xds
  985. pop enxseg
  986. call gtarea ;Get es:di = area for transfer
  987. rz ;Something to xfer?
  988. mov dx,enxseg ;Yes. Fall thru to movdat
  989. errnz <movdat-$>
  990. ; -------------------------------------------------------
  991. ; MOVDAT -- This routine performs the buffer transfer
  992. ; for entry into or exit from an MS-DOS function. The data
  993. ; is copied from DX:SI to ES:DI. The code in CX determines
  994. ; the type of data being transferred, which is used to determine
  995. ; the length.
  996. ;
  997. ; Input: DX:SI - far pointer to source buffer
  998. ; ES:DI - far pointer to destination buffer
  999. ; CX - transfer length code
  1000. ; Output: none
  1001. ; Errors: none
  1002. ; Uses: AX, BX, CS, SI, DI modified
  1003. assume ds:DGROUP,es:NOTHING,ss:DGROUP
  1004. public movdat
  1005. movdat:
  1006. push ds
  1007. mov bx,cx ;Simple count?
  1008. sub bl,INFO
  1009. jc movda2
  1010. cmp bl,PALETTE-INFO ;Yes. Use pm es?
  1011. jc movda0
  1012. mov dx,pmrg.xes ;Yes
  1013. movda0: mov cl,mvcnt[bx] ;cx = count
  1014. movda1: mov ds,dx
  1015. if DEBUG ;------------------------------------------------------------
  1016. push ax
  1017. mov ax,es
  1018. lsl ax,ax
  1019. sub ax,di
  1020. jc movbad
  1021. cmp ax,cx
  1022. jnc @f
  1023. movbad:
  1024. Debug_Out "Movdat: copy beyond end of dest seg!"
  1025. @@:
  1026. pop ax
  1027. endif ;DEBUG --------------------------------------------------------
  1028. movd1a: rep movsb ;Move data
  1029. pop ds
  1030. return
  1031. movda2: cmp cl,CX$ ;Use pmrg.xcx?
  1032. jnz movda3
  1033. mov cx,rmrg.xcx ;cx usually = pmrg.xcx, but in any event
  1034. ; cx < CB_XFRBUF1
  1035. movd21: add ccount,cx
  1036. jmp short movda1
  1037. movda3: mov ah,0
  1038. cmp cl,ASCZ
  1039. jz movda4
  1040. cmp cl,DOL
  1041. jnz movda5
  1042. mov ah,"$"
  1043. movda4: mov ds,dx
  1044. movd42: lodsb
  1045. stosb
  1046. cmp al,ah
  1047. jnz movd42
  1048. pop ds
  1049. return
  1050. movda5: cmp cl,AX$ ;Use rmrg.xax?
  1051. jnz movda6
  1052. mov cx,rmrg.xax ;Yes (only occurs for ah=3fh - read - on exit)
  1053. jmp short movd21
  1054. movda6:
  1055. cmp cl,FCB
  1056. jnz movda7
  1057. mov ds,dx
  1058. mov cl,byte ptr ds:[si]
  1059. cmp cl,0ffh ;standard or extended FCB?
  1060. mov cx,37 ;standard FCB len
  1061. jnz movd1a
  1062. mov cx,44 ;extended FCB len
  1063. jmp short movd1a
  1064. movda7: ;KYB remains
  1065. pop ds
  1066. return
  1067. ; -------------------------------------------------------
  1068. ; DOSEXIT -- This function is called on exit from the MS-DOS
  1069. ; functions to perform any data buffering and register translation
  1070. ; needed.
  1071. ;
  1072. ; Input: AX: AX value at time of INT 21h
  1073. ; Output:
  1074. ; Errors:
  1075. ; Uses:
  1076. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1077. public dosexit
  1078. dosexit:
  1079. cmp ah,51h ;Get current PSP?
  1080. jz dose0a
  1081. cmp ah,62h ;Get PSP address?
  1082. jnz dose00
  1083. dose0a:
  1084. mov ax,rmrg.xbx ;Yes. Translate segment to selector
  1085. mov bx,STD_DATA
  1086. call ParaToLDTSelector
  1087. mov rmrg.xbx,ax
  1088. return
  1089. dose00: cmp ah,2fh ;Get current DTA?
  1090. jnz dose01
  1091. mov ax,pmdta ;Yes. Load PM DTA into caller's registers
  1092. mov rmrg.xbx,ax
  1093. mov ax,pmdta+2
  1094. verr ax ; if the dta selector is no longer valid,
  1095. jz @f ; return the NULL selector instead (so we
  1096. xor ax,ax ; don't GP fault in DOSX).
  1097. @@: mov pmrg.xes,ax
  1098. return
  1099. dose01: cmp ah,55h ;Duplicate PSP?
  1100. jnz dosex1
  1101. mov ax,rmrg.xbx ;Yes, translate segments to selectors
  1102. mov bx,STD_DATA
  1103. call ParaToLDTSelector
  1104. mov rmrg.xbx,ax
  1105. mov ax,rmrg.xdx
  1106. mov bx,STD_DATA
  1107. call ParaToLDTSelector
  1108. mov rmrg.xdx,ax
  1109. return
  1110. dosex1: cmp ah,56h ;Rename?
  1111. jnz dosex2
  1112. push pmrg.xdi ;Rename has a second pointer in ES:DI--we
  1113. pop rmrg.xdi ; need to restore DI here, DX below
  1114. jmp short dosex3
  1115. dosex2: cmp ah,5Fh ;Get/Make Assign-List Entry?
  1116. callz net5Fexit ; Yes, extra buffering may be needed
  1117. dosex3:
  1118. call GetEntryCd ;ax=func entry code, di=ptr to entry code
  1119. call rstreg ;Restore entry register?
  1120. jz dosex6
  1121. cmp byte ptr pmrg.xax+1,29h ;Yes, Parse filename?
  1122. jnz dosex4
  1123. add ax,rmrg.xsi ;Yes. Increment past string
  1124. sub ax,offset DGROUP:rgbXfrBuf0 ; that was parsed
  1125. push pmrg.xdi
  1126. pop rmrg.xdi ;Restore pm di (for es:di ptr)
  1127. dosex4: mov word ptr rmrg[si],ax ;Restore register
  1128. cmp byte ptr pmrg.xax+1,4Bh ;EXEC program
  1129. jnz dosex6
  1130. push di
  1131. mov di,pmrg.xbx ;Yes, restore bx too (dx restored above)
  1132. mov rmrg.xbx,di ;es and ds are restored automatically
  1133. cmp byte ptr pmrg.xax,1 ;INT-21/4b01h (undocumented debug)?
  1134. jnz @f
  1135. mov si,npXfrBuf1 ;Yes. Pass back user ss:sp and cs:ip
  1136. lea si,[si].xsssp
  1137. lea di,[di].xsssp
  1138. mov es,pmrg.xes
  1139. movsw ;Move ss:sp
  1140. movsw
  1141. movsw ;Move cs:ip
  1142. movsw
  1143. @@:
  1144. pop di
  1145. dosex6: mov ax,cs:[di+2] ;Exit xfer?
  1146. or ax,ax
  1147. rz
  1148. dosex7: call CheckStatus ;Check the DOS return status to see if the
  1149. rnz ; data should be transfered back to PM
  1150. mov cx,ax ;Is a pointer being returned? (no data
  1151. and cl,0fh ; transfer)
  1152. cmp cl,PTR$
  1153. jnz dosex8
  1154. shr al,4 ; yes, isolate pointer type
  1155. mov si,offset rmrg.xds
  1156. mov di,offset pmrg.xds
  1157. cmp al,DSBX
  1158. jz dosex7a
  1159. ifdef DBCS ; for function 63h (Get Lead Byte)
  1160. cmp al,DSSI
  1161. jz dosex7a
  1162. endif ; DBCS
  1163. mov si,offset rmrg.xes
  1164. mov di,offset pmrg.xes
  1165. dosex7a:
  1166. mov ax,[si] ; get a selector for the segment, and
  1167. mov bx,STD_DATA ; setup to return it to caller
  1168. call ParaToLDTSelector
  1169. mov [di],ax
  1170. return
  1171. dosex8:
  1172. push pmrg.xds
  1173. pop enxseg
  1174. call gtarea ;Get area for xfer from PM to DOS
  1175. rz ;Something to move?
  1176. xchg si,di ;Turn pointers around
  1177. mov dx,ds ;dx:si -> DOS xfer area in dgroup
  1178. mov es,enxseg ;es:di -> PM-caller data area
  1179. jmp movdat ;Yes
  1180. ; -------------------------------------------------------
  1181. ; DosExitCall -- Special processing for DOS exit call service (Int 21h/00h)
  1182. ;
  1183. ; This procedure handles the obsolete Int 21h/00h terminate process
  1184. ; call in a special slimy way for Windows. Instead of doing a 00h
  1185. ; DOS call in real mode, it hacks up the parent's PSP and does a 4Ch
  1186. ; that causes control to return to the extender, who then RETURNS TO
  1187. ; THE CALLER!!! The caller must then do appropriate set PSP calls, etc.
  1188. ; This was implemented so pMode Windows kernel could have DOS clean up
  1189. ; after a Windows app terminates, but still have kernel get control
  1190. ; back.
  1191. ;
  1192. ; Note: This code assumes that the Parent PID field contains a
  1193. ; SELECTOR!
  1194. ;
  1195. ; Note^2: If for some reason it's the DOS Extender's child that's 1800doing
  1196. ; the terminate call, we let it go through normally.
  1197. ;
  1198. ; Input: none
  1199. ; Output: CY set if exit call processed by this routine, clear otherwise
  1200. ; Errors:
  1201. ; Uses: none
  1202. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1203. public DosExitCall
  1204. DosExitCall proc near
  1205. push ax
  1206. push bx
  1207. push dx
  1208. push es
  1209. SwitchToRealMode ;much of this is easier in real mode
  1210. FSTI ;allow interrupts
  1211. mov ah,51h ;get PSP of current task
  1212. pushf
  1213. FCLI
  1214. sub sp,8 ; make room for stack frame
  1215. push bp
  1216. mov bp,sp
  1217. push es
  1218. push ax
  1219. xor ax,ax
  1220. mov es,ax
  1221. mov [bp + 8],cs
  1222. mov [bp + 6],word ptr (offset dec_10)
  1223. mov ax,es:[21h*4]
  1224. mov [bp + 2],ax
  1225. mov ax,es:[21h*4 + 2]
  1226. mov [bp + 4],ax
  1227. pop ax
  1228. pop es
  1229. pop bp
  1230. retf
  1231. dec_10: cmp bx,segPSPChild ;is this our child terminating?
  1232. jnz @f ;if not, go process the call ourselves
  1233. jmp decTermChild ; yes...
  1234. @@:
  1235. FCLI ;we want to preserve the current
  1236. xor ax,ax ; rMode Int 24h handler across this
  1237. mov es,ax ; exit call (the terminating PSP
  1238. mov ax,es:[24h*4] ; has the pMode handler address).
  1239. mov dx,es:[24h*4+2] ; So get the current Int 24h handler
  1240. FSTI ; address from the rMode IDT.
  1241. mov es,bx ;address terminating PSP
  1242. assume es:PSPSEG
  1243. mov word ptr [lpfnInt24],ax ;point PSP to same Int 24h
  1244. mov word ptr [lpfnInt24+2],dx ; handler
  1245. mov ax,offset DXCODE:decTermHandler ;point PSP to our termination
  1246. mov word ptr [lpfnParent],ax ; handler
  1247. mov word ptr [lpfnParent+2],cs
  1248. push es
  1249. mov ax,segParentPSP ;Windows has the PSP's parent
  1250. push ax ; field as a selector, we need the seg
  1251. mov dx, [segEnviron]
  1252. push dx
  1253. SwitchToProtectedMode
  1254. assume ds:DGROUP,es:DGROUP
  1255. FSTI
  1256. pop ax ;get selector for environment
  1257. or ax,ax ; NULL selector (krnl386 does this)
  1258. jnz @f
  1259. xor bx,bx ; zero environment segment
  1260. jmp dec_HaveEnvSeg
  1261. @@:
  1262. call GetSegmentAddress
  1263. test bx,0fff0h ; >1mb?
  1264. jz @f ; no
  1265. xor bx,bx ; yes, zero environment segment
  1266. xor dx,dx
  1267. @@:
  1268. shr dx, 4
  1269. shl bx, 12
  1270. or bx, dx ;seg of environment
  1271. dec_HaveEnvSeg:
  1272. pop ax ;get parent psp off stack
  1273. push bx ;save seg of environment
  1274. call GetSegmentAddress ;returns BX:DX = lma of segment
  1275. shr dx,4
  1276. shl bx,12
  1277. or bx,dx ;bx now = seg of parent psp
  1278. SwitchToRealMode ;back to the shadows again...
  1279. FSTI
  1280. pop cx ;seg of environment
  1281. pop dx ;terminating PSP segment from stack
  1282. mov es,bx ;address the parent's PSP
  1283. assume es:PSPSEG
  1284. mov ax,sp
  1285. sub ax,12*2 ;some magic for DOS
  1286. mov word ptr [lpStack],ax ;set our stack in parent's PSP
  1287. mov word ptr [lpStack+2],ss
  1288. mov es,dx ;(re)address terminating PSP
  1289. assume es:PSPSEG
  1290. mov [segEnviron], cx
  1291. mov segParentPSP,bx ;real DOS doesn't like selectors in
  1292. ; parent PSP field, zap it to segment
  1293. mov ax,pmrg.xax ;terminate the process
  1294. mov ah,4Ch ; with a 4Ch DOS call
  1295. pushf
  1296. FCLI
  1297. sub sp,8 ; make room for stack frame
  1298. push bp
  1299. mov bp,sp
  1300. push es
  1301. push ax
  1302. xor ax,ax
  1303. mov es,ax
  1304. mov [bp + 8],cs
  1305. mov word ptr [bp + 6],offset decTermHandler
  1306. mov ax,es:[21h*4]
  1307. mov [bp + 2],ax
  1308. mov ax,es:[21h*4 + 2]
  1309. mov [bp + 4],ax
  1310. pop ax
  1311. pop es
  1312. pop bp
  1313. retf
  1314. assume ds:NOTHING,es:NOTHING,ss:NOTHING ;play it safe
  1315. decTermHandler: ;should return back here
  1316. push ss
  1317. pop ds
  1318. SwitchToProtectedMode ;back to pMode
  1319. assume ds:DGROUP,es:DGROUP
  1320. FSTI
  1321. les bx,dword ptr pmusrsp ;es:bx -> ip cs flag
  1322. and byte ptr es:[bx+2*2],not 1 ;clear CY in caller's flags
  1323. stc ;exit call has been processed
  1324. dec90:
  1325. pop es
  1326. pop dx
  1327. pop bx
  1328. pop ax
  1329. ret
  1330. EndHighSegment
  1331. BeginLowSegment
  1332. decTermChild:
  1333. SwitchToProtectedMode
  1334. assume ds:DGROUP,es:DGROUP
  1335. FSTI
  1336. clc
  1337. jmp short dec90
  1338. DosExitCall endp
  1339. ; -------------------------------------------------------
  1340. ; net5Fenter -- Additional entry processing for INT 21h/5Fh
  1341. ; functions.
  1342. ;
  1343. ; INT 21h/5Fh subfunctions 2, 3, and 5 have two buffers of data to
  1344. ; transfer. The normal DOSENTRY processing only does one, so we
  1345. ; setup the other buffer here.
  1346. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1347. public net5Fenter
  1348. net5Fenter proc near
  1349. cmp al,2 ;This routine only works on
  1350. rc ; subfunctions 2, 3, and 5
  1351. cmp al,4
  1352. rz
  1353. cmp al,6
  1354. rnc
  1355. push ax
  1356. mov ax,int21esdi ;entry code for INT 21h/5Fh extra buff
  1357. call gtarea ;let gtarea set it up
  1358. pop ax
  1359. cmp al,3 ;Make redirection function?
  1360. rnz
  1361. ; 5F/03 needs a buffer copied down to A1, but it's non standard in that
  1362. ; the buffer contains two (count'em 2) asciiz strings
  1363. push ax
  1364. push cx
  1365. push ds
  1366. mov ds,pmrg.xes ;user's ES:DI -> buffer, gtarea sets
  1367. xor ah,ah ; up our si to have user's di
  1368. mov cl,2
  1369. @@: lodsb ;copy one asciiz string
  1370. stosb
  1371. cmp al,ah
  1372. jnz @b
  1373. dec cl ; and then the other
  1374. jnz @b
  1375. pop ds
  1376. pop cx
  1377. pop ax
  1378. return
  1379. net5Fenter endp
  1380. ; -------------------------------------------------------
  1381. ; net5Fexit -- Additional exit processing for INT 21h/5Fh
  1382. ; functions.
  1383. ;
  1384. ; INT 21h/5Fh subfunctions 2, 3, & 5 have 2 buffers of data to transfer.
  1385. ; The normal DOSENTRY processing only does one, so do the other
  1386. ; buffer here.
  1387. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1388. public net5Fexit
  1389. net5Fexit proc near
  1390. cmp al,2 ;This routine only works on
  1391. rc ; subfunctions 2, 3 and 5
  1392. cmp al,4
  1393. rz
  1394. cmp al,6
  1395. rnc
  1396. push pmrg.xdi ;Restore protected mode DI register
  1397. pop rmrg.xdi
  1398. cmp al,2 ;Get redirection function?
  1399. jz @f
  1400. cmp al,5
  1401. rnz
  1402. @@:
  1403. ; 5F/02 & 05 need a buffer copied from A1
  1404. test byte ptr rmflags,1 ;Success? (carry flag)
  1405. rnz ; No, don't transfer anything
  1406. push ax
  1407. mov ax,int21esdi+2 ;exit code for int 21/5F extra buffer
  1408. push pmrg.xes
  1409. pop enxseg
  1410. call gtarea ;let gtarea setup the move
  1411. xchg si,di
  1412. mov dx,ds
  1413. mov es,enxseg
  1414. call movdat ; and let movdat move it
  1415. pop ax
  1416. return
  1417. net5Fexit endp
  1418. ; -------------------------------------------------------
  1419. ; RSTREG -- This function sets up to restore the original
  1420. ; protected-mode registers. This cleans up after register
  1421. ; translations performed when going into the or returning
  1422. ; from an MS-DOS call. On entry, AX contains the entry code
  1423. ; value from the entry/exit operations table. If this code
  1424. ; implies that a register needs to be restored this function
  1425. ; will return with NZ true and AX = original register value
  1426. ; and SI pointing to the appropriate location in the PMRG array.
  1427. ; If no register needs to be restored, return with Z true.
  1428. ;
  1429. ; Input: AX - entry code value
  1430. ; Output: NZ true if register needs to be restores
  1431. ; AX - register value to restore
  1432. ; SI - pointer into PMRG to the register image
  1433. ; ZR true if no restoration needed
  1434. ; Errors: none
  1435. ; Uses: AX, SI modified
  1436. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1437. public rstreg
  1438. rstreg: or ax,ax
  1439. rz
  1440. shr ax,3
  1441. and ax,1Eh
  1442. rz
  1443. cmp al,2*DTA ;DTA?
  1444. rz
  1445. xchg si,ax ;No. Restore appropriate register, e.g., dx
  1446. mov si,regoffs[si-2]
  1447. mov ax,word ptr pmrg[si]
  1448. return
  1449. ; -------------------------------------------------------
  1450. ; GTAREA -- This function examines the entry code/exit code
  1451. ; parameter and determines if any data transfer needs to be
  1452. ; performed. If so, it sets up pointers and length codes for
  1453. ; the transfer.
  1454. ; There are two transfer buffers used. The A0 buffer is 60h bytes
  1455. ; long and the A1 buffer is CB_XFRBUF1 bytes (about 4k) long.
  1456. ;
  1457. ; Input: AX - entry code/exit code
  1458. ; Output: NZ true if something needs to be transferred
  1459. ; SI - offset of source pointer
  1460. ; DI - offset of destination pointer
  1461. ; ENXSEG - segment for caller's buffer
  1462. ; (source on entry, destination on exit)
  1463. ; CX - transfer length/type code
  1464. ; Errors: none
  1465. ; Uses: AX, CX, SI, DI, ES modified
  1466. ; ENXSEG modified
  1467. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1468. public gtarea
  1469. gtarea:
  1470. test ah,RP ;Real/PM xfer (ah = 3f/40)?
  1471. jz gtare2
  1472. mov si,pmrg.xds ;Yes. *si:pmrg.xdx = pm caller's xfer area
  1473. and si,SELECTOR_INDEX
  1474. test ah,EX ;Exit call?
  1475. jz gtare1
  1476. push es
  1477. push ax
  1478. mov es,selGDT
  1479. mov al,es:[si].adrBaseHigh
  1480. mov ah,es:[si].adrbBaseHi386
  1481. test ax,0FFF0h ; check for transfer to extended
  1482. ; memory
  1483. pop ax
  1484. pop es
  1485. jnz @f
  1486. jmp gtar54
  1487. @@:
  1488. mov cx,rmrg.xax ;Yes. cx = amount read/written
  1489. sub rcount,cx ;Update remaining count
  1490. cmp cx,rmrg.xcx ;All that was requested?
  1491. jnc gtare3
  1492. mov rcount,0 ;No: done
  1493. jmp short gtare3
  1494. gtare1: push ax ;Read/Write entry
  1495. mov ax,si
  1496. mov dx,pmrg.xdx ;ax:dx = selector:offset of buffer
  1497. call SelOff2SegOff ;translate to seg:off if in conventional mem
  1498. jnz gtar12
  1499. mov rmrg.xds,ax ;store corresponding paragraph
  1500. mov rmrg.xdx,dx ; and offset
  1501. pop ax
  1502. jmp short gtar54 ;No more setup needed
  1503. gtar12: pop ax ;XRAM/RRAM read/write entry
  1504. mov cx,rcount ;Try to xfer remaining amount
  1505. cmp cx,CB_XFRBUF1 ;Too much to fit in buffer?
  1506. jbe gtar14
  1507. mov cx,CB_XFRBUF1 ;Yes, only transfer a buffer size
  1508. gtar14: mov rmrg.xcx,cx
  1509. jmp short gtare3
  1510. gtare2: test ah,A0+A1 ;xfer area?
  1511. jz gtare4
  1512. gtare3: mov di,offset DGROUP:rgbXfrBuf0 ;Point at small buffer (90h bytes)
  1513. test ah,1 ;Area 0 (small area) ?
  1514. jnz gtare4
  1515. mov di,npXfrBuf1 ;No. Point at large buffer (4K)
  1516. gtare4: push ax ;Store ptr to communication area for DOS
  1517. mov si,di
  1518. shr al,3 ;Get al = 2 * data ptr type, e.g., DSDX (ds:dx)
  1519. and al,1Eh ;al = word offset for data ptr type
  1520. jz gtare7
  1521. cmp al,2*DTA ;DOS Data Transfer Area?
  1522. jnz gtare5
  1523. mov si,pmdta ;Yes, load DTA offset
  1524. push pmdta+2 ;and the segment
  1525. pop enxseg
  1526. jmp short gtare7
  1527. gtare5: cmp al,2*ES$
  1528. jnz gtare6
  1529. test ah,80h ;INT-21 49/4A. Ignore exit call
  1530. mov ax,0
  1531. jnz gtar52
  1532. mov si,pmrg.xes ;Entry call. si = RAM xfer selector
  1533. call gtpara ;Get paragraph given by [si].gdt
  1534. jnz gtar52 ;XRAM?
  1535. mov rmrg.xes,ax ;No, store RRAM paragraph
  1536. gtar52: pop cx ;Kill saved ptr
  1537. gtar54: xor cx,cx ;RZ with zero count, i.e., no RM/PM xfer needed
  1538. mov rcount,cx
  1539. return
  1540. gtare6: test ah,80h ;Entry?
  1541. cbw
  1542. push ax
  1543. xchg di,ax ;Save real-mode area offset
  1544. mov di,regoffs[di-2] ;di = offset of saved register value
  1545. mov si,word ptr pmrg[di] ;si = saved value
  1546. jnz gtar62
  1547. mov word ptr rmrg[di],ax ;Entry. Store real-mode area offset
  1548. cmp byte ptr pmrg.xax+1,29h ;Parse filename?
  1549. jnz gtar62
  1550. mov cx,npXfrBuf1 ;Yes. Use npXfrBuf1 for FCB info
  1551. mov word ptr rmrg.xdi,cx
  1552. gtar62: xchg di,ax ;Restore di = real-mode area offset
  1553. pop ax
  1554. cmp ax,ESDI*2
  1555. jne gtare7
  1556. push pmrg.xes
  1557. pop enxseg
  1558. gtare7: pop cx ;Recover entrycd/exitcd
  1559. and cx,0Fh ;RNZ if something to xfer
  1560. rz ;No
  1561. mov dx,pmrg.xds ;Xfer needed. dx = original XRAM data selector
  1562. cmp cl,AX$ ;Use rmrg.xax?
  1563. jz gtare8
  1564. cmp cl,CX$ ;Use pmrg.xcx?
  1565. rnz ;No, just RNZ
  1566. ;Return dx:0 = pmrg.xds:si+ccount, where dx is a scratch selector
  1567. ;and si = 0. This ensures that dx:si can address a bufferful of bytes
  1568. ;without overflowing si (sort of like a huge ptr).
  1569. gtare8: xchg ax,si ;ax = original offset
  1570. mov si,dx ;si = pmrg.xds (PM data selector)
  1571. and si,SELECTOR_INDEX
  1572. xor dx,dx ;dxax = original offset in 32-bit form
  1573. add ax,ccount
  1574. adc dx,0 ;dxax += ccount (current xfer count)
  1575. push es
  1576. mov es,selGDT ;Point at GDT
  1577. add ax,es:[si].adrBaseLow
  1578. adc dl,es:[si].adrBaseHigh ;dxax absolute XRAM address
  1579. adc dh,es:[si].adrbBaseHi386
  1580. mov si,SEL_DOSSCR
  1581. cCall NSetSegmentDscr,<si,dx,ax,0,0ffffh,STD_DATA>
  1582. pop es
  1583. ; original code... changed to line below to fix file read problem.
  1584. ; may cause other bugs.....
  1585. ; mov dx,si ;Return scratch selector with 0 offset since
  1586. ;
  1587. or si,SELECTOR_TI
  1588. mov enxseg,si ;Return scratch selector with 0 offset since
  1589. xor si,si ; it points directly to the transfer location
  1590. or sp,sp ;RNZ to indicate xfer needed
  1591. return
  1592. ; -------------------------------------------------------
  1593. ; GetEntryCd -- This routine puts the entry code for the
  1594. ; DOS function into ax.
  1595. ;
  1596. ; Input: AH - MS-DOS function number
  1597. ; Output: AX - entry code for function
  1598. ; DI - address of entry code returned
  1599. ;
  1600. ; Errors: none
  1601. ; Uses: AX, DI modified
  1602. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1603. public GetEntryCd
  1604. GetEntryCd proc near
  1605. push bx
  1606. cmp ah,MaxInt21 ;Check for unsupported DOS call
  1607. jbe @f
  1608. mov di,offset DXPMCODE:Unsupported
  1609. jmp gec90
  1610. @@:
  1611. mov di,offset DXPMCODE:pmrmxfr
  1612. ifdef DBCS
  1613. cmp ah,63h ;Get Lead Byte Table?
  1614. jnz gec10
  1615. if DEBUG ;------------------------------------------------------------
  1616. cmp al,2
  1617. jbe gec15
  1618. Debug_Out "Int 21h/63h Unsupported Function (#AX)"
  1619. jmp short gec80
  1620. gec15:
  1621. endif ;DEBUG --------------------------------------------------------
  1622. cmp al,0 ;Int 21/63/00 is special
  1623. jne gec80
  1624. mov di,offset DXPMCODE:int2163
  1625. jmp short gec90
  1626. gec10:
  1627. ENDIF ; DBCS
  1628. gec20: cmp ah,5Eh ;Network Machine Name/Printer Setup Str?
  1629. jnz gec40
  1630. if DEBUG ;------------------------------------------------------------
  1631. cmp al,3
  1632. jna gec25
  1633. Debug_Out "Int 21h/5Eh Unsupported Function (#AX)"
  1634. jmp short gec80
  1635. gec25:
  1636. endif ;DEBUG --------------------------------------------------------
  1637. cmp al,3 ;Int 21-5E/00-03 are special
  1638. ja gec80
  1639. mov bl,al
  1640. mov di,offset DXPMCODE:int215E
  1641. jmp short gec85
  1642. gec40: cmp ah,5Fh ;Get/Make Assign-List Entry?
  1643. jnz gec80
  1644. if DEBUG ;------------------------------------------------------------
  1645. cmp al,5
  1646. ja @f
  1647. cmp al,2
  1648. jnb gec45
  1649. @@:
  1650. cmp al,30h ;Register based. Get Redirector version
  1651. ;used by Lanman Enhanced.
  1652. je gec80
  1653. Debug_Out "Int 21h/5Fh Unsupported Function (#AX)"
  1654. jmp short gec80
  1655. gec45:
  1656. endif ;DEBUG --------------------------------------------------------
  1657. cmp al,2 ;Int 21/5F/02-05 are special
  1658. jb gec80
  1659. cmp al,5
  1660. ja gec80
  1661. mov bl,al
  1662. sub bl,2
  1663. mov di,offset DXPMCODE:int215F02
  1664. jmp short gec85
  1665. gec80: mov bl,ah
  1666. gec85: xor bh,bh
  1667. shl bx,2
  1668. add di,bx ;Address of entry code
  1669. gec90:
  1670. mov ax,word ptr cs:[di] ;The entry code itself
  1671. pop bx
  1672. return
  1673. GetEntryCd endp
  1674. ; -------------------------------------------------------
  1675. ; CheckStatus -- This routine determines if data should be copied
  1676. ; back to protect mode by checking the DOS function
  1677. ; return status.
  1678. ;
  1679. ; Input: none
  1680. ; Output: NZ - if data should NOT be copied, Z otherwise
  1681. ;
  1682. ; Errors: none
  1683. ; Uses: none
  1684. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1685. public CheckStatus
  1686. CheckStatus proc near
  1687. ; For now, only worry about the functions that return variable length
  1688. ; results, like ASCIIZ strings.
  1689. cmp byte ptr pmrg.xax+1,32h
  1690. jz @f
  1691. cmp byte ptr pmrg.xax+1,47h ;Get Current Directory
  1692. jz @f
  1693. cmp byte ptr pmrg.xax+1,5Ah ;Create Temporary File
  1694. jz @f
  1695. cmp byte ptr pmrg.xax+1,5Eh ;Get Machine Name/Printer Str
  1696. jc cks90
  1697. cmp byte ptr pmrg.xax+1,5Fh ;Get Redirection Entry
  1698. ja cks90
  1699. @@:
  1700. test byte ptr rmflags,1 ;Carry set?
  1701. return
  1702. cks90: cmp al,al ;Assume status is okay (or doesn't
  1703. return ; matter) -- set Z and return
  1704. CheckStatus endp
  1705. ; -------------------------------------------------------
  1706. ; DOSXEC -- This function performs the transfer of the
  1707. ; DOS exec parameter block on entry to DOS function 4Bh.
  1708. ;
  1709. ; transfer int-21 ah = 4b0x EXEC block and associated strings
  1710. ; to Area 1. This area is laid out partly analogously to a PSP as follows:
  1711. ;
  1712. ; 0-1f EXEC block defined according to the execblk struc above
  1713. ; 20-2f FCB1
  1714. ; 30-3f FCB2
  1715. ; 40-bf command line
  1716. ;
  1717. ; cx, si, di changed.
  1718. assume ds:DGROUP,es:DGROUP,ss:DGROUP
  1719. public dosxec
  1720. dosxec:
  1721. push ax ;Save entrcd code
  1722. push bx
  1723. push dx
  1724. mov cx,10h ;Setup parameter block. Xfer pm user block first
  1725. mov bx,npXfrBuf1 ;Point at larger buffer
  1726. mov di,bx
  1727. mov dx,segDXDataPM
  1728. mov rmrg.xbx,di ;int-21 4b0x expects es:bx -> exec block
  1729. mov si,pmrg.xbx ;npXfrBuf1:0 - 1f (xtra room for undocumented)
  1730. mov ds,pmrg.xes
  1731. rep movsw ;copy caller's exec param block to our buffer
  1732. ; Copy FCB1 down if the user has specified one.
  1733. dsxc20: mov ax,word ptr es:[bx].fcb1ptr
  1734. cmp ax,0FFFFh
  1735. jz dsxc22
  1736. or ax,word ptr es:[bx].fcb1ptr+2
  1737. jz dsxc22
  1738. lds si,es:[bx].fcb1ptr ;Get pointer to FCB1
  1739. mov word ptr es:[bx].fcb1ptr,di ;store new pointer in the copy of the
  1740. mov word ptr es:[bx].fcb1ptr+2,dx ; exec block we are building
  1741. mov cl,8 ;copy FCB1 down to our buffer
  1742. rep movsw
  1743. jmp short dsxc24
  1744. dsxc22: add di,10h
  1745. ; Copy FCB2 down if the user has specified one.
  1746. dsxc24: mov ax,word ptr es:[bx].fcb2ptr
  1747. cmp ax,0FFFFh
  1748. jz dsxc26
  1749. or ax,word ptr es:[bx].fcb2ptr+2
  1750. jz dsxc26
  1751. lds si,es:[bx].fcb2ptr ;Move FCB2
  1752. mov word ptr es:[bx].fcb2ptr,di
  1753. mov word ptr es:[bx].fcb2ptr+2,dx
  1754. mov cl,8
  1755. rep movsw
  1756. jmp short dsxc30
  1757. dsxc26: add di,10h
  1758. ; Copy the command line down.
  1759. dsxc30: lds si,es:[bx].cmdptr ;Move command line
  1760. mov word ptr es:[bx].cmdptr,di
  1761. mov word ptr es:[bx].cmdptr+2,dx
  1762. mov cl,[si]
  1763. inc cx ;Include count
  1764. inc cx ;Include final CR not included in count
  1765. rep movsb
  1766. ; Now, we need to set up the enviroment table to be passed to the
  1767. ; child program.
  1768. mov di,bx ;di = npXfrBuf1
  1769. mov dx,es:[di] ;Setup desired environment
  1770. or dx,dx ;Use parent's environment?
  1771. jnz dosxegotenv
  1772. ; pick up the environment segment from the current PDB. It's a selector,
  1773. ; so it has to be translated.
  1774. push bx
  1775. push di
  1776. push es
  1777. mov ax,SEL_DXDATA OR STD_RING
  1778. mov ds,ax
  1779. SwitchToRealMode ;much of this is easier in real mode
  1780. mov ah,51h ;get PSP of current task
  1781. pushf
  1782. sub sp,8 ; make room for stack frame
  1783. push bp
  1784. mov bp,sp
  1785. push es
  1786. push ax
  1787. xor ax,ax
  1788. mov es,ax
  1789. mov [bp + 8],cs
  1790. mov [bp + 6],word ptr (offset dosxeret)
  1791. mov ax,es:[21h*4]
  1792. mov [bp + 2],ax
  1793. mov ax,es:[21h*4 + 2]
  1794. mov [bp + 4],ax
  1795. pop ax
  1796. pop es
  1797. pop bp
  1798. retf
  1799. dosxeret:
  1800. assume es:PSPSEG
  1801. mov es, bx ;current PSP
  1802. mov dx, es:[segEnviron] ;get environment (currently selector)
  1803. push dx ;save over call (bugbug is this needed?)
  1804. SwitchToProtectedMode
  1805. pop dx ;bugbug is this needed?
  1806. pop es
  1807. pop di
  1808. pop bx
  1809. dosxegotenv:
  1810. xor si,si ;No. Setup to copy desired environment down
  1811. mov ds,dx ;ds = dx has caller's selector. Use 0 offset
  1812. add di,100h
  1813. shr di,4 ;Convert offset to paragraph
  1814. mov dx,segDXDataPM
  1815. add dx,di ;dx = absolute paragraph within larger buffer
  1816. shl di,4 ;Convert back (with low nibble cleared)
  1817. mov cx,CB_XFRBUF1 ;Max room available for environment
  1818. sub cx,100h
  1819. dosxe2: lodsw ;Copy environment down
  1820. stosw
  1821. or ax,ax
  1822. jz dosxe4
  1823. dec si ;Check every byte offset in environment for double 0
  1824. dec di
  1825. loop dosxe2
  1826. xor dx,dx ;Environment too large for buffer: use parent's
  1827. ;Issue error message? Program might run with parent's
  1828. ; and not with desired monster environment
  1829. dosxe4: push es ;Fix up parameter block entry
  1830. pop ds ;ds:dgroup
  1831. mov [bx].evrnmt,dx
  1832. pop dx
  1833. pop bx
  1834. pop ax ;Restore entrcd code
  1835. return
  1836. ; -------------------------------------------------------
  1837. ; XFRFLG -- This function will transfer the relevant real-mode
  1838. ; flags to the protected mode IRET return information on the
  1839. ; stack for returning to the protected mode caller.
  1840. ;
  1841. ; Input:
  1842. ; Output:
  1843. ; Errors:
  1844. ; Uses: AX, CX, DI modified
  1845. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1846. public xfrflg
  1847. xfrflg: push es
  1848. les di,dword ptr pmusrsp ;es:[di] = ip cs fl (assume 80286)
  1849. mov ax,rmflags
  1850. mov cx,es:[di+2*2] ;Get pm user entry flags
  1851. and ch,not 19h ;Only allow real-mode program to
  1852. and ah,18h ; change OF and DF in high byte of flags
  1853. or ah,ch
  1854. mov es:[di+2*2],ax
  1855. pop es
  1856. return
  1857. ; -------------------------------------------------------
  1858. subttl Handlers for Special Case Dos Functions
  1859. page
  1860. ; -------------------------------------------------------
  1861. ; HANDLERS FOR SPECIAL CASE DOS FUNCTIONS
  1862. ; -------------------------------------------------------
  1863. ; -------------------------------------------------------
  1864. ; Terminate process -- This routine replaces the apps
  1865. ; termination vector in the PSP with ours. This allows
  1866. ; us to clean up the dos extender.
  1867. ;
  1868. ; Entry: nothing
  1869. ; Exit: nothing
  1870. ; Uses: none
  1871. ;
  1872. assume ds:dgroup,es:nothing
  1873. public TerminateProcess
  1874. TerminateProcess proc near
  1875. pusha
  1876. push es
  1877. ;
  1878. ; Get the childs PSP (bugbug do we need to get the current psp?)
  1879. ;
  1880. SwitchToRealMode
  1881. mov ah,51h
  1882. pushf
  1883. sub sp,8 ; make room for stack frame
  1884. push bp
  1885. mov bp,sp
  1886. push es
  1887. push ax
  1888. xor ax,ax
  1889. mov es,ax
  1890. mov [bp + 8],cs
  1891. mov [bp + 6],offset tp_10
  1892. mov ax,es:[21h*4]
  1893. mov [bp + 2],ax
  1894. mov ax,es:[21h*4 + 2]
  1895. mov [bp + 4],ax
  1896. pop ax
  1897. pop es
  1898. pop bp
  1899. retf
  1900. tp_10: FSTI
  1901. ;
  1902. ; Change the termination vector to point to the dos extender
  1903. ;
  1904. mov es,bx
  1905. mov bx,es:[0ah]
  1906. mov ax,es:[0ch]
  1907. mov cx,offset ChildTerminationHandler
  1908. mov es:[0ah],cx
  1909. mov cx,segDXCode
  1910. mov es:[0ch],cx
  1911. ;
  1912. ; Save the old termination vector for restoration later
  1913. ;
  1914. mov cx,segCurrentHostData
  1915. mov es,cx
  1916. mov word ptr es:[HdPspTerminate],bx
  1917. mov word ptr es:[HdPspTerminate+2],ax
  1918. SwitchToProtectedMode
  1919. pop es
  1920. popa
  1921. ret
  1922. TerminateProcess endp
  1923. DXPMCODE ends
  1924. ;****************************************************************
  1925. end